skylos 1.1.11__py3-none-any.whl → 1.1.12__py3-none-any.whl
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.
Potentially problematic release.
This version of skylos might be problematic. Click here for more details.
- skylos/analyzer.py +89 -26
- skylos/constants.py +35 -0
- {skylos-1.1.11.dist-info → skylos-1.1.12.dist-info}/METADATA +1 -1
- {skylos-1.1.11.dist-info → skylos-1.1.12.dist-info}/RECORD +7 -6
- {skylos-1.1.11.dist-info → skylos-1.1.12.dist-info}/WHEEL +0 -0
- {skylos-1.1.11.dist-info → skylos-1.1.12.dist-info}/entry_points.txt +0 -0
- {skylos-1.1.11.dist-info → skylos-1.1.12.dist-info}/top_level.txt +0 -0
skylos/analyzer.py
CHANGED
|
@@ -3,29 +3,15 @@ import ast,sys,json,logging,re
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from skylos.visitor import Visitor
|
|
6
|
+
from skylos.constants import (
|
|
7
|
+
AUTO_CALLED, TEST_METHOD_PATTERN, MAGIC_METHODS,
|
|
8
|
+
TEST_LIFECYCLE_METHODS, TEST_IMPORT_PATTERNS, TEST_DECORATORS,
|
|
9
|
+
DEFAULT_EXCLUDE_FOLDERS
|
|
10
|
+
)
|
|
6
11
|
|
|
7
12
|
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s')
|
|
8
13
|
logger=logging.getLogger('Skylos')
|
|
9
14
|
|
|
10
|
-
AUTO_CALLED={"__init__","__enter__","__exit__"}
|
|
11
|
-
TEST_METHOD_PATTERN = re.compile(r"^test_\w+$")
|
|
12
|
-
MAGIC_METHODS={f"__{n}__"for n in["init","new","call","getattr","getattribute","enter","exit","str","repr","hash","eq","ne","lt","gt","le","ge","iter","next","contains","len","getitem","setitem","delitem","iadd","isub","imul","itruediv","ifloordiv","imod","ipow","ilshift","irshift","iand","ixor","ior","round","format","dir","abs","complex","int","float","bool","bytes","reduce","await","aiter","anext","add","sub","mul","truediv","floordiv","mod","divmod","pow","lshift","rshift","and","or","xor","radd","rsub","rmul","rtruediv","rfloordiv","rmod","rdivmod","rpow","rlshift","rrshift","rand","ror","rxor"]}
|
|
13
|
-
|
|
14
|
-
DEFAULT_EXCLUDE_FOLDERS = {
|
|
15
|
-
"__pycache__",
|
|
16
|
-
".git",
|
|
17
|
-
".pytest_cache",
|
|
18
|
-
".mypy_cache",
|
|
19
|
-
".tox",
|
|
20
|
-
"htmlcov",
|
|
21
|
-
".coverage",
|
|
22
|
-
"build",
|
|
23
|
-
"dist",
|
|
24
|
-
"*.egg-info",
|
|
25
|
-
"venv",
|
|
26
|
-
".venv"
|
|
27
|
-
}
|
|
28
|
-
|
|
29
15
|
def parse_exclude_folders(user_exclude_folders, use_defaults=True, include_folders=None):
|
|
30
16
|
exclude_set = set()
|
|
31
17
|
|
|
@@ -156,7 +142,79 @@ class Skylos:
|
|
|
156
142
|
return class_def.base_classes
|
|
157
143
|
|
|
158
144
|
return []
|
|
145
|
+
|
|
146
|
+
def _has_test_imports(self, file_path):
|
|
147
|
+
try:
|
|
148
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
149
|
+
content = f.read()
|
|
150
|
+
|
|
151
|
+
for test_import in TEST_IMPORT_PATTERNS:
|
|
152
|
+
if f"import {test_import}" in content or f"from {test_import}" in content:
|
|
153
|
+
return True
|
|
154
|
+
|
|
155
|
+
return False
|
|
156
|
+
except:
|
|
157
|
+
return False
|
|
158
|
+
|
|
159
|
+
def _is_test_file(self, file_path):
|
|
160
|
+
"""check if file locs indicates its a test file"""
|
|
161
|
+
file_str = str(file_path).lower()
|
|
162
|
+
|
|
163
|
+
if (file_str.endswith("test.py") or
|
|
164
|
+
file_str.endswith("_test.py") or
|
|
165
|
+
"test_" in file_str or
|
|
166
|
+
"/test/" in file_str or
|
|
167
|
+
"/tests/" in file_str or
|
|
168
|
+
"\\test\\" in file_str or
|
|
169
|
+
"\\tests\\" in file_str):
|
|
170
|
+
return True
|
|
171
|
+
|
|
172
|
+
return False
|
|
173
|
+
|
|
174
|
+
def _has_test_decorators(self, file_path):
|
|
175
|
+
"""Check if file uses test-related decorators"""
|
|
176
|
+
try:
|
|
177
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
178
|
+
content = f.read()
|
|
179
|
+
|
|
180
|
+
for decorator in TEST_DECORATORS:
|
|
181
|
+
if f"@{decorator}" in content:
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
return False
|
|
185
|
+
except:
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
def _is_test_related(self, definition):
|
|
189
|
+
|
|
190
|
+
if "." in definition.name:
|
|
191
|
+
class_name = definition.name.rsplit(".", 1)[0]
|
|
192
|
+
class_simple_name = class_name.split(".")[-1]
|
|
159
193
|
|
|
194
|
+
if (class_simple_name.startswith("Test") or
|
|
195
|
+
class_simple_name.endswith("Test") or
|
|
196
|
+
class_simple_name.endswith("TestCase")):
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
if (definition.type == "method" and
|
|
200
|
+
(TEST_METHOD_PATTERN.match(definition.simple_name) or
|
|
201
|
+
definition.simple_name in TEST_LIFECYCLE_METHODS)):
|
|
202
|
+
return True
|
|
203
|
+
|
|
204
|
+
# NOT for imports, variables, parameters
|
|
205
|
+
if definition.type in ("function", "method", "class"):
|
|
206
|
+
if self._is_test_file(definition.filename):
|
|
207
|
+
return True
|
|
208
|
+
|
|
209
|
+
if self._has_test_imports(definition.filename):
|
|
210
|
+
return True
|
|
211
|
+
|
|
212
|
+
## check decorators -- test related
|
|
213
|
+
if self._has_test_decorators(definition.filename):
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
return False
|
|
217
|
+
|
|
160
218
|
def _apply_heuristics(self):
|
|
161
219
|
class_methods=defaultdict(list)
|
|
162
220
|
for d in self.defs.values():
|
|
@@ -180,6 +238,16 @@ class Skylos:
|
|
|
180
238
|
if d.type != "parameter" and (d.simple_name in MAGIC_METHODS or (d.simple_name.startswith("__") and d.simple_name.endswith("__"))):
|
|
181
239
|
d.confidence = 0
|
|
182
240
|
|
|
241
|
+
if (d.type == "import" and d.name.startswith("__future__.") and
|
|
242
|
+
d.simple_name in ("annotations", "absolute_import", "division",
|
|
243
|
+
"print_function", "unicode_literals", "generator_stop")):
|
|
244
|
+
d.confidence = 0
|
|
245
|
+
|
|
246
|
+
if (d.simple_name.startswith("_") and
|
|
247
|
+
not d.simple_name.startswith("__") and
|
|
248
|
+
d.simple_name != "_"):
|
|
249
|
+
d.confidence = 0
|
|
250
|
+
|
|
183
251
|
if not d.simple_name.startswith("_") and d.type in ("function", "method", "class"):
|
|
184
252
|
d.confidence = min(d.confidence, 90)
|
|
185
253
|
|
|
@@ -192,13 +260,8 @@ class Skylos:
|
|
|
192
260
|
if d.type == "variable" and d.simple_name == "_":
|
|
193
261
|
d.confidence = 0
|
|
194
262
|
|
|
195
|
-
if
|
|
196
|
-
|
|
197
|
-
class_simple_name = class_name.split(".")[-1]
|
|
198
|
-
if (class_simple_name.startswith("Test") or
|
|
199
|
-
class_simple_name.endswith("Test") or
|
|
200
|
-
class_simple_name.endswith("TestCase")):
|
|
201
|
-
d.confidence = 0
|
|
263
|
+
if self._is_test_related(d):
|
|
264
|
+
d.confidence = 0
|
|
202
265
|
|
|
203
266
|
def analyze(self, path, thr=60, exclude_folders=None):
|
|
204
267
|
|
skylos/constants.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
AUTO_CALLED={"__init__","__enter__","__exit__"}
|
|
4
|
+
TEST_METHOD_PATTERN = re.compile(r"^test_\w+$")
|
|
5
|
+
MAGIC_METHODS={f"__{n}__"for n in["init","new","call","getattr","getattribute","enter","exit","str","repr","hash","eq","ne","lt","gt","le","ge","iter","next","contains","len","getitem","setitem","delitem","iadd","isub","imul","itruediv","ifloordiv","imod","ipow","ilshift","irshift","iand","ixor","ior","round","format","dir","abs","complex","int","float","bool","bytes","reduce","await","aiter","anext","add","sub","mul","truediv","floordiv","mod","divmod","pow","lshift","rshift","and","or","xor","radd","rsub","rmul","rtruediv","rfloordiv","rmod","rdivmod","rpow","rlshift","rrshift","rand","ror","rxor"]}
|
|
6
|
+
TEST_LIFECYCLE_METHODS = {
|
|
7
|
+
"setUp", "tearDown", "setUpClass", "tearDownClass",
|
|
8
|
+
"setUpModule", "tearDownModule", "setup_method", "teardown_method",
|
|
9
|
+
"setup_class", "teardown_class", "setup_function", "teardown_function"
|
|
10
|
+
}
|
|
11
|
+
TEST_IMPORT_PATTERNS = {
|
|
12
|
+
"unittest", "unittest.mock", "mock", "pytest", "nose", "nose2",
|
|
13
|
+
"responses", "requests_mock", "freezegun", "factory_boy",
|
|
14
|
+
"hypothesis", "sure", "expects", "testfixtures", "faker"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
TEST_DECORATORS = {
|
|
18
|
+
"patch", "mock", "pytest.fixture", "pytest.mark", "given",
|
|
19
|
+
"responses.activate", "freeze_time", "patch.object", "patch.dict"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
DEFAULT_EXCLUDE_FOLDERS = {
|
|
23
|
+
"__pycache__",
|
|
24
|
+
".git",
|
|
25
|
+
".pytest_cache",
|
|
26
|
+
".mypy_cache",
|
|
27
|
+
".tox",
|
|
28
|
+
"htmlcov",
|
|
29
|
+
".coverage",
|
|
30
|
+
"build",
|
|
31
|
+
"dist",
|
|
32
|
+
"*.egg-info",
|
|
33
|
+
"venv",
|
|
34
|
+
".venv"
|
|
35
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
skylos/__init__.py,sha256=ZZWhq0TZ3G-yDi9inbYvMn8OBes-pqo1aYB5EivuxFI,152
|
|
2
|
-
skylos/analyzer.py,sha256=
|
|
2
|
+
skylos/analyzer.py,sha256=r3Em6cHSUY1xEwOfQjHbtqLC9vfPwRrwZxN6HrPfRCk,15012
|
|
3
3
|
skylos/cli.py,sha256=7lcRFc3zailK2cPCWk6yT-EF0oeY_CmBo6TyD5m6c5Y,17355
|
|
4
|
+
skylos/constants.py,sha256=xv4BAYWS5R48nA3n_PiZtYQNqBJHS42QVIBSpxl3ZuQ,1538
|
|
4
5
|
skylos/visitor.py,sha256=0h07CNS6RnWi3vMjWO0sexzePRXIAfPjQib8Qxu11oY,11740
|
|
5
6
|
test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
7
|
test/compare_tools.py,sha256=0g9PDeJlbst-7hOaQzrL4MiJFQKpqM8q8VeBGzpPczg,22738
|
|
@@ -18,8 +19,8 @@ test/sample_repo/sample_repo/commands.py,sha256=b6gQ9YDabt2yyfqGbOpLo0osF7wya8O4
|
|
|
18
19
|
test/sample_repo/sample_repo/models.py,sha256=xXIg3pToEZwKuUCmKX2vTlCF_VeFA0yZlvlBVPIy5Qw,3320
|
|
19
20
|
test/sample_repo/sample_repo/routes.py,sha256=8yITrt55BwS01G7nWdESdx8LuxmReqop1zrGUKPeLi8,2475
|
|
20
21
|
test/sample_repo/sample_repo/utils.py,sha256=S56hEYh8wkzwsD260MvQcmUFOkw2EjFU27nMLFE6G2k,1103
|
|
21
|
-
skylos-1.1.
|
|
22
|
-
skylos-1.1.
|
|
23
|
-
skylos-1.1.
|
|
24
|
-
skylos-1.1.
|
|
25
|
-
skylos-1.1.
|
|
22
|
+
skylos-1.1.12.dist-info/METADATA,sha256=a99JTCI1FND6v_6OPumg5O8A1lvMqBTiAcGiQ1T4CEc,225
|
|
23
|
+
skylos-1.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
skylos-1.1.12.dist-info/entry_points.txt,sha256=zzRpN2ByznlQoLeuLolS_TFNYSQxUGBL1EXQsAd6bIA,43
|
|
25
|
+
skylos-1.1.12.dist-info/top_level.txt,sha256=f8GA_7KwfaEopPMP8-EXDQXaqd4IbsOQPakZy01LkdQ,12
|
|
26
|
+
skylos-1.1.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|