skylos 1.0.10__py3-none-any.whl → 2.5.2__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.
Files changed (53) hide show
  1. skylos/__init__.py +9 -3
  2. skylos/analyzer.py +674 -168
  3. skylos/cfg_visitor.py +60 -0
  4. skylos/cli.py +719 -235
  5. skylos/codemods.py +277 -0
  6. skylos/config.py +50 -0
  7. skylos/constants.py +78 -0
  8. skylos/gatekeeper.py +147 -0
  9. skylos/linter.py +18 -0
  10. skylos/rules/base.py +20 -0
  11. skylos/rules/danger/calls.py +119 -0
  12. skylos/rules/danger/danger.py +157 -0
  13. skylos/rules/danger/danger_cmd/cmd_flow.py +75 -0
  14. skylos/rules/danger/danger_fs/__init__.py +0 -0
  15. skylos/rules/danger/danger_fs/path_flow.py +79 -0
  16. skylos/rules/danger/danger_net/__init__.py +0 -0
  17. skylos/rules/danger/danger_net/ssrf_flow.py +80 -0
  18. skylos/rules/danger/danger_sql/__init__.py +0 -0
  19. skylos/rules/danger/danger_sql/sql_flow.py +245 -0
  20. skylos/rules/danger/danger_sql/sql_raw_flow.py +96 -0
  21. skylos/rules/danger/danger_web/__init__.py +0 -0
  22. skylos/rules/danger/danger_web/xss_flow.py +170 -0
  23. skylos/rules/danger/taint.py +110 -0
  24. skylos/rules/quality/__init__.py +0 -0
  25. skylos/rules/quality/complexity.py +95 -0
  26. skylos/rules/quality/logic.py +96 -0
  27. skylos/rules/quality/nesting.py +101 -0
  28. skylos/rules/quality/structure.py +99 -0
  29. skylos/rules/secrets.py +325 -0
  30. skylos/server.py +554 -0
  31. skylos/visitor.py +502 -90
  32. skylos/visitors/__init__.py +0 -0
  33. skylos/visitors/framework_aware.py +437 -0
  34. skylos/visitors/test_aware.py +74 -0
  35. skylos-2.5.2.dist-info/METADATA +21 -0
  36. skylos-2.5.2.dist-info/RECORD +42 -0
  37. {skylos-1.0.10.dist-info → skylos-2.5.2.dist-info}/WHEEL +1 -1
  38. {skylos-1.0.10.dist-info → skylos-2.5.2.dist-info}/top_level.txt +0 -1
  39. skylos-1.0.10.dist-info/METADATA +0 -8
  40. skylos-1.0.10.dist-info/RECORD +0 -21
  41. test/compare_tools.py +0 -604
  42. test/diagnostics.py +0 -364
  43. test/sample_repo/app.py +0 -13
  44. test/sample_repo/sample_repo/commands.py +0 -81
  45. test/sample_repo/sample_repo/models.py +0 -122
  46. test/sample_repo/sample_repo/routes.py +0 -89
  47. test/sample_repo/sample_repo/utils.py +0 -36
  48. test/test_skylos.py +0 -456
  49. test/test_visitor.py +0 -220
  50. {test → skylos/rules}/__init__.py +0 -0
  51. {test/sample_repo → skylos/rules/danger}/__init__.py +0 -0
  52. {test/sample_repo/sample_repo → skylos/rules/danger/danger_cmd}/__init__.py +0 -0
  53. {skylos-1.0.10.dist-info → skylos-2.5.2.dist-info}/entry_points.txt +0 -0
test/test_visitor.py DELETED
@@ -1,220 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import ast
4
- import unittest
5
- from pathlib import Path
6
- import tempfile
7
-
8
- from skylos.visitor import Visitor, Definition, PYTHON_BUILTINS, DYNAMIC_PATTERNS
9
-
10
- class TestDefinition(unittest.TestCase):
11
- """Test the Definition class."""
12
-
13
- def test_definition_creation(self):
14
- """Test basic definition creation."""
15
- definition = Definition("module.function", "function", "test.py", 10)
16
-
17
- self.assertEqual(definition.name, "module.function")
18
- self.assertEqual(definition.type, "function")
19
- self.assertEqual(definition.filename, "test.py")
20
- self.assertEqual(definition.line, 10)
21
- self.assertEqual(definition.simple_name, "function")
22
- self.assertEqual(definition.confidence, 100)
23
- self.assertEqual(definition.references, 0)
24
- self.assertFalse(definition.is_exported)
25
-
26
- def test_definition_to_dict_function(self):
27
- """Test to_dict method for functions."""
28
- definition = Definition("mymodule.my_function", "function", "test.py", 5)
29
- result = definition.to_dict()
30
-
31
- expected = {
32
- "name": "my_function",
33
- "full_name": "mymodule.my_function",
34
- "simple_name": "my_function",
35
- "type": "function",
36
- "file": "test.py",
37
- "basename": "test.py",
38
- "line": 5,
39
- "confidence": 100,
40
- "references": 0
41
- }
42
-
43
- self.assertEqual(result, expected)
44
-
45
- def test_definition_to_dict_method(self):
46
- """Test to_dict method for methods."""
47
- definition = Definition("mymodule.MyClass.my_method", "method", "test.py", 15)
48
- result = definition.to_dict()
49
-
50
- # show last two parts for methods
51
- self.assertEqual(result["name"], "MyClass.my_method")
52
- self.assertEqual(result["full_name"], "mymodule.MyClass.my_method")
53
- self.assertEqual(result["simple_name"], "my_method")
54
-
55
- def test_init_file_detection(self):
56
- """Test detection of __init__.py files."""
57
- definition = Definition("pkg.func", "function", "/path/to/__init__.py", 1)
58
- self.assertTrue(definition.in_init)
59
-
60
- definition2 = Definition("pkg.func", "function", "/path/to/module.py", 1)
61
- self.assertFalse(definition2.in_init)
62
-
63
- class TestVisitor(unittest.TestCase):
64
- """Test the Visitor class."""
65
-
66
- def setUp(self):
67
- """Set up test fixtures."""
68
- self.temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False)
69
- self.visitor = Visitor("test_module", self.temp_file.name)
70
-
71
- def tearDown(self):
72
- """Clean up test fixtures."""
73
- Path(self.temp_file.name).unlink()
74
-
75
- def parse_and_visit(self, code):
76
- """Helper method to parse code and visit with the visitor."""
77
- tree = ast.parse(code)
78
- self.visitor.visit(tree)
79
- return self.visitor
80
-
81
- def test_simple_function(self):
82
- """Test detection of simple function definitions."""
83
- code = """
84
- def my_function():
85
- pass
86
- """
87
- visitor = self.parse_and_visit(code)
88
-
89
- self.assertEqual(len(visitor.defs), 1)
90
- definition = visitor.defs[0]
91
- self.assertEqual(definition.type, "function")
92
- self.assertEqual(definition.simple_name, "my_function")
93
-
94
- def test_class_with_methods(self):
95
- """Test detection of classes and methods."""
96
- code = """
97
- class MyClass:
98
- def __init__(self):
99
- pass
100
-
101
- def method(self):
102
- pass
103
- """
104
- visitor = self.parse_and_visit(code)
105
-
106
- # technically should find class and two methods
107
- self.assertEqual(len(visitor.defs), 3)
108
-
109
- class_def = next(d for d in visitor.defs if d.type == "class")
110
- self.assertEqual(class_def.simple_name, "MyClass")
111
-
112
- methods = [d for d in visitor.defs if d.type == "method"]
113
- self.assertEqual(len(methods), 2)
114
- method_names = {m.simple_name for m in methods}
115
- self.assertEqual(method_names, {"__init__", "method"})
116
-
117
- def test_imports(self):
118
- """Test import statement detection."""
119
- code = """
120
- import os
121
- import sys as system
122
- from pathlib import Path
123
- from collections import defaultdict, Counter
124
- """
125
- visitor = self.parse_and_visit(code)
126
-
127
- imports = [d for d in visitor.defs if d.type == "import"]
128
- self.assertTrue(len(imports) >= 4)
129
-
130
- self.assertEqual(visitor.alias["system"], "sys")
131
- self.assertEqual(visitor.alias["Path"], "pathlib.Path")
132
- self.assertEqual(visitor.alias["defaultdict"], "collections.defaultdict")
133
-
134
- def test_nested_functions(self):
135
- """Test nested function detection."""
136
- code = """
137
- def outer():
138
- def inner():
139
- def deeply_nested():
140
- pass
141
- return deeply_nested()
142
- return inner()
143
- """
144
- visitor = self.parse_and_visit(code)
145
-
146
- functions = [d for d in visitor.defs if d.type == "function"]
147
- self.assertEqual(len(functions), 3)
148
-
149
- names = {f.name for f in functions}
150
- expected_names = {
151
- "test_module.outer",
152
- "test_module.outer.inner",
153
- "test_module.outer.inner.deeply_nested"
154
- }
155
- self.assertEqual(names, expected_names)
156
-
157
- def test_getattr_detection(self):
158
- """Test detection of getattr calls."""
159
- code = """
160
- obj = SomeClass()
161
- value = getattr(obj, 'attribute_name')
162
- check = hasattr(obj, 'other_attr')
163
- """
164
- visitor = self.parse_and_visit(code)
165
-
166
- ref_names = {ref[0] for ref in visitor.refs}
167
- self.assertIn('attribute_name', ref_names)
168
- self.assertIn('other_attr', ref_names)
169
-
170
- def test_all_detection(self):
171
- """Test __all__ detection."""
172
- code = """
173
- __all__ = ['function1', 'Class1', 'CONSTANT']
174
-
175
- def function1():
176
- pass
177
-
178
- class Class1:
179
- pass
180
-
181
- CONSTANT = 42
182
- """
183
- visitor = self.parse_and_visit(code)
184
-
185
- ref_names = {ref[0] for ref in visitor.refs}
186
- self.assertIn('function1', ref_names)
187
- self.assertIn('Class1', ref_names)
188
- self.assertIn('CONSTANT', ref_names)
189
-
190
- def test_builtin_detection(self):
191
- """Test that builtins are correctly identified."""
192
- code = """
193
- def my_function():
194
- result = len([1, 2, 3])
195
- print(result)
196
- data = list(range(10))
197
- return data
198
- """
199
- visitor = self.parse_and_visit(code)
200
-
201
- ref_names = {ref[0] for ref in visitor.refs}
202
- builtins_found = ref_names & PYTHON_BUILTINS
203
- expected_builtins = {'len', 'print', 'list', 'range'}
204
- self.assertTrue(expected_builtins.issubset(builtins_found))
205
-
206
- class TestConstants(unittest.TestCase):
207
- """Test the module constants."""
208
-
209
- def test_python_builtins(self):
210
- """Test that important builtins are included."""
211
- important_builtins = {'print', 'len', 'str', 'int', 'list', 'dict', 'range'}
212
- self.assertTrue(important_builtins.issubset(PYTHON_BUILTINS))
213
-
214
- def test_dynamic_patterns(self):
215
- """Test dynamic pattern constants."""
216
- expected_patterns = {'getattr', 'globals', 'eval', 'exec'}
217
- self.assertTrue(expected_patterns.issubset(DYNAMIC_PATTERNS))
218
-
219
- if __name__ == '__main__':
220
- unittest.main(verbosity=2)
File without changes
File without changes