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.
Files changed (65) hide show
  1. ballpython-2.0.3/PKG-INFO +103 -0
  2. ballpython-2.0.3/README.md +84 -0
  3. ballpython-2.0.3/ballpython/py.typed +0 -0
  4. ballpython-2.0.3/ballpython.egg-info/PKG-INFO +103 -0
  5. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/SOURCES.txt +21 -1
  6. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/__init__.py +39 -2
  7. ballpython-2.0.3/pycleaner/baseline.py +127 -0
  8. ballpython-2.0.3/pycleaner/cache.py +282 -0
  9. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/cli.py +644 -43
  10. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/complexity_analyzer.py +16 -28
  11. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/config.py +8 -1
  12. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/dead_code_detector.py +275 -38
  13. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/dependency_auditor.py +175 -75
  14. ballpython-2.0.3/pycleaner/discovery.py +206 -0
  15. ballpython-2.0.3/pycleaner/explanations.py +323 -0
  16. ballpython-2.0.3/pycleaner/frameworks/__init__.py +115 -0
  17. ballpython-2.0.3/pycleaner/frameworks/plugins.py +290 -0
  18. ballpython-2.0.3/pycleaner/modernizer.py +349 -0
  19. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/pipeline.py +208 -20
  20. ballpython-2.0.3/pycleaner/py.typed +0 -0
  21. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/security_scanner.py +64 -38
  22. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/syntax_healer.py +188 -10
  23. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/taint_engine.py +8 -8
  24. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/test_generator.py +124 -35
  25. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/type_checker.py +29 -33
  26. ballpython-2.0.3/pycleaner/verifier.py +495 -0
  27. {ballpython-2.0.0 → ballpython-2.0.3}/pyproject.toml +45 -2
  28. ballpython-2.0.3/tests/test_baseline_and_explain.py +90 -0
  29. ballpython-2.0.3/tests/test_cache.py +81 -0
  30. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_cli.py +56 -0
  31. ballpython-2.0.3/tests/test_cli_prove.py +83 -0
  32. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_config.py +34 -0
  33. ballpython-2.0.3/tests/test_dead_code_fixer.py +90 -0
  34. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_dependency_auditor.py +41 -0
  35. ballpython-2.0.3/tests/test_discovery.py +98 -0
  36. ballpython-2.0.3/tests/test_frameworks.py +133 -0
  37. ballpython-2.0.3/tests/test_modernizer.py +106 -0
  38. ballpython-2.0.3/tests/test_mutation_test_generator.py +52 -0
  39. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_syntax_healer.py +55 -0
  40. ballpython-2.0.3/tests/test_verifier.py +74 -0
  41. ballpython-2.0.3/tests/test_verifier_pipeline.py +89 -0
  42. ballpython-2.0.0/PKG-INFO +0 -322
  43. ballpython-2.0.0/README.md +0 -303
  44. ballpython-2.0.0/ballpython.egg-info/PKG-INFO +0 -322
  45. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/__init__.py +0 -0
  46. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/__main__.py +0 -0
  47. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython/cli.py +0 -0
  48. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/dependency_links.txt +0 -0
  49. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/entry_points.txt +0 -0
  50. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/requires.txt +0 -0
  51. {ballpython-2.0.0 → ballpython-2.0.3}/ballpython.egg-info/top_level.txt +0 -0
  52. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/__main__.py +0 -0
  53. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/import_resolver.py +0 -0
  54. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/linter_formatter.py +0 -0
  55. {ballpython-2.0.0 → ballpython-2.0.3}/pycleaner/typeshed_resolver.py +0 -0
  56. {ballpython-2.0.0 → ballpython-2.0.3}/setup.cfg +0 -0
  57. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_complexity_analyzer.py +0 -0
  58. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_dead_code_detector.py +0 -0
  59. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_import_resolver.py +0 -0
  60. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_linter_formatter.py +0 -0
  61. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_pipeline.py +0 -0
  62. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_security_scanner.py +0 -0
  63. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_taint_engine.py +0 -0
  64. {ballpython-2.0.0 → ballpython-2.0.3}/tests/test_test_generator.py +0 -0
  65. {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
+ [![PyPI version](https://img.shields.io/pypi/v/ballpython.svg)](https://pypi.org/project/ballpython/)
23
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ballpython.svg)](https://pypi.org/project/ballpython/)
24
+ [![CI](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml/badge.svg)](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
25
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ [![PyPI version](https://img.shields.io/pypi/v/ballpython.svg)](https://pypi.org/project/ballpython/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ballpython.svg)](https://pypi.org/project/ballpython/)
5
+ [![CI](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml/badge.svg)](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ [![PyPI version](https://img.shields.io/pypi/v/ballpython.svg)](https://pypi.org/project/ballpython/)
23
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ballpython.svg)](https://pypi.org/project/ballpython/)
24
+ [![CI](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml/badge.svg)](https://github.com/moonrox420/ball-python/actions/workflows/ci.yml)
25
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- __version__ = "2.0.0"
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 DeadCodeDetector, DeadCodeReport
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