sflkit 0.2.18__tar.gz → 0.2.19__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 (63) hide show
  1. {sflkit-0.2.18/src/sflkit.egg-info → sflkit-0.2.19}/PKG-INFO +1 -1
  2. {sflkit-0.2.18 → sflkit-0.2.19}/pyproject.toml +1 -1
  3. sflkit-0.2.19/src/sflkit/runners/resources/__init__.py +0 -0
  4. sflkit-0.2.19/src/sflkit/runners/resources/pytest_main.py +82 -0
  5. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/runners/run.py +47 -12
  6. {sflkit-0.2.18 → sflkit-0.2.19/src/sflkit.egg-info}/PKG-INFO +1 -1
  7. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/SOURCES.txt +2 -0
  8. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_instrumentation.py +56 -6
  9. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_runner.py +1 -1
  10. {sflkit-0.2.18 → sflkit-0.2.19}/LICENSE +0 -0
  11. {sflkit-0.2.18 → sflkit-0.2.19}/README.md +0 -0
  12. {sflkit-0.2.18 → sflkit-0.2.19}/setup.cfg +0 -0
  13. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/__init__.py +0 -0
  14. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/__init__.py +0 -0
  15. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/analysis_type.py +0 -0
  16. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/analyzer.py +0 -0
  17. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/factory.py +0 -0
  18. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/mapping.py +0 -0
  19. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/predicate.py +0 -0
  20. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/similarity.py +0 -0
  21. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/spectra.py +0 -0
  22. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/suggestion.py +0 -0
  23. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/cli.py +0 -0
  24. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/color.py +0 -0
  25. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/config.py +0 -0
  26. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/__init__.py +0 -0
  27. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
  28. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
  29. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/__init__.py +0 -0
  30. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/extract.py +0 -0
  31. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/finder.py +0 -0
  32. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/language.py +0 -0
  33. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/meta.py +0 -0
  34. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/__init__.py +0 -0
  35. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/extract.py +0 -0
  36. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/factory.py +0 -0
  37. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/finder.py +0 -0
  38. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/visitor.py +0 -0
  39. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/visitor.py +0 -0
  40. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/logger.py +0 -0
  41. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/mapping.py +0 -0
  42. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/__init__.py +0 -0
  43. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/event_file.py +0 -0
  44. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/model.py +0 -0
  45. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/scope.py +0 -0
  46. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/runners/__init__.py +0 -0
  47. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/dependency_links.txt +0 -0
  48. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/entry_points.txt +0 -0
  49. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/requires.txt +0 -0
  50. {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/top_level.txt +0 -0
  51. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_analysis_objects.py +0 -0
  52. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_cli.py +0 -0
  53. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_color.py +0 -0
  54. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_config.py +0 -0
  55. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_coverage.py +0 -0
  56. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_events.py +0 -0
  57. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_execution.py +0 -0
  58. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_language.py +0 -0
  59. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_predicates.py +0 -0
  60. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_scope.py +0 -0
  61. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_spectra.py +0 -0
  62. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_suggestions.py +0 -0
  63. {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_visitors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sflkit
3
- Version: 0.2.18
3
+ Version: 0.2.19
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/uds-se/sflkit/
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "sflkit"
10
- version = "0.2.18"
10
+ version = "0.2.19"
11
11
  authors = [
12
12
  { name = "Marius Smytzek", email = "marius.smytzek@cispa.de" },
13
13
  ]
File without changes
@@ -0,0 +1,82 @@
1
+ import os
2
+ import sys
3
+ from typing import Optional, Union, List, Sequence
4
+
5
+ # noinspection PyPackageRequirements
6
+ from _pytest._code import ExceptionInfo
7
+
8
+ # noinspection PyPackageRequirements
9
+ from _pytest._io import TerminalWriter
10
+
11
+ # noinspection PyPackageRequirements
12
+ from _pytest.config import (
13
+ ExitCode,
14
+ _prepareconfig,
15
+ ConftestImportFailure,
16
+ UsageError,
17
+ filter_traceback_for_conftest_import_failure,
18
+ _PluggyPlugin,
19
+ )
20
+
21
+
22
+ def pytest_collection_finish(session):
23
+ """
24
+ Called after collection has been performed and modified.
25
+ """
26
+ file = os.getenv("SFLKIT_PYTEST_COLLECTION_FINISH_FILE", "tmp_sflkit_pytest")
27
+ with open(file, "w") as f:
28
+ for item in session.items:
29
+ f.write(item.nodeid + "\n")
30
+
31
+
32
+ def main(
33
+ args: Optional[Union[List[str], "os.PathLike[str]"]] = None,
34
+ plugins: Optional[Sequence[Union[str, _PluggyPlugin]]] = None,
35
+ ) -> Union[int, ExitCode]:
36
+ """Perform an in-process test run.
37
+
38
+ :param args: List of command line arguments.
39
+ :param plugins: List of plugin objects to be auto-registered during initialization.
40
+
41
+ :returns: An exit code.
42
+ """
43
+ try:
44
+ try:
45
+ config = _prepareconfig(args, plugins)
46
+ except ConftestImportFailure as e:
47
+ exc_info = ExceptionInfo.from_exc_info(e.excinfo)
48
+ tw = TerminalWriter(sys.stderr)
49
+ tw.line(f"ImportError while loading conftest '{e.path}'.", red=True)
50
+ exc_info.traceback = exc_info.traceback.filter(
51
+ filter_traceback_for_conftest_import_failure
52
+ )
53
+ exc_repr = (
54
+ exc_info.getrepr(style="short", chain=False)
55
+ if exc_info.traceback
56
+ else exc_info.exconly()
57
+ )
58
+ formatted_tb = str(exc_repr)
59
+ for line in formatted_tb.splitlines():
60
+ tw.line(line.rstrip(), red=True)
61
+ return ExitCode.USAGE_ERROR
62
+ else:
63
+ try:
64
+ config.hook.pytest_collection_finish = pytest_collection_finish
65
+ ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main(
66
+ config=config
67
+ )
68
+ try:
69
+ return ExitCode(ret)
70
+ except ValueError:
71
+ return ret
72
+ finally:
73
+ config._ensure_unconfigure()
74
+ except UsageError as e:
75
+ tw = TerminalWriter(sys.stderr)
76
+ for msg in e.args:
77
+ tw.line(f"ERROR: {msg}\n", red=True)
78
+ return ExitCode.USAGE_ERROR
79
+
80
+
81
+ if __name__ == "__main__":
82
+ main(sys.argv[1:])
@@ -9,6 +9,8 @@ import subprocess
9
9
  from pathlib import Path
10
10
  from typing import List, Dict, Optional, Tuple
11
11
 
12
+ from sflkit.logger import LOGGER
13
+
12
14
  Environment = Dict[str, str]
13
15
 
14
16
  PYTEST_RESULT_PATTERN = re.compile(
@@ -118,6 +120,15 @@ class VoidRunner(Runner):
118
120
 
119
121
 
120
122
  class PytestRunner(Runner):
123
+ def __init__(
124
+ self,
125
+ re_filter: str = r".*",
126
+ timeout=DEFAULT_TIMEOUT,
127
+ set_python_path: bool = False,
128
+ ):
129
+ super().__init__(re_filter, timeout)
130
+ self.set_python_path = set_python_path
131
+
121
132
  @staticmethod
122
133
  def _common_base(directory: Path, tests: List[str]) -> Path:
123
134
  parts = directory.parts
@@ -165,25 +176,49 @@ class PytestRunner(Runner):
165
176
  directory = directory.absolute()
166
177
  if files:
167
178
  if isinstance(files, (str, os.PathLike)):
168
- c.append(files)
179
+ c.append(str(files))
169
180
  else:
170
- c += files
181
+ c += [str(f) for f in files]
171
182
  if base:
172
183
  if not files:
173
- c.append(base)
184
+ c.append(str(base))
174
185
  root_dir = directory / base
175
186
  else:
176
187
  root_dir = directory
177
- output = subprocess.run(
178
- ["python", "-m", "pytest", "--collect-only", "-q"] + c,
188
+ tmp = Path(f"tmp_sflkit_pytest_tmp_{id(self)}").absolute()
189
+ pytest_main = (
190
+ Path(__file__).parent.resolve() / "resources" / "pytest_main.py"
191
+ ).absolute()
192
+ environ = dict(environ or os.environ)
193
+ environ["SFLKIT_PYTEST_COLLECTION_FINISH_FILE"] = str(tmp)
194
+ if self.set_python_path:
195
+ if "PYTHONPATH" in environ:
196
+ environ["PYTHONPATH"] = str(directory) + ":" + environ["PYTHONPATH"]
197
+ else:
198
+ environ["PYTHONPATH"] = str(directory)
199
+ process = subprocess.run(
200
+ [
201
+ "python3",
202
+ str(pytest_main),
203
+ "--collect-only",
204
+ ]
205
+ + c,
179
206
  stdout=subprocess.PIPE,
207
+ stderr=subprocess.PIPE,
180
208
  env=environ,
181
209
  cwd=directory,
182
- ).stdout.decode("utf-8")
183
- tests = output.split("\n\n", 1)[0].split("\n")
184
- if tests[-1] == "":
185
- tests = tests[:-1]
186
- return self._normalize_paths(tests, directory, root_dir)
210
+ )
211
+ LOGGER.info(f"pytest collection finished with {process.returncode}")
212
+ if not tmp.exists():
213
+ tmp = directory / "tmp_sflkit_pytest"
214
+ if tmp.exists():
215
+ with open(tmp, "r") as f:
216
+ tests = [line.strip() for line in f.readlines()]
217
+ os.remove(tmp)
218
+ return self._normalize_paths(tests, directory, root_dir)
219
+ else:
220
+ LOGGER.warn(f"Could not find {tmp}")
221
+ return []
187
222
 
188
223
  @staticmethod
189
224
  def __get_pytest_result__(
@@ -207,7 +242,7 @@ class PytestRunner(Runner):
207
242
  ) -> TestResult:
208
243
  try:
209
244
  output = subprocess.run(
210
- ["python", "-m", "pytest", test],
245
+ ["python3", "-m", "pytest", test],
211
246
  stdout=subprocess.PIPE,
212
247
  env=environ,
213
248
  cwd=directory,
@@ -288,7 +323,7 @@ class InputRunner(Runner):
288
323
  result = TestResult.FAILING
289
324
  try:
290
325
  process = subprocess.run(
291
- ["python", self.access] + test,
326
+ ["python3", self.access] + test,
292
327
  stdout=subprocess.PIPE,
293
328
  stderr=subprocess.PIPE,
294
329
  env=environ,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sflkit
3
- Version: 0.2.18
3
+ Version: 0.2.19
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/uds-se/sflkit/
@@ -42,6 +42,8 @@ src/sflkit/model/model.py
42
42
  src/sflkit/model/scope.py
43
43
  src/sflkit/runners/__init__.py
44
44
  src/sflkit/runners/run.py
45
+ src/sflkit/runners/resources/__init__.py
46
+ src/sflkit/runners/resources/pytest_main.py
45
47
  tests/test_analysis_objects.py
46
48
  tests/test_cli.py
47
49
  tests/test_color.py
@@ -2,8 +2,7 @@ import atexit
2
2
  import os
3
3
  from pathlib import Path
4
4
 
5
- from parameterized import parameterized
6
- from sflkitlib.events import event, EventType
5
+ from sflkitlib.events import EventType
7
6
 
8
7
  from sflkit import instrument_config, Config
9
8
  from utils import BaseTest
@@ -121,6 +120,61 @@ class TestInstrumentation(BaseTest):
121
120
  self.assertTrue(mapping.exists())
122
121
  self.assertTrue(mapping.is_file())
123
122
 
123
+ def test_instrument_exclude(self):
124
+ src = Path(BaseTest.TEST_RESOURCES, "test_exclude")
125
+ dst = Path(BaseTest.TEST_DIR)
126
+ instrument_config(
127
+ Config.create(
128
+ path=str(src),
129
+ language="python",
130
+ events="line",
131
+ predicates="line",
132
+ working=BaseTest.TEST_DIR,
133
+ include="included",
134
+ exclude=os.path.join("included", "excluded"),
135
+ )
136
+ )
137
+ included = dst / "included"
138
+ excluded = included / "excluded"
139
+ a = included / "a.py"
140
+ b = excluded / "b.py"
141
+ c = dst / "c.py"
142
+
143
+ included_src = src / "included"
144
+ excluded_src = included_src / "excluded"
145
+ a_src = included_src / "a.py"
146
+ b_src = excluded_src / "b.py"
147
+ c_src = src / "c.py"
148
+
149
+ self.assertTrue(included.exists())
150
+ self.assertTrue(included.is_dir())
151
+ self.assertTrue(excluded.exists())
152
+ self.assertTrue(excluded.is_dir())
153
+ self.assertTrue(a.exists())
154
+ self.assertTrue(a.is_file())
155
+ self.assertTrue(b.exists())
156
+ self.assertTrue(b.is_file())
157
+ self.assertTrue(c.exists())
158
+ self.assertTrue(c.is_file())
159
+
160
+ with open(a, "r") as fp:
161
+ a_content = fp.read()
162
+ with open(a_src, "r") as fp:
163
+ a_src_content = fp.read()
164
+ self.assertNotEqual(a_src_content, a_content)
165
+
166
+ with open(b, "r") as fp:
167
+ b_content = fp.read()
168
+ with open(b_src, "r") as fp:
169
+ b_src_content = fp.read()
170
+ self.assertEqual(b_src_content, b_content)
171
+
172
+ with open(c, "r") as fp:
173
+ c_content = fp.read()
174
+ with open(c_src, "r") as fp:
175
+ c_src_content = fp.read()
176
+ self.assertEqual(c_src_content, c_content)
177
+
124
178
 
125
179
  class TestLib(BaseTest):
126
180
  @classmethod
@@ -146,10 +200,6 @@ class TestLib(BaseTest):
146
200
  def setUp(self) -> None:
147
201
  self.events = None
148
202
 
149
- def load(self) -> None:
150
- self.lib.dump_events()
151
- self.events = event.load(self.TEST_PATH)
152
-
153
203
  def tearDown(self) -> None:
154
204
  # noinspection PyBroadException
155
205
  try:
@@ -37,7 +37,7 @@ class RunnerTests(BaseTest):
37
37
  exclude="tests",
38
38
  )
39
39
  instrument_config(config)
40
- runner = PytestRunner()
40
+ runner = PytestRunner(set_python_path=True)
41
41
  output = Path(BaseTest.TEST_DIR, "events").absolute()
42
42
  runner.run(
43
43
  Path(BaseTest.TEST_DIR), output, files=[Path("tests", "test_middle.py")]
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