sflkit 0.5.3__tar.gz → 0.5.5__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 (86) hide show
  1. {sflkit-0.5.3/src/sflkit.egg-info → sflkit-0.5.5}/PKG-INFO +1 -1
  2. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/__init__.py +1 -1
  3. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/factory.py +63 -22
  4. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/spectra.py +7 -1
  5. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/file_instrumentation.py +6 -1
  6. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/meta.py +50 -21
  7. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/factory.py +188 -6
  8. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/visitor.py +2 -1
  9. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/parallel.py +10 -10
  10. sflkit-0.5.5/src/sflkit/model/scope.py +82 -0
  11. {sflkit-0.5.3 → sflkit-0.5.5/src/sflkit.egg-info}/PKG-INFO +1 -1
  12. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/SOURCES.txt +1 -0
  13. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_analysis_objects.py +4 -1
  14. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_config.py +4 -1
  15. sflkit-0.5.5/tests/test_expression.py +181 -0
  16. sflkit-0.5.5/tests/test_scope.py +43 -0
  17. sflkit-0.5.3/src/sflkit/model/scope.py +0 -39
  18. sflkit-0.5.3/tests/test_scope.py +0 -20
  19. {sflkit-0.5.3 → sflkit-0.5.5}/LICENSE +0 -0
  20. {sflkit-0.5.3 → sflkit-0.5.5}/README.md +0 -0
  21. {sflkit-0.5.3 → sflkit-0.5.5}/pyproject.toml +0 -0
  22. {sflkit-0.5.3 → sflkit-0.5.5}/setup.cfg +0 -0
  23. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/__init__.py +0 -0
  24. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/analysis_type.py +0 -0
  25. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/analyzer.py +0 -0
  26. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/mapping.py +0 -0
  27. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/predicate.py +0 -0
  28. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/similarity.py +0 -0
  29. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/suggestion.py +0 -0
  30. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/cli.py +0 -0
  31. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/color.py +0 -0
  32. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/config.py +0 -0
  33. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/evaluation.py +0 -0
  34. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/__init__.py +0 -0
  35. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/event_file.py +0 -0
  36. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/mapping.py +0 -0
  37. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/__init__.py +0 -0
  38. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/handler.py +0 -0
  39. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/value.py +0 -0
  40. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/vector.py +0 -0
  41. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/__init__.py +0 -0
  42. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
  43. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/__init__.py +0 -0
  44. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/extract.py +0 -0
  45. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/finder.py +0 -0
  46. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/__init__.py +0 -0
  47. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/extract.py +0 -0
  48. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/factory.py +0 -0
  49. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/finder.py +0 -0
  50. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/visitor.py +0 -0
  51. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/language.py +0 -0
  52. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/__init__.py +0 -0
  53. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/extract.py +0 -0
  54. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/finder.py +0 -0
  55. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/visitor.py +0 -0
  56. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/logger.py +0 -0
  57. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/__init__.py +0 -0
  58. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/model.py +0 -0
  59. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/runners/__init__.py +0 -0
  60. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/runners/run.py +0 -0
  61. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/__init__.py +0 -0
  62. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/analyzer.py +0 -0
  63. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/models.py +0 -0
  64. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/dependency_links.txt +0 -0
  65. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/entry_points.txt +0 -0
  66. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/requires.txt +0 -0
  67. {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/top_level.txt +0 -0
  68. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_analyzer.py +0 -0
  69. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_cli.py +0 -0
  70. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_color.py +0 -0
  71. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_coverage.py +0 -0
  72. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_dependency_weights.py +0 -0
  73. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_evaluation.py +0 -0
  74. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_events.py +0 -0
  75. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_execution.py +0 -0
  76. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_features.py +0 -0
  77. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_instrumentation.py +0 -0
  78. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_language.py +0 -0
  79. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_parallelization.py +0 -0
  80. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_predicates.py +0 -0
  81. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner.py +0 -0
  82. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner_parallel.py +0 -0
  83. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner_pytest_versions.py +0 -0
  84. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_spectra.py +0 -0
  85. {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_suggestions.py +0 -0
  86. {sflkit-0.5.3 → sflkit-0.5.5}/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.5
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.5"
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 = {
@@ -722,7 +722,13 @@ class DefUse(Spectrum):
722
722
 
723
723
  @staticmethod
724
724
  def events():
725
- return [EventType.DEF, EventType.USE]
725
+ return [
726
+ EventType.DEF,
727
+ EventType.USE,
728
+ EventType.FUNCTION_ENTER,
729
+ EventType.FUNCTION_EXIT,
730
+ EventType.FUNCTION_ERROR,
731
+ ]
726
732
 
727
733
  def get_suggestion(
728
734
  self, metric: Callable = None, base_dir: str = "", use_weight: bool = False
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from pathlib import Path
2
3
  from typing import List, Optional
3
4
 
@@ -11,7 +12,11 @@ class FileInstrumentation(Instrumentation):
11
12
  super().__init__(visitor, mapping_path)
12
13
 
13
14
  def instrument(
14
- self, src: str, dst: str, suffixes: List[str] = None, file: str = ""
15
+ self,
16
+ src: os.PathLike,
17
+ dst: os.PathLike,
18
+ suffixes: List[str] = None,
19
+ file: str = "",
15
20
  ):
16
21
  self.visitor.instrument(src, dst, file)
17
22
  self.events = EventMapping(
@@ -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
 
@@ -85,6 +88,7 @@ class MetaVisitor(ABC):
85
88
  event_id_generator: IDGenerator,
86
89
  function_id_generator: IDGenerator,
87
90
  tmp_generator: TmpGenerator,
91
+ order: int = 0,
88
92
  **kwargs,
89
93
  ):
90
94
  self.event_id_generator = event_id_generator
@@ -95,6 +99,27 @@ class MetaVisitor(ABC):
95
99
  self.condition_extract = language.condition_extract
96
100
  self.event_count = 0
97
101
  self.file = None
102
+ self.order = order
103
+
104
+ def __lt__(self, other):
105
+ if not isinstance(other, MetaVisitor):
106
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
107
+ return self.order < other.order
108
+
109
+ def __gt__(self, other):
110
+ if not isinstance(other, MetaVisitor):
111
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
112
+ return self.order > other.order
113
+
114
+ def __le__(self, other):
115
+ if not isinstance(other, MetaVisitor):
116
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
117
+ return self.order <= other.order
118
+
119
+ def __ge__(self, other):
120
+ if not isinstance(other, MetaVisitor):
121
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
122
+ return self.order >= other.order
98
123
 
99
124
  def get_event_call(self, event: Event):
100
125
  pass
@@ -145,26 +170,30 @@ class CombinationVisitor(MetaVisitor):
145
170
  tmp_generator,
146
171
  )
147
172
  if test:
148
- self.visitors = [
149
- visitor(
150
- language,
151
- event_id_generator,
152
- function_id_generator,
153
- tmp_generator,
154
- ignore_inner=ignore_inner,
155
- )
156
- for visitor in visitors
157
- ]
173
+ self.visitors = sorted(
174
+ [
175
+ visitor(
176
+ language,
177
+ event_id_generator,
178
+ function_id_generator,
179
+ tmp_generator,
180
+ ignore_inner=ignore_inner,
181
+ )
182
+ for visitor in visitors
183
+ ],
184
+ )
158
185
  else:
159
- self.visitors = [
160
- visitor(
161
- language,
162
- event_id_generator,
163
- function_id_generator,
164
- tmp_generator,
165
- )
166
- for visitor in visitors
167
- ]
186
+ self.visitors = sorted(
187
+ [
188
+ visitor(
189
+ language,
190
+ event_id_generator,
191
+ function_id_generator,
192
+ tmp_generator,
193
+ )
194
+ for visitor in visitors
195
+ ],
196
+ )
168
197
 
169
198
  def visit_start(self, *args) -> Injection:
170
199
  injections = Injection()
@@ -56,10 +56,15 @@ class PythonEventFactory(MetaVisitor, NodeVisitor):
56
56
  event_id_generator: IDGenerator,
57
57
  function_id_generator: IDGenerator,
58
58
  tmp_generator: TmpGenerator,
59
+ order: int = 0,
59
60
  **kwargs,
60
61
  ):
61
62
  super().__init__(
62
- language, event_id_generator, function_id_generator, tmp_generator
63
+ language,
64
+ event_id_generator,
65
+ function_id_generator,
66
+ tmp_generator,
67
+ order=order,
63
68
  )
64
69
 
65
70
  def visit_start(self, *args) -> Injection:
@@ -291,7 +296,21 @@ class DefEventFactory(PythonEventFactory):
291
296
  def visit_AsyncFunctionDef(self, node: AsyncFunctionDef) -> Injection:
292
297
  return self.visit_function(node)
293
298
 
294
- def get_event(self, node: typing.Union[Assign, AnnAssign, AugAssign], var: str):
299
+ def get_event(
300
+ self,
301
+ node: typing.Union[
302
+ Assign,
303
+ AnnAssign,
304
+ AugAssign,
305
+ FunctionDef,
306
+ AsyncFunctionDef,
307
+ For,
308
+ AsyncFor,
309
+ With,
310
+ AsyncWith,
311
+ ],
312
+ var: str,
313
+ ):
295
314
  return DefEvent(
296
315
  self.file, node.lineno, self.event_id_generator.get_next_id(), var
297
316
  )
@@ -369,18 +388,24 @@ class FunctionEventFactory(PythonEventFactory):
369
388
  event_id_generator: IDGenerator,
370
389
  function_id_generator: IDGenerator,
371
390
  tmp_generator: TmpGenerator,
391
+ order: int,
372
392
  **kwargs,
373
393
  ):
374
394
  super().__init__(
375
- language, event_id_generator, function_id_generator, tmp_generator, **kwargs
395
+ language,
396
+ event_id_generator,
397
+ function_id_generator,
398
+ tmp_generator,
399
+ order=order,
400
+ **kwargs,
376
401
  )
377
402
  self.function_stack = list()
378
403
 
379
404
  def get_function_id(self, node: AST) -> int:
380
405
  if node not in FunctionEventFactory.functions:
381
- FunctionEventFactory.functions[
382
- node
383
- ] = self.function_id_generator.get_next_id()
406
+ FunctionEventFactory.functions[node] = (
407
+ self.function_id_generator.get_next_id()
408
+ )
384
409
  return FunctionEventFactory.functions[node]
385
410
 
386
411
  @staticmethod
@@ -403,6 +428,23 @@ class FunctionEventFactory(PythonEventFactory):
403
428
 
404
429
 
405
430
  class FunctionEnterEventFactory(FunctionEventFactory):
431
+ def __init__(
432
+ self,
433
+ language,
434
+ event_id_generator: IDGenerator,
435
+ function_id_generator: IDGenerator,
436
+ tmp_generator: TmpGenerator,
437
+ **kwargs,
438
+ ):
439
+ super().__init__(
440
+ language,
441
+ event_id_generator,
442
+ function_id_generator,
443
+ tmp_generator,
444
+ order=-2,
445
+ **kwargs,
446
+ )
447
+
406
448
  def get_function(self):
407
449
  return "add_function_enter_event"
408
450
 
@@ -441,6 +483,23 @@ class FunctionEnterEventFactory(FunctionEventFactory):
441
483
 
442
484
 
443
485
  class FunctionExitEventFactor(FunctionEventFactory):
486
+ def __init__(
487
+ self,
488
+ language,
489
+ event_id_generator: IDGenerator,
490
+ function_id_generator: IDGenerator,
491
+ tmp_generator: TmpGenerator,
492
+ **kwargs,
493
+ ):
494
+ super().__init__(
495
+ language,
496
+ event_id_generator,
497
+ function_id_generator,
498
+ tmp_generator,
499
+ order=2,
500
+ **kwargs,
501
+ )
502
+
444
503
  def get_function(self):
445
504
  return "add_function_exit_event"
446
505
 
@@ -521,6 +580,23 @@ class FunctionExitEventFactor(FunctionEventFactory):
521
580
 
522
581
 
523
582
  class FunctionErrorEventFactory(FunctionEventFactory):
583
+ def __init__(
584
+ self,
585
+ language,
586
+ event_id_generator: IDGenerator,
587
+ function_id_generator: IDGenerator,
588
+ tmp_generator: TmpGenerator,
589
+ **kwargs,
590
+ ):
591
+ super().__init__(
592
+ language,
593
+ event_id_generator,
594
+ function_id_generator,
595
+ tmp_generator,
596
+ order=2,
597
+ **kwargs,
598
+ )
599
+
524
600
  def get_function(self):
525
601
  return "add_function_error_event"
526
602
 
@@ -550,6 +626,24 @@ class LoopEventFactory(PythonEventFactory):
550
626
  loops: typing.Dict[AST, int] = dict()
551
627
  loop_id: int = 0
552
628
 
629
+ def __init__(
630
+ self,
631
+ language,
632
+ event_id_generator: IDGenerator,
633
+ function_id_generator: IDGenerator,
634
+ tmp_generator: TmpGenerator,
635
+ order: int,
636
+ **kwargs,
637
+ ):
638
+ super().__init__(
639
+ language,
640
+ event_id_generator,
641
+ function_id_generator,
642
+ tmp_generator,
643
+ order=order,
644
+ **kwargs,
645
+ )
646
+
553
647
  @staticmethod
554
648
  def get_loop_id(node: AST) -> int:
555
649
  if node not in LoopEventFactory.loops:
@@ -571,6 +665,23 @@ class LoopEventFactory(PythonEventFactory):
571
665
 
572
666
 
573
667
  class LoopBeginEventFactory(LoopEventFactory):
668
+ def __init__(
669
+ self,
670
+ language,
671
+ event_id_generator: IDGenerator,
672
+ function_id_generator: IDGenerator,
673
+ tmp_generator: TmpGenerator,
674
+ **kwargs,
675
+ ):
676
+ super().__init__(
677
+ language,
678
+ event_id_generator,
679
+ function_id_generator,
680
+ tmp_generator,
681
+ order=-1,
682
+ **kwargs,
683
+ )
684
+
574
685
  def get_function(self):
575
686
  return "add_loop_begin_event"
576
687
 
@@ -587,6 +698,23 @@ class LoopBeginEventFactory(LoopEventFactory):
587
698
 
588
699
 
589
700
  class LoopHitEventFactory(LoopEventFactory):
701
+ def __init__(
702
+ self,
703
+ language,
704
+ event_id_generator: IDGenerator,
705
+ function_id_generator: IDGenerator,
706
+ tmp_generator: TmpGenerator,
707
+ **kwargs,
708
+ ):
709
+ super().__init__(
710
+ language,
711
+ event_id_generator,
712
+ function_id_generator,
713
+ tmp_generator,
714
+ order=-1,
715
+ **kwargs,
716
+ )
717
+
590
718
  def get_function(self):
591
719
  return "add_loop_hit_event"
592
720
 
@@ -603,6 +731,23 @@ class LoopHitEventFactory(LoopEventFactory):
603
731
 
604
732
 
605
733
  class LoopEndEventFactory(LoopEventFactory):
734
+ def __init__(
735
+ self,
736
+ language,
737
+ event_id_generator: IDGenerator,
738
+ function_id_generator: IDGenerator,
739
+ tmp_generator: TmpGenerator,
740
+ **kwargs,
741
+ ):
742
+ super().__init__(
743
+ language,
744
+ event_id_generator,
745
+ function_id_generator,
746
+ tmp_generator,
747
+ order=1,
748
+ **kwargs,
749
+ )
750
+
606
751
  def get_function(self):
607
752
  return "add_loop_end_event"
608
753
 
@@ -717,6 +862,7 @@ class UseEventFactory(PythonEventFactory):
717
862
  return self._get_try_wrapper(event)
718
863
 
719
864
  def get_event(self, node: AST, use: str) -> UseEvent:
865
+ # noinspection PyUnresolvedReferences
720
866
  return UseEvent(
721
867
  self.file, node.lineno, self.event_id_generator.get_next_id(), use
722
868
  )
@@ -894,6 +1040,23 @@ class LenEventFactory(DefEventFactory):
894
1040
 
895
1041
 
896
1042
  class TestStartEventFactory(FunctionEventFactory):
1043
+ def __init__(
1044
+ self,
1045
+ language,
1046
+ event_id_generator: IDGenerator,
1047
+ function_id_generator: IDGenerator,
1048
+ tmp_generator: TmpGenerator,
1049
+ **kwargs,
1050
+ ):
1051
+ super().__init__(
1052
+ language,
1053
+ event_id_generator,
1054
+ function_id_generator,
1055
+ tmp_generator,
1056
+ order=2,
1057
+ **kwargs,
1058
+ )
1059
+
897
1060
  def get_function(self):
898
1061
  return "add_test_start_event"
899
1062
 
@@ -924,6 +1087,23 @@ class TestStartEventFactory(FunctionEventFactory):
924
1087
 
925
1088
 
926
1089
  class TestEndEventFactory(FunctionEventFactory):
1090
+ def __init__(
1091
+ self,
1092
+ language,
1093
+ event_id_generator: IDGenerator,
1094
+ function_id_generator: IDGenerator,
1095
+ tmp_generator: TmpGenerator,
1096
+ **kwargs,
1097
+ ):
1098
+ super().__init__(
1099
+ language,
1100
+ event_id_generator,
1101
+ function_id_generator,
1102
+ tmp_generator,
1103
+ order=2,
1104
+ **kwargs,
1105
+ )
1106
+
927
1107
  def get_function(self):
928
1108
  return "add_test_end_event"
929
1109
 
@@ -991,6 +1171,7 @@ class TestLineEventFactory(LineEventFactory):
991
1171
  return "add_test_line_event"
992
1172
 
993
1173
  def visit_line(self, node: AST) -> Injection:
1174
+ # noinspection PyUnresolvedReferences
994
1175
  line_event = TestLineEvent(
995
1176
  self.file, node.lineno, self.event_id_generator.get_next_id()
996
1177
  )
@@ -1113,6 +1294,7 @@ class TestUseEventFactory(UseEventFactory):
1113
1294
  return "add_test_use_event"
1114
1295
 
1115
1296
  def get_event(self, node: AST, use: str) -> TestUseEvent:
1297
+ # noinspection PyUnresolvedReferences
1116
1298
  return TestUseEvent(
1117
1299
  self.file, node.lineno, self.event_id_generator.get_next_id(), use
1118
1300
  )
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from abc import abstractmethod, ABC
2
3
 
3
4
  from sflkit.language.meta import MetaVisitor
@@ -22,7 +23,7 @@ class ASTVisitor(ABC):
22
23
  def start_visit(self, ast):
23
24
  raise NotImplementedError()
24
25
 
25
- def instrument(self, src: str, dst: str, file: str = ""):
26
+ def instrument(self, src: os.PathLike, dst: os.PathLike, file: str = ""):
26
27
  self.file = file
27
28
  with open(src, "r") as fp:
28
29
  source = fp.read()