skylos 1.2.2__py3-none-any.whl → 2.1.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/visitor.py CHANGED
@@ -1,28 +1,27 @@
1
1
  #!/usr/bin/env python3
2
2
  import ast
3
3
  from pathlib import Path
4
- import os
5
- import re, logging, traceback
6
- DBG = bool(int(os.getenv("SKYLOS_DEBUG", "0")))
7
- log = logging.getLogger("Skylos")
4
+ import re
8
5
 
9
-
10
- PYTHON_BUILTINS={"print","len","str","int","float","list","dict","set","tuple","range","open","super","object","type","enumerate","zip","map","filter","sorted","reversed","sum","min","max","all","any","next","iter","repr","chr","ord","bytes","bytearray","memoryview","format","round","abs","pow","divmod","complex","hash","id","bool","callable","getattr","setattr","delattr","hasattr","isinstance","issubclass","globals","locals","vars","dir","property","classmethod","staticmethod"}
11
- DYNAMIC_PATTERNS={"getattr","globals","eval","exec"}
6
+ PYTHON_BUILTINS={"print", "len", "str", "int", "float", "list", "dict", "set", "tuple", "range", "open",
7
+ "super", "object", "type", "enumerate", "zip", "map", "filter", "sorted", "sum", "min",
8
+ "next", "iter", "bytes", "bytearray", "format", "round", "abs", "complex", "hash", "id", "bool", "callable",
9
+ "getattr", "max", "all", "any", "setattr", "hasattr", "isinstance", "globals", "locals",
10
+ "vars", "dir" ,"property", "classmethod", "staticmethod"}
11
+ DYNAMIC_PATTERNS={"getattr", "globals", "eval", "exec"}
12
12
 
13
13
  class Definition:
14
- __slots__ = ('name', 'type', 'filename', 'line', 'simple_name', 'confidence', 'references', 'is_exported', 'in_init')
15
14
 
16
- def __init__(self, n, t, f, l):
17
- self.name = n
15
+ def __init__(self, name, t, filename, line):
16
+ self.name = name
18
17
  self.type = t
19
- self.filename = f
20
- self.line = l
21
- self.simple_name = n.split('.')[-1]
18
+ self.filename = filename
19
+ self.line = line
20
+ self.simple_name = name.split('.')[-1]
22
21
  self.confidence = 100
23
22
  self.references = 0
24
23
  self.is_exported = False
25
- self.in_init = "__init__.py" in str(f)
24
+ self.in_init = "__init__.py" in str(filename)
26
25
 
27
26
  def to_dict(self):
28
27
  if self.type == "method" and "." in self.name:
@@ -48,26 +47,33 @@ class Definition:
48
47
 
49
48
  class Visitor(ast.NodeVisitor):
50
49
  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,n,t,l):
63
- if n not in{d.name for d in self.defs}:self.defs.append(Definition(n,t,self.file,l))
64
-
65
- def add_ref(self,n):self.refs.append((n,self.file))
66
-
67
- def qual(self,n):
68
- if n in self.alias:return self.alias[n]
69
- if n in PYTHON_BUILTINS:return n
70
- return f"{self.mod}.{n}"if self.mod else n
50
+ self.mod= mod
51
+ self.file= file
52
+ self.defs= []
53
+ self.refs= []
54
+ self.cls= None
55
+ self.alias= {}
56
+ self.dyn= set()
57
+ self.exports= set()
58
+ self.current_function_scope= []
59
+ self.current_function_params= []
60
+ self.local_var_maps = []
61
+ self.in_cst_class = 0
62
+ self.local_type_maps = []
63
+
64
+ def add_def(self, name, t, line):
65
+ if name not in {d.name for d in self.defs}:
66
+ self.defs.append(Definition(name, t, self.file, line))
67
+
68
+ def add_ref(self, name):
69
+ self.refs.append((name, self.file))
70
+
71
+ def qual(self, name):
72
+ if name in self.alias:
73
+ return self.alias[name]
74
+ if name in PYTHON_BUILTINS:
75
+ return name
76
+ return f"{self.mod}.{name}" if self.mod else name
71
77
 
72
78
  def visit_annotation(self, node):
73
79
  if node is not None:
@@ -82,25 +88,17 @@ class Visitor(ast.NodeVisitor):
82
88
  if not isinstance(annotation_str, str):
83
89
  return
84
90
 
85
- if DBG:
86
- log.debug(f"[visitor] parsing string annotation {annotation_str!r} "
87
- f"in {self.filename}:{getattr(self, 'line', '?')}")
88
-
89
91
  try:
90
92
  parsed = ast.parse(annotation_str, mode="eval")
91
93
  self.visit(parsed.body)
92
- except Exception:
93
- if DBG:
94
- log.debug("[visitor] inner-annotation parse failed:\n" +
95
- traceback.format_exc())
96
- # keep going but dont swallow symbol names:
94
+ except:
97
95
  for tok in re.findall(r"[A-Za-z_][A-Za-z0-9_]*", annotation_str):
98
96
  self.add_ref(tok)
99
97
 
100
- def visit_Import(self,node):
98
+ def visit_Import(self, node):
101
99
  for a in node.names:
102
- full=a.name
103
- self.alias[a.asname or a.name.split(".")[-1]]=full
100
+ full= a.name
101
+ self.alias[a.asname or a.name.split(".")[-1]]= full
104
102
  self.add_def(full,"import",node.lineno)
105
103
 
106
104
  def visit_ImportFrom(self, node):
@@ -127,6 +125,7 @@ class Visitor(ast.NodeVisitor):
127
125
  self.visit_annotation(arg.annotation)
128
126
  for arg in args.posonlyargs:
129
127
  self.visit_annotation(arg.annotation)
128
+
130
129
  for arg in args.kwonlyargs:
131
130
  self.visit_annotation(arg.annotation)
132
131
  if args.vararg:
@@ -143,16 +142,18 @@ class Visitor(ast.NodeVisitor):
143
142
  outer_scope_prefix = '.'.join(self.current_function_scope) + '.' if self.current_function_scope else ''
144
143
 
145
144
  if self.cls:
146
- name_parts = [self.mod, self.cls, outer_scope_prefix + node.name]
145
+ name_parts= [self.mod, self.cls, outer_scope_prefix + node.name]
147
146
  else:
148
- name_parts = [self.mod, outer_scope_prefix + node.name]
147
+ name_parts= [self.mod, outer_scope_prefix + node.name]
149
148
 
150
- qualified_name = ".".join(filter(None, name_parts))
149
+ qualified_name= ".".join(filter(None, name_parts))
151
150
 
152
151
  self.add_def(qualified_name,"method"if self.cls else"function",node.lineno)
153
152
 
154
153
  self.current_function_scope.append(node.name)
155
-
154
+ self.local_var_maps.append({})
155
+ self.local_type_maps.append({})
156
+
156
157
  old_params = self.current_function_params
157
158
  self.current_function_params = []
158
159
 
@@ -172,32 +173,95 @@ class Visitor(ast.NodeVisitor):
172
173
 
173
174
  self.current_function_scope.pop()
174
175
  self.current_function_params = old_params
176
+ self.local_var_maps.pop()
177
+ self.local_type_maps.pop()
175
178
 
176
- visit_AsyncFunctionDef=visit_FunctionDef
179
+ visit_AsyncFunctionDef= visit_FunctionDef
177
180
 
178
- def visit_ClassDef(self,node):
179
- cname=f"{self.mod}.{node.name}"
180
- self.add_def(cname,"class",node.lineno)
181
+ def visit_ClassDef(self, node):
182
+ cname =f"{self.mod}.{node.name}"
183
+ self.add_def(cname, "class",node.lineno)
184
+
185
+ is_cst = False
181
186
 
182
187
  for base in node.bases:
188
+ base_name = ""
189
+ if isinstance(base, ast.Attribute):
190
+ base_name = base.attr
191
+ elif isinstance(base, ast.Name):
192
+ base_name = base.id
183
193
  self.visit(base)
194
+ if base_name in {"CSTTransformer", "CSTVisitor"}:
195
+ is_cst = True
184
196
  for keyword in node.keywords:
185
197
  self.visit(keyword.value)
186
198
  for decorator in node.decorator_list:
187
199
  self.visit(decorator)
188
200
 
189
- prev=self.cls;self.cls=node.name
190
- for b in node.body:self.visit(b)
191
- self.cls=prev
201
+ prev= self.cls
202
+ if is_cst:
203
+ self.in_cst_class += 1
204
+
205
+ self.cls= node.name
206
+ for b in node.body:
207
+ self.visit(b)
208
+
209
+ self.cls= prev
210
+ if is_cst:
211
+ self.in_cst_class -= 1
192
212
 
193
213
  def visit_AnnAssign(self, node):
194
214
  self.visit_annotation(node.annotation)
195
215
  if node.value:
196
216
  self.visit(node.value)
197
- self.visit(node.target)
217
+
218
+ def _define(t):
219
+ if isinstance(t, ast.Name):
220
+ name_simple = t.id
221
+ scope_parts = [self.mod]
222
+ if self.cls: scope_parts.append(self.cls)
223
+ if self.current_function_scope: scope_parts.extend(self.current_function_scope)
224
+ prefix = '.'.join(filter(None, scope_parts))
225
+ if prefix:
226
+ var_name = f"{prefix}.{name_simple}"
227
+ else:
228
+ var_name = name_simple
229
+
230
+ self.add_def(var_name, "variable", t.lineno)
231
+ if self.current_function_scope and self.local_var_maps:
232
+ self.local_var_maps[-1][name_simple] = var_name
233
+ elif isinstance(t, (ast.Tuple, ast.List)):
234
+ for elt in t.elts:
235
+ _define(elt)
236
+ _define(node.target)
198
237
 
199
238
  def visit_AugAssign(self, node):
200
- self.visit(node.target)
239
+ if isinstance(node.target, ast.Name):
240
+ nm = node.target.id
241
+ if (self.current_function_scope and
242
+ self.local_var_maps and
243
+ self.local_var_maps and
244
+ nm in self.local_var_maps[-1]):
245
+
246
+ self.add_ref(self.local_var_maps[-1][nm])
247
+
248
+ else:
249
+ self.add_ref(self.qual(nm))
250
+ scope_parts = [self.mod]
251
+ if self.cls: scope_parts.append(self.cls)
252
+
253
+ if self.current_function_scope: scope_parts.extend(self.current_function_scope)
254
+ prefix = '.'.join(filter(None, scope_parts))
255
+ if prefix:
256
+ var_name = f"{prefix}.{nm}"
257
+ else:
258
+ var_name = nm
259
+
260
+ self.add_def(var_name, "variable", node.lineno)
261
+ if self.current_function_scope and self.local_var_maps:
262
+ self.local_var_maps[-1][nm] = var_name
263
+ else:
264
+ self.visit(node.target)
201
265
  self.visit(node.value)
202
266
 
203
267
  def visit_Subscript(self, node):
@@ -215,8 +279,11 @@ class Visitor(ast.NodeVisitor):
215
279
  def visit_Assign(self, node):
216
280
  def process_target_for_def(target_node):
217
281
  if isinstance(target_node, ast.Name):
218
- var_name_simple = target_node.id
219
- if var_name_simple == "__all__" and not self.current_function_scope and not self.cls:
282
+ name_simple = target_node.id
283
+ if (name_simple == "METADATA_DEPENDENCIES"
284
+ and self.cls and self.in_cst_class > 0):
285
+ return
286
+ if name_simple == "__all__" and not self.current_function_scope and not self.cls:
220
287
  return
221
288
 
222
289
  scope_parts = [self.mod]
@@ -224,11 +291,16 @@ class Visitor(ast.NodeVisitor):
224
291
  scope_parts.append(self.cls)
225
292
  if self.current_function_scope:
226
293
  scope_parts.extend(self.current_function_scope)
227
-
294
+
228
295
  prefix = '.'.join(filter(None, scope_parts))
229
- qualified_var_name = f"{prefix}.{var_name_simple}" if prefix else var_name_simple
296
+ if prefix:
297
+ var_name = f"{prefix}.{name_simple}"
298
+ else:
299
+ var_name = name_simple
230
300
 
231
- self.add_def(qualified_var_name, "variable", target_node.lineno)
301
+ self.add_def(var_name, "variable", target_node.lineno)
302
+ if self.current_function_scope and self.local_var_maps:
303
+ self.local_var_maps[-1][name_simple] = var_name
232
304
 
233
305
  elif isinstance(target_node, (ast.Tuple, ast.List)):
234
306
  for elt in target_node.elts:
@@ -236,7 +308,7 @@ class Visitor(ast.NodeVisitor):
236
308
 
237
309
  for t in node.targets:
238
310
  process_target_for_def(t)
239
-
311
+
240
312
  for target in node.targets:
241
313
  if isinstance(target, ast.Name) and target.id == "__all__":
242
314
  if isinstance(node.value, (ast.List, ast.Tuple)):
@@ -246,12 +318,48 @@ class Visitor(ast.NodeVisitor):
246
318
  value = elt.value
247
319
  elif hasattr(elt, 's') and isinstance(elt.s, str):
248
320
  value = elt.s
249
-
321
+
250
322
  if value is not None:
251
- full_name_export = f"{self.mod}.{value}" if self.mod else value
252
- self.add_ref(full_name_export)
253
- self.add_ref(value)
254
-
323
+ if self.mod:
324
+ export_name = f"{self.mod}.{value}"
325
+ else:
326
+ export_name = value
327
+
328
+ self.add_ref(export_name)
329
+ self.add_ref(value)
330
+
331
+ try:
332
+ if isinstance(node.value, ast.Call):
333
+ callee = node.value.func
334
+ fqname = None
335
+
336
+ if isinstance(callee, ast.Name):
337
+ fqname = self.alias.get(callee.id, self.qual(callee.id))
338
+
339
+ elif isinstance(callee, ast.Attribute):
340
+ parts = []
341
+ cur = callee
342
+ while isinstance(cur, ast.Attribute):
343
+ parts.append(cur.attr)
344
+ cur = cur.value
345
+ head = None
346
+ if isinstance(cur, ast.Name):
347
+ head = self.alias.get(cur.id, self.qual(cur.id))
348
+ if head:
349
+ fqname = ".".join([head] + list(reversed(parts)))
350
+
351
+ if fqname and self.current_function_scope and self.local_type_maps:
352
+ def _mark_target(t):
353
+ if isinstance(t, ast.Name):
354
+ self.local_type_maps[-1][t.id] = fqname
355
+ elif isinstance(t, (ast.Tuple, ast.List)):
356
+ for elt in t.elts:
357
+ _mark_target(elt)
358
+ for t in node.targets:
359
+ _mark_target(t)
360
+ except Exception:
361
+ pass
362
+
255
363
  self.generic_visit(node)
256
364
 
257
365
  def visit_Call(self, node):
@@ -271,7 +379,10 @@ class Visitor(ast.NodeVisitor):
271
379
  elif isinstance(node.args[0], ast.Name):
272
380
  target_name = node.args[0].id
273
381
  if target_name != "self":
274
- self.dyn.add(self.mod.split(".")[0] if self.mod else "")
382
+ if self.mod:
383
+ self.dyn.add(self.mod.split(".")[0])
384
+ else:
385
+ self.dyn.add("")
275
386
 
276
387
  elif isinstance(node.func, ast.Name) and node.func.id == "globals":
277
388
  parent = getattr(node, 'parent', None)
@@ -283,32 +394,80 @@ class Visitor(ast.NodeVisitor):
283
394
  self.add_ref(f"{self.mod}.{func_name}")
284
395
 
285
396
  elif isinstance(node.func, ast.Name) and node.func.id in ("eval", "exec"):
286
- self.dyn.add(self.mod.split(".")[0] if self.mod else "")
397
+ root_mod = ""
398
+ if self.mod:
399
+ root_mod = self.mod.split(".")[0]
400
+ self.dyn.add(root_mod)
287
401
 
288
- def visit_Name(self,node):
289
- if isinstance(node.ctx,ast.Load):
402
+ def visit_Name(self, node):
403
+ if isinstance(node.ctx, ast.Load):
290
404
  for param_name, param_full_name in self.current_function_params:
291
405
  if node.id == param_name:
292
406
  self.add_ref(param_full_name)
293
- break
294
- else:
295
- # not parameter, handle normally
296
- qualified = self.qual(node.id)
297
- self.add_ref(qualified)
298
- if node.id in DYNAMIC_PATTERNS:
299
- self.dyn.add(self.mod.split(".")[0])
407
+ return
408
+
409
+ if (self.current_function_scope and
410
+ self.local_var_maps
411
+ and self.local_var_maps
412
+ and node.id in self.local_var_maps[-1]):
413
+
414
+ self.add_ref(self.local_var_maps[-1][node.id])
415
+ return
416
+
417
+ qualified = self.qual(node.id)
418
+ self.add_ref(qualified)
419
+ if node.id in DYNAMIC_PATTERNS:
420
+ self.dyn.add(self.mod.split(".")[0])
300
421
 
301
422
  def visit_Attribute(self, node):
302
423
  self.generic_visit(node)
303
- if isinstance(node.ctx, ast.Load) and isinstance(node.value, ast.Name):
304
- if node.value.id in [param_name for param_name, _ in self.current_function_params]:
305
- # mark parameter as referenced
306
- for param_name, param_full_name in self.current_function_params:
307
- if node.value.id == param_name:
308
- self.add_ref(param_full_name)
309
- break
310
-
311
- self.add_ref(f"{self.qual(node.value.id)}.{node.attr}")
424
+
425
+ if not isinstance(node.ctx, ast.Load):
426
+ return
427
+
428
+ if isinstance(node.value, ast.Name):
429
+ base = node.value.id
430
+
431
+ param_hit = None
432
+ for param_name, param_full in self.current_function_params:
433
+ if base == param_name:
434
+ param_hit = (param_name, param_full)
435
+ break
436
+
437
+ if param_hit:
438
+ self.add_ref(param_hit[1])
439
+
440
+ if self.cls and base in {"self", "cls"}:
441
+ if self.mod:
442
+ owner = f"{self.mod}.{self.cls}"
443
+ else:
444
+ owner = self.cls
445
+
446
+ self.add_ref(f"{owner}.{node.attr}")
447
+ return
448
+
449
+ if (self.current_function_scope and
450
+ self.local_type_maps and
451
+ self.local_type_maps[-1].get(base)):
452
+
453
+ self.add_ref(f"{self.local_type_maps[-1][base]}.{node.attr}")
454
+ return
455
+
456
+ self.add_ref(f"{self.qual(base)}.{node.attr}")
457
+
458
+ def visit_NamedExpr(self, node):
459
+ self.visit(node.value)
460
+ if isinstance(node.target, ast.Name):
461
+ nm = node.target.id
462
+ scope_parts = [self.mod]
463
+ if self.cls: scope_parts.append(self.cls)
464
+ if self.current_function_scope: scope_parts.extend(self.current_function_scope)
465
+ prefix = '.'.join(filter(None, scope_parts))
466
+ var_name = f"{prefix}.{nm}" if prefix else nm
467
+ self.add_def(var_name, "variable", node.lineno)
468
+ if self.current_function_scope and self.local_var_maps:
469
+ self.local_var_maps[-1][nm] = var_name
470
+ self.add_ref(var_name)
312
471
 
313
472
  def visit_keyword(self, node):
314
473
  self.visit(node.value)
@@ -1,8 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skylos
3
- Version: 1.2.2
3
+ Version: 2.1.0
4
4
  Summary: A static analysis tool for Python codebases
5
5
  Author-email: oha <aaronoh2015@gmail.com>
6
6
  Requires-Python: >=3.9
7
7
  Requires-Dist: inquirer>=3.0.0
8
+ Requires-Dist: flask>=2.1.0
9
+ Requires-Dist: flask-cors>=3.0.0
10
+ Requires-Dist: libcst>=1.8.2
8
11
  Dynamic: requires-python
@@ -1,10 +1,12 @@
1
- skylos/__init__.py,sha256=ZZWhq0TZ3G-yDi9inbYvMn8OBes-pqo1aYB5EivuxFI,152
2
- skylos/analyzer.py,sha256=cO6J-hOsdJLoyw2vkL2BdX_fS-i5R50suLuh1QqPly4,15144
3
- skylos/cli.py,sha256=6udZY4vLU6PFzVMkaiCLCRcLXgquyHdmf4rIOAPosWc,18266
4
- skylos/constants.py,sha256=F1kMjuTxfw2hJjd0SeOQcgex5WhHMUhXCzOlVmwuACs,1230
5
- skylos/framework_aware.py,sha256=p7BGoFnzkpaLJoE3M5qgyIeZvXx17tOkdyXgeqGKmqU,5804
6
- skylos/test_aware.py,sha256=cduaWMcFsuzIEQWAMFPC58xGk8NUU3SbUS0ChRPedv8,2372
7
- skylos/visitor.py,sha256=MnWyzs0b2JOD2Nj1Iu7ZIZHCr7fRC92PY1bsT8bdgXg,12796
1
+ skylos/__init__.py,sha256=sr_HNrjL2O7hbyh_8vN2tG1ZKw8sXJVegKjp3G8Iz9c,151
2
+ skylos/analyzer.py,sha256=JoQ_otvLmI5k64y3h11jVZEWuA6u3npY15Nwy1vrGi0,14995
3
+ skylos/cli.py,sha256=bRxhvKkw_VWQVHT6WxKyX9i3qJjGuJJaEJ3QI8FIpZw,15887
4
+ skylos/codemods.py,sha256=A5dNwTJiYtgP3Mv8NQ03etdfi9qNHSECv1GRpLyDCYU,3213
5
+ skylos/constants.py,sha256=vAfKls0OuR5idtXzeMDfYv5-wLtYWDe1NW5TSUJT8RI,1636
6
+ skylos/framework_aware.py,sha256=eX4oU0jQwDWejkkW4kjRNctre27sVLHK1CTDDiqPqRw,13054
7
+ skylos/server.py,sha256=5Rlgy3LdE8I5TWRJJh0n19JqhVYaAOc9fUtRjL-PpX8,16270
8
+ skylos/test_aware.py,sha256=kxYoMG2m02kbMlxtFOM-MWJO8qqxHviP9HgAMbKRfvU,2304
9
+ skylos/visitor.py,sha256=i-YWVenc8mG0dWzYi945HmktIE2RkgL7rBT7VUnhkLI,18073
8
10
  test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
11
  test/compare_tools.py,sha256=0g9PDeJlbst-7hOaQzrL4MiJFQKpqM8q8VeBGzpPczg,22738
10
12
  test/conftest.py,sha256=57sTF6vLL5U0CVKwGQFJcRs6n7t1dEHIriQoSluNmAI,6418
@@ -12,8 +14,9 @@ test/diagnostics.py,sha256=ExuFOCVpc9BDwNYapU96vj9RXLqxji32Sv6wVF4nJYU,13802
12
14
  test/test_analyzer.py,sha256=vZ-0cSF_otm7ZYdp6U3a8eWGwRZ6Tf0tVuJxYqcxdqM,22816
13
15
  test/test_changes_analyzer.py,sha256=l1hspCFz-sF8gqOilJvntUDuGckwhYsVtzvSRB13ZWw,5085
14
16
  test/test_cli.py,sha256=rtdKzanDRJT_F92jKkCQFdhvlfwVJxfXKO8Hrbn-mIg,13180
17
+ test/test_codemods.py,sha256=Tbp9jE95HDl77EenTmyTtB1Sc3L8fwY9xiMNVDN5lxo,4522
15
18
  test/test_constants.py,sha256=pMuDy0UpC81zENMDCeK6Bqmm3BR_HHZQSlMG-9TgOm0,12602
16
- test/test_framework_aware.py,sha256=tJ7bnhiGeSdsAvrWaGJO5ovTrw9n9BBk6o1HCw15yDA,11693
19
+ test/test_framework_aware.py,sha256=G9va1dEQ31wsvd4X7ROf_1YhhAQG5CogB7v0hYCojQ8,8802
17
20
  test/test_integration.py,sha256=bNKGUe-w0xEZEdnoQNHbssvKMGs9u9fmFQTOz1lX9_k,12398
18
21
  test/test_skylos.py,sha256=kz77STrS4k3Eez5RDYwGxOg2WH3e7zNZPUYEaTLbGTs,15608
19
22
  test/test_test_aware.py,sha256=VmbR_MQY0m941CAxxux8OxJHIr7l8crfWRouSeBMhIo,9390
@@ -25,8 +28,8 @@ test/sample_repo/sample_repo/commands.py,sha256=b6gQ9YDabt2yyfqGbOpLo0osF7wya8O4
25
28
  test/sample_repo/sample_repo/models.py,sha256=xXIg3pToEZwKuUCmKX2vTlCF_VeFA0yZlvlBVPIy5Qw,3320
26
29
  test/sample_repo/sample_repo/routes.py,sha256=8yITrt55BwS01G7nWdESdx8LuxmReqop1zrGUKPeLi8,2475
27
30
  test/sample_repo/sample_repo/utils.py,sha256=S56hEYh8wkzwsD260MvQcmUFOkw2EjFU27nMLFE6G2k,1103
28
- skylos-1.2.2.dist-info/METADATA,sha256=2cvKXdg5thOkSpCbaN7jQ3Lwa10jVmVVB6KvDST3ZOw,224
29
- skylos-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- skylos-1.2.2.dist-info/entry_points.txt,sha256=zzRpN2ByznlQoLeuLolS_TFNYSQxUGBL1EXQsAd6bIA,43
31
- skylos-1.2.2.dist-info/top_level.txt,sha256=f8GA_7KwfaEopPMP8-EXDQXaqd4IbsOQPakZy01LkdQ,12
32
- skylos-1.2.2.dist-info/RECORD,,
31
+ skylos-2.1.0.dist-info/METADATA,sha256=oE2audt2wkmDLNdDcZCHgmDxtrZY8gygMnDwI5Qi6V4,314
32
+ skylos-2.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ skylos-2.1.0.dist-info/entry_points.txt,sha256=zzRpN2ByznlQoLeuLolS_TFNYSQxUGBL1EXQsAd6bIA,43
34
+ skylos-2.1.0.dist-info/top_level.txt,sha256=f8GA_7KwfaEopPMP8-EXDQXaqd4IbsOQPakZy01LkdQ,12
35
+ skylos-2.1.0.dist-info/RECORD,,