skylos 1.2.2__py3-none-any.whl → 2.0.0__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/__init__.py +1 -1
- skylos/analyzer.py +58 -95
- skylos/cli.py +46 -36
- skylos/constants.py +25 -10
- skylos/framework_aware.py +8 -2
- skylos/server.py +560 -0
- skylos/test_aware.py +0 -1
- skylos/visitor.py +70 -56
- {skylos-1.2.2.dist-info → skylos-2.0.0.dist-info}/METADATA +1 -1
- {skylos-1.2.2.dist-info → skylos-2.0.0.dist-info}/RECORD +13 -12
- {skylos-1.2.2.dist-info → skylos-2.0.0.dist-info}/WHEEL +0 -0
- {skylos-1.2.2.dist-info → skylos-2.0.0.dist-info}/entry_points.txt +0 -0
- {skylos-1.2.2.dist-info → skylos-2.0.0.dist-info}/top_level.txt +0 -0
skylos/visitor.py
CHANGED
|
@@ -7,22 +7,25 @@ DBG = bool(int(os.getenv("SKYLOS_DEBUG", "0")))
|
|
|
7
7
|
log = logging.getLogger("Skylos")
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
PYTHON_BUILTINS={"print","len","str","int","float","list","dict","set","tuple","range","open",
|
|
11
|
-
|
|
10
|
+
PYTHON_BUILTINS={"print", "len", "str", "int", "float", "list", "dict", "set", "tuple", "range", "open",
|
|
11
|
+
"super", "object", "type", "enumerate", "zip", "map", "filter", "sorted", "sum", "min",
|
|
12
|
+
"next", "iter", "bytes", "bytearray", "format", "round", "abs", "complex", "hash", "id", "bool", "callable",
|
|
13
|
+
"getattr", "max", "all", "any", "setattr", "hasattr", "isinstance", "globals", "locals",
|
|
14
|
+
"vars", "dir" ,"property", "classmethod", "staticmethod"}
|
|
15
|
+
DYNAMIC_PATTERNS={"getattr", "globals", "eval", "exec"}
|
|
12
16
|
|
|
13
17
|
class Definition:
|
|
14
|
-
__slots__ = ('name', 'type', 'filename', 'line', 'simple_name', 'confidence', 'references', 'is_exported', 'in_init')
|
|
15
18
|
|
|
16
|
-
def __init__(self,
|
|
17
|
-
self.name =
|
|
19
|
+
def __init__(self, name, t, filename, line):
|
|
20
|
+
self.name = name
|
|
18
21
|
self.type = t
|
|
19
|
-
self.filename =
|
|
20
|
-
self.line =
|
|
21
|
-
self.simple_name =
|
|
22
|
+
self.filename = filename
|
|
23
|
+
self.line = line
|
|
24
|
+
self.simple_name = name.split('.')[-1]
|
|
22
25
|
self.confidence = 100
|
|
23
26
|
self.references = 0
|
|
24
27
|
self.is_exported = False
|
|
25
|
-
self.in_init = "__init__.py" in str(
|
|
28
|
+
self.in_init = "__init__.py" in str(filename)
|
|
26
29
|
|
|
27
30
|
def to_dict(self):
|
|
28
31
|
if self.type == "method" and "." in self.name:
|
|
@@ -48,26 +51,30 @@ class Definition:
|
|
|
48
51
|
|
|
49
52
|
class Visitor(ast.NodeVisitor):
|
|
50
53
|
def __init__(self,mod,file):
|
|
51
|
-
self.mod=mod
|
|
52
|
-
self.file=file
|
|
53
|
-
self.defs=[]
|
|
54
|
-
self.refs=[]
|
|
55
|
-
self.cls=None
|
|
56
|
-
self.alias={}
|
|
57
|
-
self.dyn=set()
|
|
58
|
-
self.exports=set()
|
|
59
|
-
self.current_function_scope
|
|
60
|
-
self.current_function_params
|
|
61
|
-
|
|
62
|
-
def add_def(self,
|
|
63
|
-
if
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
self.mod= mod
|
|
55
|
+
self.file= file
|
|
56
|
+
self.defs= []
|
|
57
|
+
self.refs= []
|
|
58
|
+
self.cls= None
|
|
59
|
+
self.alias= {}
|
|
60
|
+
self.dyn= set()
|
|
61
|
+
self.exports= set()
|
|
62
|
+
self.current_function_scope= []
|
|
63
|
+
self.current_function_params= []
|
|
64
|
+
|
|
65
|
+
def add_def(self, name, t, line):
|
|
66
|
+
if name not in {d.name for d in self.defs}:
|
|
67
|
+
self.defs.append(Definition(name, t, self.file, line))
|
|
68
|
+
|
|
69
|
+
def add_ref(self, name):
|
|
70
|
+
self.refs.append((name, self.file))
|
|
71
|
+
|
|
72
|
+
def qual(self, name):
|
|
73
|
+
if name in self.alias:
|
|
74
|
+
return self.alias[name]
|
|
75
|
+
if name in PYTHON_BUILTINS:
|
|
76
|
+
return name
|
|
77
|
+
return f"{self.mod}.{name}" if self.mod else name
|
|
71
78
|
|
|
72
79
|
def visit_annotation(self, node):
|
|
73
80
|
if node is not None:
|
|
@@ -83,24 +90,23 @@ class Visitor(ast.NodeVisitor):
|
|
|
83
90
|
return
|
|
84
91
|
|
|
85
92
|
if DBG:
|
|
86
|
-
log.debug(f"
|
|
87
|
-
|
|
93
|
+
log.debug(f"parsing annotation: {annotation_str}")
|
|
94
|
+
|
|
88
95
|
|
|
89
96
|
try:
|
|
90
97
|
parsed = ast.parse(annotation_str, mode="eval")
|
|
91
98
|
self.visit(parsed.body)
|
|
92
|
-
except
|
|
99
|
+
except:
|
|
93
100
|
if DBG:
|
|
94
|
-
log.debug("
|
|
95
|
-
|
|
96
|
-
# keep going but dont swallow symbol names:
|
|
101
|
+
if DBG: log.debug("annotation parse failed")
|
|
102
|
+
|
|
97
103
|
for tok in re.findall(r"[A-Za-z_][A-Za-z0-9_]*", annotation_str):
|
|
98
104
|
self.add_ref(tok)
|
|
99
105
|
|
|
100
|
-
def visit_Import(self,node):
|
|
106
|
+
def visit_Import(self, node):
|
|
101
107
|
for a in node.names:
|
|
102
|
-
full=a.name
|
|
103
|
-
self.alias[a.asname or a.name.split(".")[-1]]=full
|
|
108
|
+
full= a.name
|
|
109
|
+
self.alias[a.asname or a.name.split(".")[-1]]= full
|
|
104
110
|
self.add_def(full,"import",node.lineno)
|
|
105
111
|
|
|
106
112
|
def visit_ImportFrom(self, node):
|
|
@@ -127,6 +133,7 @@ class Visitor(ast.NodeVisitor):
|
|
|
127
133
|
self.visit_annotation(arg.annotation)
|
|
128
134
|
for arg in args.posonlyargs:
|
|
129
135
|
self.visit_annotation(arg.annotation)
|
|
136
|
+
|
|
130
137
|
for arg in args.kwonlyargs:
|
|
131
138
|
self.visit_annotation(arg.annotation)
|
|
132
139
|
if args.vararg:
|
|
@@ -143,11 +150,11 @@ class Visitor(ast.NodeVisitor):
|
|
|
143
150
|
outer_scope_prefix = '.'.join(self.current_function_scope) + '.' if self.current_function_scope else ''
|
|
144
151
|
|
|
145
152
|
if self.cls:
|
|
146
|
-
name_parts
|
|
153
|
+
name_parts= [self.mod, self.cls, outer_scope_prefix + node.name]
|
|
147
154
|
else:
|
|
148
|
-
name_parts
|
|
155
|
+
name_parts= [self.mod, outer_scope_prefix + node.name]
|
|
149
156
|
|
|
150
|
-
qualified_name
|
|
157
|
+
qualified_name= ".".join(filter(None, name_parts))
|
|
151
158
|
|
|
152
159
|
self.add_def(qualified_name,"method"if self.cls else"function",node.lineno)
|
|
153
160
|
|
|
@@ -173,11 +180,11 @@ class Visitor(ast.NodeVisitor):
|
|
|
173
180
|
self.current_function_scope.pop()
|
|
174
181
|
self.current_function_params = old_params
|
|
175
182
|
|
|
176
|
-
visit_AsyncFunctionDef=visit_FunctionDef
|
|
183
|
+
visit_AsyncFunctionDef= visit_FunctionDef
|
|
177
184
|
|
|
178
|
-
def visit_ClassDef(self,node):
|
|
179
|
-
cname=f"{self.mod}.{node.name}"
|
|
180
|
-
self.add_def(cname,"class",node.lineno)
|
|
185
|
+
def visit_ClassDef(self, node):
|
|
186
|
+
cname =f"{self.mod}.{node.name}"
|
|
187
|
+
self.add_def(cname, "class",node.lineno)
|
|
181
188
|
|
|
182
189
|
for base in node.bases:
|
|
183
190
|
self.visit(base)
|
|
@@ -186,9 +193,13 @@ class Visitor(ast.NodeVisitor):
|
|
|
186
193
|
for decorator in node.decorator_list:
|
|
187
194
|
self.visit(decorator)
|
|
188
195
|
|
|
189
|
-
prev=self.cls
|
|
190
|
-
|
|
191
|
-
self.cls=
|
|
196
|
+
prev= self.cls
|
|
197
|
+
|
|
198
|
+
self.cls= node.name
|
|
199
|
+
for b in node.body:
|
|
200
|
+
self.visit(b)
|
|
201
|
+
|
|
202
|
+
self.cls= prev
|
|
192
203
|
|
|
193
204
|
def visit_AnnAssign(self, node):
|
|
194
205
|
self.visit_annotation(node.annotation)
|
|
@@ -215,20 +226,22 @@ class Visitor(ast.NodeVisitor):
|
|
|
215
226
|
def visit_Assign(self, node):
|
|
216
227
|
def process_target_for_def(target_node):
|
|
217
228
|
if isinstance(target_node, ast.Name):
|
|
218
|
-
|
|
219
|
-
if
|
|
229
|
+
name_simple = target_node.id
|
|
230
|
+
if name_simple == "__all__" and not self.current_function_scope and not self.cls:
|
|
220
231
|
return
|
|
221
232
|
|
|
222
233
|
scope_parts = [self.mod]
|
|
234
|
+
|
|
223
235
|
if self.cls:
|
|
224
236
|
scope_parts.append(self.cls)
|
|
237
|
+
|
|
225
238
|
if self.current_function_scope:
|
|
226
239
|
scope_parts.extend(self.current_function_scope)
|
|
227
240
|
|
|
228
241
|
prefix = '.'.join(filter(None, scope_parts))
|
|
229
|
-
|
|
242
|
+
var_name = f"{prefix}.{name_simple}" if prefix else name_simple
|
|
230
243
|
|
|
231
|
-
self.add_def(
|
|
244
|
+
self.add_def(var_name, "variable", target_node.lineno)
|
|
232
245
|
|
|
233
246
|
elif isinstance(target_node, (ast.Tuple, ast.List)):
|
|
234
247
|
for elt in target_node.elts:
|
|
@@ -248,8 +261,8 @@ class Visitor(ast.NodeVisitor):
|
|
|
248
261
|
value = elt.s
|
|
249
262
|
|
|
250
263
|
if value is not None:
|
|
251
|
-
|
|
252
|
-
self.add_ref(
|
|
264
|
+
export_name = f"{self.mod}.{value}" if self.mod else value
|
|
265
|
+
self.add_ref(export_name)
|
|
253
266
|
self.add_ref(value)
|
|
254
267
|
|
|
255
268
|
self.generic_visit(node)
|
|
@@ -285,12 +298,13 @@ class Visitor(ast.NodeVisitor):
|
|
|
285
298
|
elif isinstance(node.func, ast.Name) and node.func.id in ("eval", "exec"):
|
|
286
299
|
self.dyn.add(self.mod.split(".")[0] if self.mod else "")
|
|
287
300
|
|
|
288
|
-
def visit_Name(self,node):
|
|
289
|
-
if isinstance(node.ctx,ast.Load):
|
|
301
|
+
def visit_Name(self, node):
|
|
302
|
+
if isinstance(node.ctx, ast.Load):
|
|
290
303
|
for param_name, param_full_name in self.current_function_params:
|
|
291
304
|
if node.id == param_name:
|
|
292
305
|
self.add_ref(param_full_name)
|
|
293
306
|
break
|
|
307
|
+
|
|
294
308
|
else:
|
|
295
309
|
# not parameter, handle normally
|
|
296
310
|
qualified = self.qual(node.id)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
skylos/__init__.py,sha256=
|
|
2
|
-
skylos/analyzer.py,sha256=
|
|
3
|
-
skylos/cli.py,sha256=
|
|
4
|
-
skylos/constants.py,sha256=
|
|
5
|
-
skylos/framework_aware.py,sha256=
|
|
6
|
-
skylos/
|
|
7
|
-
skylos/
|
|
1
|
+
skylos/__init__.py,sha256=xIvJTzzvvgfcQWYMckJFXNNlXPpU1gjO1IldPy7T_N4,151
|
|
2
|
+
skylos/analyzer.py,sha256=TDr_szli65cuQWD6BUcQCUFleM1R-QZD0uRUoHlU6As,14145
|
|
3
|
+
skylos/cli.py,sha256=Xqc_vnueic0D39FI0YzMtJObLsn8MqFFCUnY1nrpEt4,18115
|
|
4
|
+
skylos/constants.py,sha256=vAfKls0OuR5idtXzeMDfYv5-wLtYWDe1NW5TSUJT8RI,1636
|
|
5
|
+
skylos/framework_aware.py,sha256=vbZ1CZIL_2TOEkdH8uVSPPihLM2ctqA01zEHL8HG5sw,5768
|
|
6
|
+
skylos/server.py,sha256=5Rlgy3LdE8I5TWRJJh0n19JqhVYaAOc9fUtRjL-PpX8,16270
|
|
7
|
+
skylos/test_aware.py,sha256=kxYoMG2m02kbMlxtFOM-MWJO8qqxHviP9HgAMbKRfvU,2304
|
|
8
|
+
skylos/visitor.py,sha256=FXNck0qjVB3lfp4X63D5-bE1NsvUTbfvT17ivIevhjk,12654
|
|
8
9
|
test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
10
|
test/compare_tools.py,sha256=0g9PDeJlbst-7hOaQzrL4MiJFQKpqM8q8VeBGzpPczg,22738
|
|
10
11
|
test/conftest.py,sha256=57sTF6vLL5U0CVKwGQFJcRs6n7t1dEHIriQoSluNmAI,6418
|
|
@@ -25,8 +26,8 @@ test/sample_repo/sample_repo/commands.py,sha256=b6gQ9YDabt2yyfqGbOpLo0osF7wya8O4
|
|
|
25
26
|
test/sample_repo/sample_repo/models.py,sha256=xXIg3pToEZwKuUCmKX2vTlCF_VeFA0yZlvlBVPIy5Qw,3320
|
|
26
27
|
test/sample_repo/sample_repo/routes.py,sha256=8yITrt55BwS01G7nWdESdx8LuxmReqop1zrGUKPeLi8,2475
|
|
27
28
|
test/sample_repo/sample_repo/utils.py,sha256=S56hEYh8wkzwsD260MvQcmUFOkw2EjFU27nMLFE6G2k,1103
|
|
28
|
-
skylos-
|
|
29
|
-
skylos-
|
|
30
|
-
skylos-
|
|
31
|
-
skylos-
|
|
32
|
-
skylos-
|
|
29
|
+
skylos-2.0.0.dist-info/METADATA,sha256=gVlJTPqEjfbbnn0TGbDT5aEx8TBtD1r-mitvOfJBI-Y,224
|
|
30
|
+
skylos-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
skylos-2.0.0.dist-info/entry_points.txt,sha256=zzRpN2ByznlQoLeuLolS_TFNYSQxUGBL1EXQsAd6bIA,43
|
|
32
|
+
skylos-2.0.0.dist-info/top_level.txt,sha256=f8GA_7KwfaEopPMP8-EXDQXaqd4IbsOQPakZy01LkdQ,12
|
|
33
|
+
skylos-2.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|