sflkit 0.5.3__tar.gz → 0.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. {sflkit-0.5.3/src/sflkit.egg-info → sflkit-0.5.4}/PKG-INFO +1 -1
  2. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/__init__.py +1 -1
  3. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/factory.py +63 -22
  4. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/meta.py +5 -2
  5. sflkit-0.5.4/src/sflkit/model/scope.py +82 -0
  6. {sflkit-0.5.3 → sflkit-0.5.4/src/sflkit.egg-info}/PKG-INFO +1 -1
  7. sflkit-0.5.4/tests/test_scope.py +43 -0
  8. sflkit-0.5.3/src/sflkit/model/scope.py +0 -39
  9. sflkit-0.5.3/tests/test_scope.py +0 -20
  10. {sflkit-0.5.3 → sflkit-0.5.4}/LICENSE +0 -0
  11. {sflkit-0.5.3 → sflkit-0.5.4}/README.md +0 -0
  12. {sflkit-0.5.3 → sflkit-0.5.4}/pyproject.toml +0 -0
  13. {sflkit-0.5.3 → sflkit-0.5.4}/setup.cfg +0 -0
  14. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/__init__.py +0 -0
  15. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/analysis_type.py +0 -0
  16. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/analyzer.py +0 -0
  17. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/mapping.py +0 -0
  18. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/predicate.py +0 -0
  19. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/similarity.py +0 -0
  20. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/spectra.py +0 -0
  21. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/suggestion.py +0 -0
  22. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/cli.py +0 -0
  23. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/color.py +0 -0
  24. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/config.py +0 -0
  25. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/evaluation.py +0 -0
  26. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/__init__.py +0 -0
  27. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/event_file.py +0 -0
  28. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/mapping.py +0 -0
  29. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/__init__.py +0 -0
  30. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/handler.py +0 -0
  31. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/value.py +0 -0
  32. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/vector.py +0 -0
  33. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/__init__.py +0 -0
  34. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
  35. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
  36. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/__init__.py +0 -0
  37. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/extract.py +0 -0
  38. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/finder.py +0 -0
  39. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/__init__.py +0 -0
  40. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/extract.py +0 -0
  41. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/factory.py +0 -0
  42. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/finder.py +0 -0
  43. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/visitor.py +0 -0
  44. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/language.py +0 -0
  45. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/__init__.py +0 -0
  46. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/extract.py +0 -0
  47. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/factory.py +0 -0
  48. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/finder.py +0 -0
  49. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/visitor.py +0 -0
  50. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/visitor.py +0 -0
  51. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/logger.py +0 -0
  52. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/__init__.py +0 -0
  53. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/model.py +0 -0
  54. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/parallel.py +0 -0
  55. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/runners/__init__.py +0 -0
  56. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/runners/run.py +0 -0
  57. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/__init__.py +0 -0
  58. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/analyzer.py +0 -0
  59. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/models.py +0 -0
  60. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/SOURCES.txt +0 -0
  61. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/dependency_links.txt +0 -0
  62. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/entry_points.txt +0 -0
  63. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/requires.txt +0 -0
  64. {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/top_level.txt +0 -0
  65. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_analysis_objects.py +0 -0
  66. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_analyzer.py +0 -0
  67. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_cli.py +0 -0
  68. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_color.py +0 -0
  69. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_config.py +0 -0
  70. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_coverage.py +0 -0
  71. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_dependency_weights.py +0 -0
  72. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_evaluation.py +0 -0
  73. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_events.py +0 -0
  74. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_execution.py +0 -0
  75. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_features.py +0 -0
  76. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_instrumentation.py +0 -0
  77. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_language.py +0 -0
  78. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_parallelization.py +0 -0
  79. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_predicates.py +0 -0
  80. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner.py +0 -0
  81. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner_parallel.py +0 -0
  82. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner_pytest_versions.py +0 -0
  83. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_spectra.py +0 -0
  84. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_suggestions.py +0 -0
  85. {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_visitors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sflkit
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Author-email: Marius Smytzek <marius.smytzek@cispa.de>
6
6
  Project-URL: Homepage, https://github.com/smythi93/sflkit/
@@ -6,7 +6,7 @@ from sflkit.config import Config, parse_config
6
6
  from sflkit.instrumentation.dir_instrumentation import DirInstrumentation
7
7
 
8
8
 
9
- __version__ = "0.5.3"
9
+ __version__ = "0.5.4"
10
10
 
11
11
 
12
12
  def instrument_config(conf: Config):
@@ -85,7 +85,7 @@ class LineFactory(AnalysisFactory):
85
85
  if key not in self.objects:
86
86
  self.objects[key] = Line(event)
87
87
  return [self.objects[key]]
88
- return None
88
+ return []
89
89
 
90
90
 
91
91
  class BranchFactory(AnalysisFactory):
@@ -117,7 +117,7 @@ class BranchFactory(AnalysisFactory):
117
117
  return [self.objects[key], self.objects[else_key]]
118
118
  return [self.objects[key]]
119
119
 
120
- return None
120
+ return []
121
121
 
122
122
 
123
123
  class FunctionFactory(AnalysisFactory):
@@ -130,7 +130,7 @@ class FunctionFactory(AnalysisFactory):
130
130
  if key not in self.objects:
131
131
  self.objects[key] = Function(event)
132
132
  return [self.objects[key]]
133
- return None
133
+ return []
134
134
 
135
135
 
136
136
  class LoopFactory(AnalysisFactory):
@@ -170,27 +170,70 @@ class LoopFactory(AnalysisFactory):
170
170
  elif event.event_type == EventType.LOOP_END:
171
171
  return self.objects[key][:]
172
172
  return list()
173
- return None
173
+ return []
174
174
 
175
175
 
176
176
  class DefUseFactory(AnalysisFactory):
177
177
  def __init__(self):
178
178
  super().__init__()
179
179
  self.id_to_def: dict[EventFile, dict[tuple[str, int], DefEvent]] = dict()
180
+ self.def_stack: dict[EventFile, dict[int, dict[tuple[str, int], DefEvent]]] = (
181
+ dict()
182
+ )
180
183
 
181
184
  def reset(self, event_file: EventFile):
182
- with self._lock:
183
- self.id_to_def[event_file] = dict()
185
+ if event_file in self.id_to_def:
186
+ del self.id_to_def[event_file]
187
+ if event_file in self.def_stack:
188
+ del self.def_stack[event_file]
189
+
190
+ def _find_def_event(
191
+ self,
192
+ event_file: EventFile,
193
+ scope_id: int,
194
+ var_name: str,
195
+ var_id: int,
196
+ ) -> DefEvent:
197
+ # Strategy 1: Check in scope
198
+ def_event = None
199
+ if event_file in self.def_stack and scope_id in self.def_stack[event_file]:
200
+ def_event = self.def_stack[event_file][scope_id].get(
201
+ (var_name, var_id), None
202
+ )
203
+
204
+ # Strategy 2: Look up in the global DEF stack (other threads)
205
+ if def_event is None:
206
+ if event_file in self.id_to_def:
207
+ def_event = self.id_to_def[event_file].get((var_name, var_id), None)
208
+
209
+ return def_event
184
210
 
185
211
  def get_analysis(
186
212
  self, event, event_file: EventFile, scope: Scope = None
187
213
  ) -> List[AnalysisObject]:
214
+ thread_id = event.thread_id
215
+ scope_id = scope.id if scope else 0
216
+
188
217
  if event.event_type == EventType.DEF:
189
- with self._lock:
190
- self.id_to_def[event_file][(event.var, event.var_id)] = event
218
+ key = (event.var, event.var_id)
219
+
220
+ # Initialize structures if needed
221
+ if event_file not in self.id_to_def:
222
+ self.id_to_def[event_file] = dict()
223
+ if event_file not in self.def_stack:
224
+ self.def_stack[event_file] = dict()
225
+ if scope_id not in self.def_stack[event_file]:
226
+ self.def_stack[event_file][scope_id] = dict()
227
+
228
+ # Store the DEF event
229
+ self.id_to_def[event_file][key] = event
230
+ self.def_stack[event_file][scope_id][key] = event
231
+
191
232
  elif event.event_type == EventType.USE:
192
- with self._lock:
193
- def_event = self.id_to_def[event_file].get((event.var, event.var_id))
233
+ def_event = self._find_def_event(
234
+ event_file, scope_id, event.var, event.var_id
235
+ )
236
+
194
237
  if def_event:
195
238
  key = (
196
239
  DefUse.analysis_type(),
@@ -204,7 +247,7 @@ class DefUseFactory(AnalysisFactory):
204
247
  if key not in self.objects:
205
248
  self.objects[key] = DefUse(def_event, event)
206
249
  return [self.objects[key]]
207
- return None
250
+ return []
208
251
 
209
252
 
210
253
  class ConditionFactory(AnalysisFactory):
@@ -305,7 +348,7 @@ class ScalarPairFactory(ComparisonFactory):
305
348
  )
306
349
  objects.append(self.objects[key])
307
350
  return objects
308
- return None
351
+ return []
309
352
 
310
353
 
311
354
  class VariableFactory(ComparisonFactory):
@@ -332,7 +375,7 @@ class VariableFactory(ComparisonFactory):
332
375
  self.objects[key] = VariablePredicate(event, comp)
333
376
  objects.append(self.objects[key])
334
377
  return objects
335
- return None
378
+ return []
336
379
 
337
380
 
338
381
  class ReturnFactory(ComparisonFactory):
@@ -402,7 +445,7 @@ class ReturnFactory(ComparisonFactory):
402
445
  )
403
446
  objects.append(self.objects[key])
404
447
  return objects
405
- return None
448
+ return []
406
449
 
407
450
 
408
451
  class ConstantCompFactory(AnalysisFactory):
@@ -429,7 +472,7 @@ class ConstantCompFactory(AnalysisFactory):
429
472
  self.objects[key] = self.class_(event)
430
473
  objects.append(self.objects[key])
431
474
  return objects
432
- return None
475
+ return []
433
476
 
434
477
 
435
478
  class NoneFactory(ConstantCompFactory):
@@ -467,7 +510,7 @@ class PredicateFunctionFactory(AnalysisFactory):
467
510
  # noinspection PyArgumentList
468
511
  self.objects[key] = self.class_(event)
469
512
  return [self.objects[key]]
470
- return None
513
+ return []
471
514
 
472
515
 
473
516
  class IsAsciiFactory(PredicateFunctionFactory):
@@ -518,7 +561,7 @@ class LengthFactory(AnalysisFactory):
518
561
  Length(event, Length.evaluate_length_more)
519
562
  )
520
563
  return self.objects[key][:]
521
- return None
564
+ return []
522
565
 
523
566
 
524
567
  class FunctionErrorFactory(AnalysisFactory):
@@ -530,11 +573,9 @@ class FunctionErrorFactory(AnalysisFactory):
530
573
  self, event, event_file: EventFile, scope: Scope = None
531
574
  ) -> List[AnalysisObject]:
532
575
  if event.event_type == EventType.FUNCTION_ENTER:
533
- with self._lock:
534
- self.function_mapping[event.function_id] = event.line
576
+ self.function_mapping[event.function_id] = event.line
535
577
  if event.event_type in (EventType.FUNCTION_ERROR, EventType.FUNCTION_EXIT):
536
- with self._lock:
537
- line = self.function_mapping.get(event.function_id, event.line)
578
+ line = self.function_mapping.get(event.function_id, event.line)
538
579
  key = (
539
580
  FunctionErrorPredicate.analysis_type(),
540
581
  event.file,
@@ -547,7 +588,7 @@ class FunctionErrorFactory(AnalysisFactory):
547
588
  event.file, line, event.function
548
589
  )
549
590
  return [self.objects[key]]
550
- return None
591
+ return []
551
592
 
552
593
 
553
594
  analysis_factory_mapping = {
@@ -1,5 +1,6 @@
1
1
  import random
2
2
  from abc import ABC
3
+ from threading import Lock
3
4
  from typing import List, Type, Any
4
5
 
5
6
  from sflkitlib.events.event import Event
@@ -60,10 +61,12 @@ class Injection:
60
61
  class IDGenerator:
61
62
  def __init__(self):
62
63
  self.current_id = 0
64
+ self.lock = Lock()
63
65
 
64
66
  def get_next_id(self):
65
- id_ = self.current_id
66
- self.current_id += 1
67
+ with self.lock:
68
+ id_ = self.current_id
69
+ self.current_id += 1
67
70
  return id_
68
71
 
69
72
 
@@ -0,0 +1,82 @@
1
+ from threading import Lock
2
+ from typing import List
3
+
4
+
5
+ class Var(object):
6
+ def __init__(self, var, value, type_, id_: int = None):
7
+ self.var = var
8
+ self.value = value
9
+ self.type_ = type_
10
+ self.id = id_ if id_ is not None else hash(self)
11
+
12
+ def __hash__(self):
13
+ return hash(self.var)
14
+
15
+ def __eq__(self, other):
16
+ return isinstance(other, Var) and self.var == other.var
17
+
18
+
19
+ class IDGenerator:
20
+ def __init__(self):
21
+ self.current_id = 0
22
+ self.lock = Lock()
23
+
24
+ def get_next_id(self):
25
+ with self.lock:
26
+ self.current_id += 1
27
+ return self.current_id
28
+
29
+
30
+ class Scope(object):
31
+
32
+ SCOPE_ID = IDGenerator()
33
+
34
+ def __init__(self, parent=None):
35
+ self.parent = parent
36
+ self.variables = dict()
37
+ self.id = Scope.SCOPE_ID.get_next_id()
38
+
39
+ def __hash__(self):
40
+ return hash(self.id)
41
+
42
+ def __eq__(self, other):
43
+ return isinstance(other, Scope) and self.id == other.id
44
+
45
+ def enter(self):
46
+ return Scope(parent=self)
47
+
48
+ def exit(self):
49
+ if self.parent is not None:
50
+ return self.parent
51
+ else:
52
+ return self
53
+
54
+ def __contains__(self, var: str) -> bool:
55
+ current = self
56
+ while current is not None:
57
+ if var in current.variables:
58
+ return True
59
+ current = current.parent
60
+ return False
61
+
62
+ def value(self, var: str) -> Var:
63
+ current = self
64
+ while current is not None:
65
+ if var in current.variables:
66
+ return current.variables[var].value
67
+ current = current.parent
68
+ return None
69
+
70
+ def add(self, var, value, type_, id_: int = None):
71
+ self.variables[var] = Var(var, value, type_, id_)
72
+
73
+ def get_all_vars_dict(self):
74
+ current = self
75
+ variables = dict()
76
+ while current is not None:
77
+ variables = {**current.variables, **variables}
78
+ current = current.parent
79
+ return variables
80
+
81
+ def get_all_vars(self) -> List[Var]:
82
+ return list(self.get_all_vars_dict().values())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sflkit
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Author-email: Marius Smytzek <marius.smytzek@cispa.de>
6
6
  Project-URL: Homepage, https://github.com/smythi93/sflkit/
@@ -0,0 +1,43 @@
1
+ import unittest
2
+
3
+ from sflkit.model.scope import Var, Scope
4
+
5
+
6
+ class TestScope(unittest.TestCase):
7
+ def test_var_eq(self):
8
+ var_1 = Var("x", 2, int)
9
+ var_2 = Var("y", 2, int)
10
+ var_3 = Var("x", "", str)
11
+ self.assertEqual(var_1, var_3)
12
+ self.assertNotEqual(var_1, var_2)
13
+ self.assertNotEqual(var_2, var_3)
14
+ self.assertEqual(hash(var_1), hash(var_3))
15
+ self.assertNotEqual(hash(var_1), hash(var_2))
16
+ self.assertNotEqual(hash(var_2), hash(var_3))
17
+
18
+ def test_scope_without_parent(self):
19
+ scope = Scope()
20
+ self.assertIs(scope, scope.exit())
21
+
22
+ def test_scope_with_parent(self):
23
+ parent_scope = Scope()
24
+ child_scope = parent_scope.enter()
25
+ self.assertIs(parent_scope, child_scope.exit())
26
+
27
+ def test_scope_contains(self):
28
+ scope = Scope()
29
+ scope.variables["x"] = Var("x", 10, int)
30
+ self.assertIn("x", scope)
31
+ self.assertNotIn("y", scope)
32
+
33
+ def test_scope_all_vars(self):
34
+ parent_scope = Scope()
35
+ parent_scope.variables["x"] = Var("x", 10, int)
36
+ child_scope = parent_scope.enter()
37
+ child_scope.variables["y"] = Var("y", 20, int)
38
+
39
+ all_vars = child_scope.get_all_vars_dict()
40
+ self.assertIn("x", all_vars)
41
+ self.assertIn("y", all_vars)
42
+ self.assertEqual(all_vars["x"].value, 10)
43
+ self.assertEqual(all_vars["y"].value, 20)
@@ -1,39 +0,0 @@
1
- from typing import List
2
-
3
-
4
- class Var(object):
5
- def __init__(self, var, value, type_):
6
- self.var = var
7
- self.value = value
8
- self.type_ = type_
9
-
10
- def __hash__(self):
11
- return hash(self.var)
12
-
13
- def __eq__(self, other):
14
- return isinstance(other, Var) and self.var == other.var
15
-
16
-
17
- class Scope(object):
18
- def __init__(self, parent=None, variables: dict = None):
19
- self.parent = parent
20
- self.variables = dict() if variables is None else variables.copy()
21
-
22
- def enter(self):
23
- return Scope(parent=self, variables=self.variables)
24
-
25
- def exit(self):
26
- if self.parent is not None:
27
- return self.parent
28
- else:
29
- return self
30
-
31
- def value(self, var: str) -> Var:
32
- if var in self.variables:
33
- return self.variables[var].value
34
-
35
- def add(self, var, value, type_):
36
- self.variables[var] = Var(var, value, type_)
37
-
38
- def get_all_vars(self) -> List[Var]:
39
- return list(self.variables.values())
@@ -1,20 +0,0 @@
1
- import unittest
2
-
3
- from sflkit.model.scope import Var, Scope
4
-
5
-
6
- class TestScope(unittest.TestCase):
7
- def test_var_eq(self):
8
- var_1 = Var("x", 2, int)
9
- var_2 = Var("y", 2, int)
10
- var_3 = Var("x", "", str)
11
- self.assertEqual(var_1, var_3)
12
- self.assertNotEqual(var_1, var_2)
13
- self.assertNotEqual(var_2, var_3)
14
- self.assertEqual(hash(var_1), hash(var_3))
15
- self.assertNotEqual(hash(var_1), hash(var_2))
16
- self.assertNotEqual(hash(var_2), hash(var_3))
17
-
18
- def test_scope_without_parent(self):
19
- scope = Scope()
20
- self.assertIs(scope, scope.exit())
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes