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.
- {sflkit-0.2.18/src/sflkit.egg-info → sflkit-0.2.19}/PKG-INFO +1 -1
- {sflkit-0.2.18 → sflkit-0.2.19}/pyproject.toml +1 -1
- sflkit-0.2.19/src/sflkit/runners/resources/__init__.py +0 -0
- sflkit-0.2.19/src/sflkit/runners/resources/pytest_main.py +82 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/runners/run.py +47 -12
- {sflkit-0.2.18 → sflkit-0.2.19/src/sflkit.egg-info}/PKG-INFO +1 -1
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/SOURCES.txt +2 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_instrumentation.py +56 -6
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_runner.py +1 -1
- {sflkit-0.2.18 → sflkit-0.2.19}/LICENSE +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/README.md +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/setup.cfg +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/analysis_type.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/analyzer.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/factory.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/mapping.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/predicate.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/similarity.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/spectra.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/analysis/suggestion.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/cli.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/color.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/config.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/extract.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/finder.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/language.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/meta.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/extract.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/factory.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/finder.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/python/visitor.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/language/visitor.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/logger.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/mapping.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/event_file.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/model.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/model/scope.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit/runners/__init__.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/dependency_links.txt +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/entry_points.txt +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/requires.txt +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/src/sflkit.egg-info/top_level.txt +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_analysis_objects.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_cli.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_color.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_config.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_coverage.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_events.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_execution.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_language.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_predicates.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_scope.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_spectra.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_suggestions.py +0 -0
- {sflkit-0.2.18 → sflkit-0.2.19}/tests/test_visitors.py +0 -0
|
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
|
-
|
|
178
|
-
|
|
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
|
-
)
|
|
183
|
-
|
|
184
|
-
if
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
["
|
|
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
|
-
["
|
|
326
|
+
["python3", self.access] + test,
|
|
292
327
|
stdout=subprocess.PIPE,
|
|
293
328
|
stderr=subprocess.PIPE,
|
|
294
329
|
env=environ,
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|