ballpython 2.0.0__tar.gz → 2.0.3__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.
- ballpython-2.0.3/PKG-INFO +103 -0
- ballpython-2.0.3/README.md +84 -0
- ballpython-2.0.3/ballpython/py.typed +0 -0
- ballpython-2.0.3/ballpython.egg-info/PKG-INFO +103 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/SOURCES.txt +21 -1
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/__init__.py +39 -2
- ballpython-2.0.3/pycleaner/baseline.py +127 -0
- ballpython-2.0.3/pycleaner/cache.py +282 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/cli.py +644 -43
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/complexity_analyzer.py +16 -28
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/config.py +8 -1
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/dead_code_detector.py +275 -38
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/dependency_auditor.py +175 -75
- ballpython-2.0.3/pycleaner/discovery.py +206 -0
- ballpython-2.0.3/pycleaner/explanations.py +323 -0
- ballpython-2.0.3/pycleaner/frameworks/__init__.py +115 -0
- ballpython-2.0.3/pycleaner/frameworks/plugins.py +290 -0
- ballpython-2.0.3/pycleaner/modernizer.py +349 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/pipeline.py +208 -20
- ballpython-2.0.3/pycleaner/py.typed +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/security_scanner.py +64 -38
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/syntax_healer.py +188 -10
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/taint_engine.py +8 -8
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/test_generator.py +124 -35
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/type_checker.py +29 -33
- ballpython-2.0.3/pycleaner/verifier.py +495 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pyproject.toml +45 -2
- ballpython-2.0.3/tests/test_baseline_and_explain.py +90 -0
- ballpython-2.0.3/tests/test_cache.py +81 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_cli.py +56 -0
- ballpython-2.0.3/tests/test_cli_prove.py +83 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_config.py +34 -0
- ballpython-2.0.3/tests/test_dead_code_fixer.py +90 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_dependency_auditor.py +41 -0
- ballpython-2.0.3/tests/test_discovery.py +98 -0
- ballpython-2.0.3/tests/test_frameworks.py +133 -0
- ballpython-2.0.3/tests/test_modernizer.py +106 -0
- ballpython-2.0.3/tests/test_mutation_test_generator.py +52 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_syntax_healer.py +55 -0
- ballpython-2.0.3/tests/test_verifier.py +74 -0
- ballpython-2.0.3/tests/test_verifier_pipeline.py +89 -0
- ballpython-2.0.0/PKG-INFO +0 -322
- ballpython-2.0.0/README.md +0 -303
- ballpython-2.0.0/ballpython.egg-info/PKG-INFO +0 -322
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/__init__.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/__main__.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/cli.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/dependency_links.txt +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/entry_points.txt +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/requires.txt +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/top_level.txt +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/__main__.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/import_resolver.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/linter_formatter.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/typeshed_resolver.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/setup.cfg +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_complexity_analyzer.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_dead_code_detector.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_import_resolver.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_linter_formatter.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_pipeline.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_security_scanner.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_taint_engine.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_test_generator.py +0 -0
- {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_type_checker.py +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ballpython
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: The Ultimate Static Python Intelligence, Healing, Type Verification, and Security Suite
|
|
5
|
+
Author: Developer
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: ruff>=0.1.0
|
|
10
|
+
Requires-Dist: rich>=13.0.0
|
|
11
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
14
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
15
|
+
Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
16
|
+
Provides-Extra: security
|
|
17
|
+
Requires-Dist: cryptography>=41.0.0; extra == "security"
|
|
18
|
+
Requires-Dist: defusedxml>=0.7.1; extra == "security"
|
|
19
|
+
|
|
20
|
+
# ballpython
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/ballpython/)
|
|
23
|
+
[](https://pypi.org/project/ballpython/)
|
|
24
|
+
[](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
|
|
25
|
+
[](https://opensource.org/licenses/MIT)
|
|
26
|
+
|
|
27
|
+
**The zero-config Python code cleaner, syntax healer, and quality suite.**
|
|
28
|
+
|
|
29
|
+
`ballpython` automatically repairs broken syntax, resolves missing imports, prunes dead code, scans for security vulnerabilities, and formats your code in a single command. Zero LLM dependencies, 100% offline, and fast.
|
|
30
|
+
|
|
31
|
+
Both `ballpython` and `pycleaner` CLI commands are identical.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install ballpython
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
### 1. Fix and format your code
|
|
46
|
+
Run `ballpython` on any file or directory. It automatically heals syntax errors, resolves missing imports, removes unused variables, and applies canonical formatting:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ballpython .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Check code in CI (Dry Run)
|
|
53
|
+
Check for syntax errors, security vulnerabilities, dead code, and linting violations without modifying any files on disk:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ballpython check .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## What It Does Automatically
|
|
62
|
+
|
|
63
|
+
When you run `ballpython`, all engines run under the hood in one pass:
|
|
64
|
+
|
|
65
|
+
* **Syntax Healing:** Repairs missing statement colons (`def`, `class`, `if`), accidental `=` assignments in conditionals, unclosed parentheses/brackets, tab/space mixups, and legacy Python 2 except/print statements.
|
|
66
|
+
* **Smart Import Resolution:** Resolves undefined symbols to standard library modules and common aliases, inserts `TYPE_CHECKING` guards, and prunes unused imports.
|
|
67
|
+
* **Formatting & Modernization:** Formats code to PEP 8 standards (powered by `ruff`), modernizes legacy type annotations (PEP 585/604), and removes redundant `object` inheritance.
|
|
68
|
+
* **Dead Code Pruning:** Discovers and eliminates unreachable code, empty pass blocks, and unused private definitions.
|
|
69
|
+
* **Security & Taint Audit:** Detects hardcoded API secrets, SQL/command injection patterns, and unsafe `eval`/`exec`/`pickle` calls.
|
|
70
|
+
* **Type Verification:** Verifies function call signatures against bundled Typeshed stubs.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Pre-Commit Hook
|
|
75
|
+
|
|
76
|
+
Add `ballpython` to your `.pre-commit-config.yaml`:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
repos:
|
|
80
|
+
- repo: https://github.com/moonrox420/ball-python
|
|
81
|
+
rev: v2.0.3
|
|
82
|
+
hooks:
|
|
83
|
+
- id: pycleaner
|
|
84
|
+
args: ["check"]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Configuration
|
|
90
|
+
|
|
91
|
+
Optional configuration can be placed in `pyproject.toml` under `[tool.pycleaner]`:
|
|
92
|
+
|
|
93
|
+
```toml
|
|
94
|
+
[tool.pycleaner]
|
|
95
|
+
exclude = ["migrations/", "generated/"]
|
|
96
|
+
line-length = 88
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT License.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ballpython
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/ballpython/)
|
|
4
|
+
[](https://pypi.org/project/ballpython/)
|
|
5
|
+
[](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
**The zero-config Python code cleaner, syntax healer, and quality suite.**
|
|
9
|
+
|
|
10
|
+
`ballpython` automatically repairs broken syntax, resolves missing imports, prunes dead code, scans for security vulnerabilities, and formats your code in a single command. Zero LLM dependencies, 100% offline, and fast.
|
|
11
|
+
|
|
12
|
+
Both `ballpython` and `pycleaner` CLI commands are identical.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install ballpython
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
### 1. Fix and format your code
|
|
27
|
+
Run `ballpython` on any file or directory. It automatically heals syntax errors, resolves missing imports, removes unused variables, and applies canonical formatting:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ballpython .
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Check code in CI (Dry Run)
|
|
34
|
+
Check for syntax errors, security vulnerabilities, dead code, and linting violations without modifying any files on disk:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ballpython check .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## What It Does Automatically
|
|
43
|
+
|
|
44
|
+
When you run `ballpython`, all engines run under the hood in one pass:
|
|
45
|
+
|
|
46
|
+
* **Syntax Healing:** Repairs missing statement colons (`def`, `class`, `if`), accidental `=` assignments in conditionals, unclosed parentheses/brackets, tab/space mixups, and legacy Python 2 except/print statements.
|
|
47
|
+
* **Smart Import Resolution:** Resolves undefined symbols to standard library modules and common aliases, inserts `TYPE_CHECKING` guards, and prunes unused imports.
|
|
48
|
+
* **Formatting & Modernization:** Formats code to PEP 8 standards (powered by `ruff`), modernizes legacy type annotations (PEP 585/604), and removes redundant `object` inheritance.
|
|
49
|
+
* **Dead Code Pruning:** Discovers and eliminates unreachable code, empty pass blocks, and unused private definitions.
|
|
50
|
+
* **Security & Taint Audit:** Detects hardcoded API secrets, SQL/command injection patterns, and unsafe `eval`/`exec`/`pickle` calls.
|
|
51
|
+
* **Type Verification:** Verifies function call signatures against bundled Typeshed stubs.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Pre-Commit Hook
|
|
56
|
+
|
|
57
|
+
Add `ballpython` to your `.pre-commit-config.yaml`:
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
repos:
|
|
61
|
+
- repo: https://github.com/moonrox420/ball-python
|
|
62
|
+
rev: v2.0.3
|
|
63
|
+
hooks:
|
|
64
|
+
- id: pycleaner
|
|
65
|
+
args: ["check"]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Optional configuration can be placed in `pyproject.toml` under `[tool.pycleaner]`:
|
|
73
|
+
|
|
74
|
+
```toml
|
|
75
|
+
[tool.pycleaner]
|
|
76
|
+
exclude = ["migrations/", "generated/"]
|
|
77
|
+
line-length = 88
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT License.
|
|
File without changes
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ballpython
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: The Ultimate Static Python Intelligence, Healing, Type Verification, and Security Suite
|
|
5
|
+
Author: Developer
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: ruff>=0.1.0
|
|
10
|
+
Requires-Dist: rich>=13.0.0
|
|
11
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
14
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
15
|
+
Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
16
|
+
Provides-Extra: security
|
|
17
|
+
Requires-Dist: cryptography>=41.0.0; extra == "security"
|
|
18
|
+
Requires-Dist: defusedxml>=0.7.1; extra == "security"
|
|
19
|
+
|
|
20
|
+
# ballpython
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/ballpython/)
|
|
23
|
+
[](https://pypi.org/project/ballpython/)
|
|
24
|
+
[](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
|
|
25
|
+
[](https://opensource.org/licenses/MIT)
|
|
26
|
+
|
|
27
|
+
**The zero-config Python code cleaner, syntax healer, and quality suite.**
|
|
28
|
+
|
|
29
|
+
`ballpython` automatically repairs broken syntax, resolves missing imports, prunes dead code, scans for security vulnerabilities, and formats your code in a single command. Zero LLM dependencies, 100% offline, and fast.
|
|
30
|
+
|
|
31
|
+
Both `ballpython` and `pycleaner` CLI commands are identical.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install ballpython
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
### 1. Fix and format your code
|
|
46
|
+
Run `ballpython` on any file or directory. It automatically heals syntax errors, resolves missing imports, removes unused variables, and applies canonical formatting:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ballpython .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Check code in CI (Dry Run)
|
|
53
|
+
Check for syntax errors, security vulnerabilities, dead code, and linting violations without modifying any files on disk:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ballpython check .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## What It Does Automatically
|
|
62
|
+
|
|
63
|
+
When you run `ballpython`, all engines run under the hood in one pass:
|
|
64
|
+
|
|
65
|
+
* **Syntax Healing:** Repairs missing statement colons (`def`, `class`, `if`), accidental `=` assignments in conditionals, unclosed parentheses/brackets, tab/space mixups, and legacy Python 2 except/print statements.
|
|
66
|
+
* **Smart Import Resolution:** Resolves undefined symbols to standard library modules and common aliases, inserts `TYPE_CHECKING` guards, and prunes unused imports.
|
|
67
|
+
* **Formatting & Modernization:** Formats code to PEP 8 standards (powered by `ruff`), modernizes legacy type annotations (PEP 585/604), and removes redundant `object` inheritance.
|
|
68
|
+
* **Dead Code Pruning:** Discovers and eliminates unreachable code, empty pass blocks, and unused private definitions.
|
|
69
|
+
* **Security & Taint Audit:** Detects hardcoded API secrets, SQL/command injection patterns, and unsafe `eval`/`exec`/`pickle` calls.
|
|
70
|
+
* **Type Verification:** Verifies function call signatures against bundled Typeshed stubs.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Pre-Commit Hook
|
|
75
|
+
|
|
76
|
+
Add `ballpython` to your `.pre-commit-config.yaml`:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
repos:
|
|
80
|
+
- repo: https://github.com/moonrox420/ball-python
|
|
81
|
+
rev: v2.0.3
|
|
82
|
+
hooks:
|
|
83
|
+
- id: pycleaner
|
|
84
|
+
args: ["check"]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Configuration
|
|
90
|
+
|
|
91
|
+
Optional configuration can be placed in `pyproject.toml` under `[tool.pycleaner]`:
|
|
92
|
+
|
|
93
|
+
```toml
|
|
94
|
+
[tool.pycleaner]
|
|
95
|
+
exclude = ["migrations/", "generated/"]
|
|
96
|
+
line-length = 88
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT License.
|
|
@@ -3,6 +3,7 @@ pyproject.toml
|
|
|
3
3
|
ballpython/__init__.py
|
|
4
4
|
ballpython/__main__.py
|
|
5
5
|
ballpython/cli.py
|
|
6
|
+
ballpython/py.typed
|
|
6
7
|
ballpython.egg-info/PKG-INFO
|
|
7
8
|
ballpython.egg-info/SOURCES.txt
|
|
8
9
|
ballpython.egg-info/dependency_links.txt
|
|
@@ -11,30 +12,49 @@ ballpython.egg-info/requires.txt
|
|
|
11
12
|
ballpython.egg-info/top_level.txt
|
|
12
13
|
pycleaner/__init__.py
|
|
13
14
|
pycleaner/__main__.py
|
|
15
|
+
pycleaner/baseline.py
|
|
16
|
+
pycleaner/cache.py
|
|
14
17
|
pycleaner/cli.py
|
|
15
18
|
pycleaner/complexity_analyzer.py
|
|
16
19
|
pycleaner/config.py
|
|
17
20
|
pycleaner/dead_code_detector.py
|
|
18
21
|
pycleaner/dependency_auditor.py
|
|
22
|
+
pycleaner/discovery.py
|
|
23
|
+
pycleaner/explanations.py
|
|
19
24
|
pycleaner/import_resolver.py
|
|
20
25
|
pycleaner/linter_formatter.py
|
|
26
|
+
pycleaner/modernizer.py
|
|
21
27
|
pycleaner/pipeline.py
|
|
28
|
+
pycleaner/py.typed
|
|
22
29
|
pycleaner/security_scanner.py
|
|
23
30
|
pycleaner/syntax_healer.py
|
|
24
31
|
pycleaner/taint_engine.py
|
|
25
32
|
pycleaner/test_generator.py
|
|
26
33
|
pycleaner/type_checker.py
|
|
27
34
|
pycleaner/typeshed_resolver.py
|
|
35
|
+
pycleaner/verifier.py
|
|
36
|
+
pycleaner/frameworks/__init__.py
|
|
37
|
+
pycleaner/frameworks/plugins.py
|
|
38
|
+
tests/test_baseline_and_explain.py
|
|
39
|
+
tests/test_cache.py
|
|
28
40
|
tests/test_cli.py
|
|
41
|
+
tests/test_cli_prove.py
|
|
29
42
|
tests/test_complexity_analyzer.py
|
|
30
43
|
tests/test_config.py
|
|
31
44
|
tests/test_dead_code_detector.py
|
|
45
|
+
tests/test_dead_code_fixer.py
|
|
32
46
|
tests/test_dependency_auditor.py
|
|
47
|
+
tests/test_discovery.py
|
|
48
|
+
tests/test_frameworks.py
|
|
33
49
|
tests/test_import_resolver.py
|
|
34
50
|
tests/test_linter_formatter.py
|
|
51
|
+
tests/test_modernizer.py
|
|
52
|
+
tests/test_mutation_test_generator.py
|
|
35
53
|
tests/test_pipeline.py
|
|
36
54
|
tests/test_security_scanner.py
|
|
37
55
|
tests/test_syntax_healer.py
|
|
38
56
|
tests/test_taint_engine.py
|
|
39
57
|
tests/test_test_generator.py
|
|
40
|
-
tests/test_type_checker.py
|
|
58
|
+
tests/test_type_checker.py
|
|
59
|
+
tests/test_verifier.py
|
|
60
|
+
tests/test_verifier_pipeline.py
|
|
@@ -10,19 +10,38 @@ dataflow taint vulnerabilities, and synthesizes automated behavioral test suites
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
from pycleaner.discovery import (
|
|
14
|
+
DEFAULT_IGNORED_DIRS,
|
|
15
|
+
PROTECTED_FILE_PATTERNS,
|
|
16
|
+
collect_project_python_files,
|
|
17
|
+
is_ignored_directory,
|
|
18
|
+
is_protected_file,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__version__ = "2.0.3"
|
|
14
22
|
__all__ = [
|
|
23
|
+
"BaselineFingerprint",
|
|
24
|
+
"BaselineManager",
|
|
15
25
|
"CleanPipeline",
|
|
16
26
|
"CleanResult",
|
|
17
27
|
"ComplexityAnalyzer",
|
|
18
28
|
"ComplexityReport",
|
|
29
|
+
"ContentAddressableCache",
|
|
30
|
+
"CounterExample",
|
|
19
31
|
"DeadCodeDetector",
|
|
32
|
+
"DeadCodeFixResult",
|
|
33
|
+
"DeadCodeFixer",
|
|
20
34
|
"DeadCodeReport",
|
|
21
35
|
"DependencyAuditor",
|
|
22
36
|
"GeneratedTestSuite",
|
|
23
37
|
"ImportResolver",
|
|
38
|
+
"IsolatedDifferentialVerifier",
|
|
24
39
|
"LinterFormatter",
|
|
40
|
+
"ModernizeResult",
|
|
41
|
+
"Modernizer",
|
|
42
|
+
"ProofReceipt",
|
|
25
43
|
"PyCleanerConfig",
|
|
44
|
+
"RuleExplanation",
|
|
26
45
|
"SecurityReport",
|
|
27
46
|
"SecurityScanner",
|
|
28
47
|
"SyntaxHealer",
|
|
@@ -35,15 +54,27 @@ __all__ = [
|
|
|
35
54
|
"TypeFinding",
|
|
36
55
|
"TypeReport",
|
|
37
56
|
"TypeshedResolver",
|
|
57
|
+
"VerificationTier",
|
|
58
|
+
"get_explanation",
|
|
59
|
+
"list_rules",
|
|
38
60
|
"load_config",
|
|
39
61
|
]
|
|
40
62
|
|
|
63
|
+
from pycleaner.baseline import BaselineFingerprint, BaselineManager
|
|
64
|
+
from pycleaner.cache import ContentAddressableCache
|
|
41
65
|
from pycleaner.complexity_analyzer import ComplexityAnalyzer, ComplexityReport
|
|
42
66
|
from pycleaner.config import PyCleanerConfig, load_config
|
|
43
|
-
from pycleaner.dead_code_detector import
|
|
67
|
+
from pycleaner.dead_code_detector import (
|
|
68
|
+
DeadCodeDetector,
|
|
69
|
+
DeadCodeFixer,
|
|
70
|
+
DeadCodeFixResult,
|
|
71
|
+
DeadCodeReport,
|
|
72
|
+
)
|
|
44
73
|
from pycleaner.dependency_auditor import DependencyAuditor
|
|
74
|
+
from pycleaner.explanations import RuleExplanation, get_explanation, list_rules
|
|
45
75
|
from pycleaner.import_resolver import ImportResolver
|
|
46
76
|
from pycleaner.linter_formatter import LinterFormatter
|
|
77
|
+
from pycleaner.modernizer import Modernizer, ModernizeResult
|
|
47
78
|
from pycleaner.pipeline import CleanPipeline, CleanResult
|
|
48
79
|
from pycleaner.security_scanner import SecurityReport, SecurityScanner
|
|
49
80
|
from pycleaner.syntax_healer import SyntaxHealer
|
|
@@ -51,3 +82,9 @@ from pycleaner.taint_engine import TaintEngine, TaintFinding, TaintReport
|
|
|
51
82
|
from pycleaner.test_generator import GeneratedTestSuite, TestCase, TestGenerator
|
|
52
83
|
from pycleaner.type_checker import TypeChecker, TypeFinding, TypeReport
|
|
53
84
|
from pycleaner.typeshed_resolver import TypeshedResolver
|
|
85
|
+
from pycleaner.verifier import (
|
|
86
|
+
CounterExample,
|
|
87
|
+
IsolatedDifferentialVerifier,
|
|
88
|
+
ProofReceipt,
|
|
89
|
+
VerificationTier,
|
|
90
|
+
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pycleaner.baseline
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
Technical Debt Ratchet and Baseline Management Engine.
|
|
6
|
+
|
|
7
|
+
Enables incremental adoption of PyCleaner on legacy codebases by snapshotting
|
|
8
|
+
existing diagnostic violations into `.pycleaner/baseline.json`. Future CI/CD
|
|
9
|
+
checks ensure that existing technical debt can only decrease, never increase.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import hashlib
|
|
15
|
+
import json
|
|
16
|
+
import time
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class BaselineFingerprint:
|
|
24
|
+
rule: str
|
|
25
|
+
file: str
|
|
26
|
+
line: int
|
|
27
|
+
symbol: str
|
|
28
|
+
|
|
29
|
+
def to_hash(self) -> str:
|
|
30
|
+
raw = f"{self.rule}:{self.file}:{self.line}:{self.symbol}"
|
|
31
|
+
return hashlib.sha256(raw.encode("utf-8")).hexdigest()[:16]
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict[str, Any]:
|
|
34
|
+
return {
|
|
35
|
+
"rule": self.rule,
|
|
36
|
+
"file": self.file,
|
|
37
|
+
"line": self.line,
|
|
38
|
+
"symbol": self.symbol,
|
|
39
|
+
"hash": self.to_hash(),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class BaselineManager:
|
|
44
|
+
"""Manages baseline generation, loading, and ratchet comparison."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, baseline_path: Path | str = ".pycleaner/baseline.json") -> None:
|
|
47
|
+
self.baseline_path = Path(baseline_path)
|
|
48
|
+
|
|
49
|
+
def load_fingerprints(self) -> set[str]:
|
|
50
|
+
"""Loads baseline issue hashes from disk."""
|
|
51
|
+
if not self.baseline_path.exists():
|
|
52
|
+
return set()
|
|
53
|
+
try:
|
|
54
|
+
data = json.loads(self.baseline_path.read_text(encoding="utf-8"))
|
|
55
|
+
fingerprints = data.get("fingerprints", [])
|
|
56
|
+
return {
|
|
57
|
+
fp.get("hash")
|
|
58
|
+
for fp in fingerprints
|
|
59
|
+
if isinstance(fp, dict) and fp.get("hash")
|
|
60
|
+
}
|
|
61
|
+
except json.JSONDecodeError:
|
|
62
|
+
return set()
|
|
63
|
+
|
|
64
|
+
def save_baseline(
|
|
65
|
+
self,
|
|
66
|
+
fingerprints: list[BaselineFingerprint],
|
|
67
|
+
root_dir: Path,
|
|
68
|
+
) -> Path:
|
|
69
|
+
"""Serializes fingerprints to the baseline JSON file."""
|
|
70
|
+
self.baseline_path.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
payload = {
|
|
72
|
+
"version": 1,
|
|
73
|
+
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
74
|
+
"root_dir": str(root_dir.resolve()),
|
|
75
|
+
"issue_count": len(fingerprints),
|
|
76
|
+
"fingerprints": [fp.to_dict() for fp in fingerprints],
|
|
77
|
+
}
|
|
78
|
+
self.baseline_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
|
|
79
|
+
return self.baseline_path
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def create_fingerprint(
|
|
83
|
+
rule: str,
|
|
84
|
+
file_path: Path | str,
|
|
85
|
+
line: int,
|
|
86
|
+
symbol: str,
|
|
87
|
+
root_dir: Path | None = None,
|
|
88
|
+
) -> BaselineFingerprint:
|
|
89
|
+
"""Constructs a deterministic fingerprint with normalized relative path."""
|
|
90
|
+
p = Path(file_path)
|
|
91
|
+
if root_dir is not None:
|
|
92
|
+
try:
|
|
93
|
+
rel = str(p.resolve().relative_to(root_dir.resolve())).replace(
|
|
94
|
+
"\\", "/"
|
|
95
|
+
)
|
|
96
|
+
except ValueError:
|
|
97
|
+
rel = p.name
|
|
98
|
+
else:
|
|
99
|
+
rel = p.name
|
|
100
|
+
|
|
101
|
+
return BaselineFingerprint(
|
|
102
|
+
rule=rule,
|
|
103
|
+
file=rel,
|
|
104
|
+
line=line,
|
|
105
|
+
symbol=symbol,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def filter_new_issues(
|
|
109
|
+
self,
|
|
110
|
+
issues: list[BaselineFingerprint],
|
|
111
|
+
) -> tuple[list[BaselineFingerprint], list[BaselineFingerprint]]:
|
|
112
|
+
"""
|
|
113
|
+
Separates issues into (tolerated_baseline_issues, new_debt_issues).
|
|
114
|
+
Returns:
|
|
115
|
+
(tolerated, new_debt)
|
|
116
|
+
"""
|
|
117
|
+
known_hashes = self.load_fingerprints()
|
|
118
|
+
tolerated: list[BaselineFingerprint] = []
|
|
119
|
+
new_debt: list[BaselineFingerprint] = []
|
|
120
|
+
|
|
121
|
+
for issue in issues:
|
|
122
|
+
if issue.to_hash() in known_hashes:
|
|
123
|
+
tolerated.append(issue)
|
|
124
|
+
else:
|
|
125
|
+
new_debt.append(issue)
|
|
126
|
+
|
|
127
|
+
return tolerated, new_debt
|