sflkit 0.2.3__tar.gz → 0.2.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 (59) hide show
  1. {sflkit-0.2.3/src/SFLKit.egg-info → sflkit-0.2.5}/PKG-INFO +1 -1
  2. {sflkit-0.2.3 → sflkit-0.2.5}/pyproject.toml +1 -1
  3. {sflkit-0.2.3 → sflkit-0.2.5/src/SFLKit.egg-info}/PKG-INFO +1 -1
  4. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/__init__.py +1 -1
  5. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/analysis_type.py +14 -2
  6. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/predicate.py +60 -1
  7. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/spectra.py +25 -1
  8. {sflkit-0.2.3 → sflkit-0.2.5}/LICENSE +0 -0
  9. {sflkit-0.2.3 → sflkit-0.2.5}/README.md +0 -0
  10. {sflkit-0.2.3 → sflkit-0.2.5}/setup.cfg +0 -0
  11. {sflkit-0.2.3 → sflkit-0.2.5}/setup.py +0 -0
  12. {sflkit-0.2.3 → sflkit-0.2.5}/src/SFLKit.egg-info/SOURCES.txt +0 -0
  13. {sflkit-0.2.3 → sflkit-0.2.5}/src/SFLKit.egg-info/dependency_links.txt +0 -0
  14. {sflkit-0.2.3 → sflkit-0.2.5}/src/SFLKit.egg-info/entry_points.txt +0 -0
  15. {sflkit-0.2.3 → sflkit-0.2.5}/src/SFLKit.egg-info/requires.txt +0 -0
  16. {sflkit-0.2.3 → sflkit-0.2.5}/src/SFLKit.egg-info/top_level.txt +0 -0
  17. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/__init__.py +0 -0
  18. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/analyzer.py +0 -0
  19. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/factory.py +0 -0
  20. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/mapping.py +0 -0
  21. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/similarity.py +0 -0
  22. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/analysis/suggestion.py +0 -0
  23. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/cli.py +0 -0
  24. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/color.py +0 -0
  25. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/config.py +0 -0
  26. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/instrumentation/__init__.py +0 -0
  27. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
  28. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
  29. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/__init__.py +0 -0
  30. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/extract.py +0 -0
  31. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/finder.py +0 -0
  32. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/language.py +0 -0
  33. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/meta.py +0 -0
  34. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/python/__init__.py +0 -0
  35. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/python/extract.py +0 -0
  36. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/python/factory.py +0 -0
  37. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/python/finder.py +0 -0
  38. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/python/visitor.py +0 -0
  39. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/language/visitor.py +0 -0
  40. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/model/__init__.py +0 -0
  41. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/model/event_file.py +0 -0
  42. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/model/model.py +0 -0
  43. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/model/scope.py +0 -0
  44. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/runners/__init__.py +0 -0
  45. {sflkit-0.2.3 → sflkit-0.2.5}/src/sflkit/runners/run.py +0 -0
  46. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_analysis_objects.py +0 -0
  47. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_cli.py +0 -0
  48. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_color.py +0 -0
  49. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_config.py +0 -0
  50. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_events.py +0 -0
  51. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_execution.py +0 -0
  52. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_instrumentation.py +0 -0
  53. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_language.py +0 -0
  54. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_predicates.py +0 -0
  55. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_runner.py +0 -0
  56. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_scope.py +0 -0
  57. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_spectra.py +0 -0
  58. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_suggestions.py +0 -0
  59. {sflkit-0.2.3 → sflkit-0.2.5}/tests/test_visitors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sflkit
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Home-page: https://github.com/uds-se/sflkit
6
6
  Author: Marius Smytzek & Andreas Zeller
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "sflkit"
10
- version = "0.2.3"
10
+ version = "0.2.5"
11
11
  authors = [
12
12
  { name = "Marius Smytzek", email = "marius.smytzek@cispa.de" },
13
13
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sflkit
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Home-page: https://github.com/uds-se/sflkit
6
6
  Author: Marius Smytzek & Andreas Zeller
@@ -6,7 +6,7 @@ from sflkit.analysis.predicate import Predicate
6
6
  from sflkit.config import Config, parse_config
7
7
  from sflkit.instrumentation.dir_instrumentation import DirInstrumentation
8
8
 
9
- __version__ = "0.2.3"
9
+ __version__ = "0.2.5"
10
10
 
11
11
 
12
12
  def instrument_config(conf: Config, event_dump: str = None):
@@ -5,6 +5,12 @@ from typing import List, Type
5
5
  from sflkit.model.scope import Scope
6
6
 
7
7
 
8
+ class EvaluationResult(enum.Enum):
9
+ TRUE = 1
10
+ FALSE = 0
11
+ UNOBSERVED = -1
12
+
13
+
8
14
  class AnalysisType(enum.Enum):
9
15
  LINE = 0
10
16
  BRANCH = 1
@@ -22,6 +28,12 @@ class AnalysisType(enum.Enum):
22
28
  SPECIAL_STRING = 13
23
29
  EMPTY_BYTES = 14
24
30
 
31
+ def __str__(self):
32
+ return self.name
33
+
34
+ def __repr__(self):
35
+ return self.name
36
+
25
37
 
26
38
  """
27
39
  If you want to add new spectra or predicates, please register them here and in sflkit/language/.py
@@ -29,7 +41,6 @@ If you want to add new spectra or predicates, please register them here and in s
29
41
 
30
42
 
31
43
  class AnalysisObject(object):
32
-
33
44
  function_finder = None
34
45
  loop_finder = None
35
46
  branch_finder = None
@@ -43,12 +54,13 @@ class AnalysisObject(object):
43
54
  # noinspection PyUnusedLocal
44
55
  def __init__(self, event):
45
56
  self.suspiciousness: float = 0
57
+ self.last_evaluation: EvaluationResult = EvaluationResult.UNOBSERVED
46
58
 
47
59
  def __repr__(self):
48
60
  return f"{self.analysis_type()}:{self.suspiciousness}"
49
61
 
50
62
  def __str__(self):
51
- return repr(self)
63
+ return f"{self.analysis_type()}"
52
64
 
53
65
  @staticmethod
54
66
  @abstractmethod
@@ -5,7 +5,7 @@ from typing import Tuple, Callable, Optional
5
5
  from sflkitlib.events import EventType
6
6
  from sflkitlib.events.event import BranchEvent, FunctionExitEvent, DefEvent
7
7
 
8
- from sflkit.analysis.analysis_type import AnalysisType
8
+ from sflkit.analysis.analysis_type import AnalysisType, EvaluationResult
9
9
  from sflkit.analysis.spectra import Spectrum
10
10
  from sflkit.analysis.suggestion import Suggestion, Location
11
11
  from sflkit.model import scope
@@ -24,6 +24,17 @@ class Predicate(Spectrum, ABC):
24
24
  self.increase_true = 0
25
25
  self.increase_false = 0
26
26
  self.true_hits = dict()
27
+ self.last_evaluation = EvaluationResult.UNOBSERVED
28
+
29
+ @staticmethod
30
+ def default_evaluation() -> EvaluationResult:
31
+ return EvaluationResult.UNOBSERVED
32
+
33
+ def get_last_evaluation(self, id_: int) -> EvaluationResult:
34
+ if id_ not in self.true_hits:
35
+ return self.default_evaluation()
36
+ else:
37
+ return self.last_evaluation
27
38
 
28
39
  def finalize(self, passed: list, failed: list):
29
40
  super().finalize(passed, failed)
@@ -46,6 +57,9 @@ class Predicate(Spectrum, ABC):
46
57
  self.true_hits[id_] = 0
47
58
  if self._evaluate_predicate(scope_):
48
59
  self.true_hits[id_] += 1
60
+ self.last_evaluation = EvaluationResult.TRUE
61
+ else:
62
+ self.last_evaluation = EvaluationResult.FALSE
49
63
 
50
64
  def get_metric(self, metric: Callable = None):
51
65
  if metric is None:
@@ -131,6 +145,9 @@ class Branch(Predicate):
131
145
  if event.then_id == self.then_id:
132
146
  super(Predicate, self).hit(id_, event, scope_)
133
147
  self.true_hits[id_] += 1
148
+ self.last_evaluation = EvaluationResult.TRUE
149
+ else:
150
+ self.last_evaluation = EvaluationResult.FALSE
134
151
 
135
152
  def get_suggestion(self, metric: Callable = None, base_dir: str = ""):
136
153
  if metric == Predicate.IncreaseFalse:
@@ -142,6 +159,9 @@ class Branch(Predicate):
142
159
  self.get_metric(metric),
143
160
  )
144
161
 
162
+ def __str__(self):
163
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{'then' if self.then else 'else'}:{self.then_id}"
164
+
145
165
 
146
166
  class Comp(enum.Enum):
147
167
  LT = 0
@@ -165,6 +185,12 @@ class Comp(enum.Enum):
165
185
  elif self == Comp.NE:
166
186
  return x != y
167
187
 
188
+ def __repr__(self):
189
+ return self.name
190
+
191
+ def __str__(self):
192
+ return self.name
193
+
168
194
 
169
195
  class Comparison(Predicate, ABC):
170
196
  def __init__(self, file, line, op: Comp):
@@ -209,6 +235,9 @@ class ScalarPair(Comparison):
209
235
  def _get_second(self, scope_: scope.Scope):
210
236
  return scope_.value(self.var2)
211
237
 
238
+ def __str__(self):
239
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var1}{self.op}{self.var2}"
240
+
212
241
 
213
242
  class VariablePredicate(Comparison):
214
243
  def __init__(self, event, op: Comp):
@@ -228,6 +257,9 @@ class VariablePredicate(Comparison):
228
257
  def _get_first(self, scope_: scope.Scope):
229
258
  return scope_.value(self.var)
230
259
 
260
+ def __str__(self):
261
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}{self.op}0"
262
+
231
263
 
232
264
  class NonePredicate(Comparison):
233
265
  def __init__(self, event: DefEvent):
@@ -250,6 +282,9 @@ class NonePredicate(Comparison):
250
282
  def _get_second(self, scope_: scope.Scope):
251
283
  return None
252
284
 
285
+ def __str__(self):
286
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
287
+
253
288
 
254
289
  class ReturnPredicate(Comparison):
255
290
  def __init__(self, event: FunctionExitEvent, op: Comp, value: Optional[int] = 0):
@@ -275,6 +310,9 @@ class ReturnPredicate(Comparison):
275
310
  def _get_second(self, scope_: scope.Scope):
276
311
  return self.value
277
312
 
313
+ def __str__(self):
314
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.function}{self.op}{self.value}"
315
+
278
316
 
279
317
  class EmptyStringPredicate(Comparison):
280
318
  def __init__(self, event: DefEvent):
@@ -297,6 +335,9 @@ class EmptyStringPredicate(Comparison):
297
335
  def _get_second(self, scope_: scope.Scope):
298
336
  return ""
299
337
 
338
+ def __str__(self):
339
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
340
+
300
341
 
301
342
  class EmptyBytesPredicate(Comparison):
302
343
  def __init__(self, event: DefEvent):
@@ -319,6 +360,9 @@ class EmptyBytesPredicate(Comparison):
319
360
  def _get_second(self, scope_: scope.Scope):
320
361
  return b""
321
362
 
363
+ def __str__(self):
364
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
365
+
322
366
 
323
367
  class FunctionPredicate(Predicate, ABC):
324
368
  def __init__(self, file, line, var: str, predicate: callable):
@@ -345,6 +389,9 @@ class IsAsciiPredicate(FunctionPredicate):
345
389
  def analysis_type():
346
390
  return AnalysisType.ASCII_STRING
347
391
 
392
+ def __str__(self):
393
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
394
+
348
395
 
349
396
  class ContainsDigitPredicate(FunctionPredicate):
350
397
  def __init__(self, event: DefEvent):
@@ -358,6 +405,9 @@ class ContainsDigitPredicate(FunctionPredicate):
358
405
  def analysis_type():
359
406
  return AnalysisType.DIGIT_STRING
360
407
 
408
+ def __str__(self):
409
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
410
+
361
411
 
362
412
  class ContainsSpecialPredicate(FunctionPredicate):
363
413
  def __init__(self, event: DefEvent):
@@ -371,6 +421,9 @@ class ContainsSpecialPredicate(FunctionPredicate):
371
421
  def analysis_type():
372
422
  return AnalysisType.SPECIAL_STRING
373
423
 
424
+ def __str__(self):
425
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.var}"
426
+
374
427
 
375
428
  class Condition(Predicate):
376
429
  def __init__(self, file: str, line: int, condition: str):
@@ -391,3 +444,9 @@ class Condition(Predicate):
391
444
  self.true_hits[id_] = 0
392
445
  if event.value:
393
446
  self.true_hits[id_] += 1
447
+ self.last_evaluation = EvaluationResult.TRUE
448
+ else:
449
+ self.last_evaluation = EvaluationResult.FALSE
450
+
451
+ def __str__(self):
452
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.condition}"
@@ -14,7 +14,7 @@ from sflkitlib.events.event import (
14
14
  UseEvent,
15
15
  )
16
16
 
17
- from sflkit.analysis.analysis_type import AnalysisObject, AnalysisType
17
+ from sflkit.analysis.analysis_type import AnalysisObject, AnalysisType, EvaluationResult
18
18
  from sflkit.analysis.suggestion import Suggestion, Location
19
19
  from sflkit.model.scope import Scope
20
20
 
@@ -39,6 +39,20 @@ class Spectrum(AnalysisObject, ABC):
39
39
  self.failed_observed = failed_observed
40
40
  self.failed_not_observed = failed_not_observed
41
41
  self.hits = dict()
42
+ self.last_evaluation: EvaluationResult = EvaluationResult.FALSE
43
+
44
+ def __str__(self):
45
+ return f"{self.analysis_type()}:{self.file}:{self.line}"
46
+
47
+ @staticmethod
48
+ def default_evaluation() -> EvaluationResult:
49
+ return EvaluationResult.FALSE
50
+
51
+ def get_last_evaluation(self, id_: int) -> EvaluationResult:
52
+ if id_ not in self.hits:
53
+ return self.default_evaluation()
54
+ else:
55
+ return self.last_evaluation
42
56
 
43
57
  def get_metric(self, metric: Callable = None):
44
58
  if metric is None:
@@ -59,6 +73,7 @@ class Spectrum(AnalysisObject, ABC):
59
73
  self.suspiciousness = self.get_metric(metric)
60
74
 
61
75
  def hit(self, id_, event, scope_: Scope = None):
76
+ self.last_evaluation = True
62
77
  if id_ not in self.hits:
63
78
  self.hits[id_] = 1
64
79
  else:
@@ -483,6 +498,9 @@ class Function(Spectrum):
483
498
  self.get_metric(metric),
484
499
  )
485
500
 
501
+ def __str__(self):
502
+ return f"{self.analysis_type()}:{self.file}:{self.function}:{self.line}"
503
+
486
504
 
487
505
  class DefUse(Spectrum):
488
506
  def __init__(self, def_event: DefEvent, use_event: UseEvent):
@@ -505,6 +523,9 @@ class DefUse(Spectrum):
505
523
  self.get_metric(metric),
506
524
  )
507
525
 
526
+ def __str__(self):
527
+ return f"{self.analysis_type()}:{self.file}:{self.line}:{self.use_file}:{self.use_line}:{self.var}"
528
+
508
529
 
509
530
  class Loop(Spectrum):
510
531
  def __init__(
@@ -569,3 +590,6 @@ class Loop(Spectrum):
569
590
  [Location(self.file, line) for line in finder.get_locations(base_dir)],
570
591
  self.get_metric(metric),
571
592
  )
593
+
594
+ def __str__(self):
595
+ return f"{self.analysis_type()}:{self.file}:{self.line}"
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