pycodecommenter 2.0.3__tar.gz → 2.1.0__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.
- pycodecommenter-2.1.0/.github/workflows/publish.yml +33 -0
- pycodecommenter-2.1.0/.gitignore +56 -0
- pycodecommenter-2.1.0/CHANGELOG.md +40 -0
- pycodecommenter-2.1.0/CONTRIBUTING.md +29 -0
- pycodecommenter-2.1.0/Future Work/Future Release WorkPlan.txt +15 -0
- pycodecommenter-2.1.0/Future Work/v2.1.0 /342/200/224 Remaining Items (dry-run, backup, config loader, test rewrite).txt" +143 -0
- pycodecommenter-2.1.0/Future Work/v2.2.0 /342/200/224 Accuracy & Output.txt" +126 -0
- pycodecommenter-2.1.0/Future Work/v3.0.0 /342/200/224 Safe, Configurable, Extensible.txt" +132 -0
- pycodecommenter-2.1.0/Future Work/v3.1.0 /342/200/224 Integrations.txt" +139 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/LICENSE +21 -21
- {pycodecommenter-2.0.3/pycodecommenter.egg-info → pycodecommenter-2.1.0}/PKG-INFO +322 -281
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/__init__.py +27 -26
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/cli.py +101 -72
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/commenter.py +477 -450
- pycodecommenter-2.1.0/PyCodeCommenter/config.py +82 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/coverage.py +124 -124
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/docstring_parser.py +121 -121
- pycodecommenter-2.1.0/PyCodeCommenter/inference.py +150 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/parameter_descriptions.py +76 -76
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/templates.py +95 -95
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/type_analyzer.py +203 -203
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/validator.py +563 -563
- pycodecommenter-2.1.0/README.md +289 -0
- pycodecommenter-2.1.0/conftest.py +1 -0
- pycodecommenter-2.1.0/examples/basic_usage.py +35 -0
- pycodecommenter-2.1.0/examples/ci_integration.py +29 -0
- pycodecommenter-2.1.0/examples/coverage_example.py +18 -0
- pycodecommenter-2.1.0/examples/validation_example.py +26 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0/pycodecommenter.egg-info}/PKG-INFO +322 -281
- pycodecommenter-2.1.0/pycodecommenter.egg-info/SOURCES.txt +44 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/requires.txt +1 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pyproject.toml +49 -49
- pycodecommenter-2.1.0/scratch/test_infer.py +17 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/setup.cfg +4 -4
- pycodecommenter-2.1.0/test_backwards_compatibility.py +39 -0
- pycodecommenter-2.1.0/test_basic_validation.py +56 -0
- pycodecommenter-2.1.0/test_coverage.py +30 -0
- pycodecommenter-2.1.0/test_edge_cases.py +58 -0
- pycodecommenter-2.1.0/test_integration.py +74 -0
- pycodecommenter-2.1.0/test_modern.py +37 -0
- pycodecommenter-2.1.0/test_type_analyzer.py +32 -0
- pycodecommenter-2.1.0/test_validation.py +170 -0
- pycodecommenter-2.0.3/README.md +0 -249
- pycodecommenter-2.0.3/pycodecommenter.egg-info/SOURCES.txt +0 -19
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/main.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/dependency_links.txt +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/entry_points.txt +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pypi-publish:
|
|
9
|
+
name: Upload release to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment:
|
|
12
|
+
name: pypi
|
|
13
|
+
url: https://pypi.org/p/pycodecommenter
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.x'
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install build
|
|
28
|
+
|
|
29
|
+
- name: Build package
|
|
30
|
+
run: python -m build
|
|
31
|
+
|
|
32
|
+
- name: Publish package distributions to PyPI
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
share/python-wheels/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
.installed.cfg
|
|
22
|
+
*.egg
|
|
23
|
+
MANIFEST
|
|
24
|
+
|
|
25
|
+
# Environments
|
|
26
|
+
.env
|
|
27
|
+
.venv
|
|
28
|
+
env/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
env.bak/
|
|
32
|
+
venv.bak/
|
|
33
|
+
|
|
34
|
+
# Pytest
|
|
35
|
+
.pytest_cache/
|
|
36
|
+
.coverage
|
|
37
|
+
htmlcov/
|
|
38
|
+
|
|
39
|
+
# Local/Temp Files for PyCodeCommenter
|
|
40
|
+
env_info.txt
|
|
41
|
+
out.txt
|
|
42
|
+
output.txt
|
|
43
|
+
modern_output.txt
|
|
44
|
+
modern_results.txt
|
|
45
|
+
test_output.txt
|
|
46
|
+
reproduction.py
|
|
47
|
+
test_cst.txt
|
|
48
|
+
main_output.txt
|
|
49
|
+
out_*.txt
|
|
50
|
+
verify_*.py
|
|
51
|
+
verify_*.txt
|
|
52
|
+
error.txt
|
|
53
|
+
version_info.txt
|
|
54
|
+
|
|
55
|
+
# VS Code
|
|
56
|
+
.vscode/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PyCodeCommenter will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [2.0.0] - 2026-01-25
|
|
6
|
+
|
|
7
|
+
### Major Release - Complete Rewrite
|
|
8
|
+
|
|
9
|
+
#### Added
|
|
10
|
+
- **Comprehensive Validation System** - 6 types of documentation checks
|
|
11
|
+
- **Coverage Analysis** - Project-wide documentation metrics
|
|
12
|
+
- **Modern Type Support** - PEP 604 unions, PEP 585 generics
|
|
13
|
+
- **Async Function Support** - Full support for `async def`
|
|
14
|
+
- **Multiple Export Formats** - JSON, Markdown, console output
|
|
15
|
+
- **Smart Docstring Parsing** - Preserves existing documentation
|
|
16
|
+
- **Structured AST Traversal** - NodeVisitor pattern for reliability
|
|
17
|
+
- **Professional Reporting** - Actionable error messages with suggestions
|
|
18
|
+
- **CI/CD Ready** - Easy integration with pipelines
|
|
19
|
+
|
|
20
|
+
#### Changed
|
|
21
|
+
- Replaced basic type inference with comprehensive `TypeAnalyzer`
|
|
22
|
+
- Improved docstring generation with better templates
|
|
23
|
+
- Enhanced error handling with proper logging
|
|
24
|
+
- Better handling of edge cases and malformed code
|
|
25
|
+
|
|
26
|
+
#### Fixed
|
|
27
|
+
- Duplicate `_infer_type` methods consolidated
|
|
28
|
+
- Brittle patching logic made robust
|
|
29
|
+
- Import resolution issues
|
|
30
|
+
- Unicode/encoding handling
|
|
31
|
+
|
|
32
|
+
#### Breaking Changes
|
|
33
|
+
- Minimum Python version: 3.8+
|
|
34
|
+
- Some internal APIs changed (public API remains compatible)
|
|
35
|
+
|
|
36
|
+
## [1.0.0] - Earlier Version
|
|
37
|
+
|
|
38
|
+
- Basic docstring generation
|
|
39
|
+
- Template-based descriptions
|
|
40
|
+
- File and string input support
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Contributing to PyCodeCommenter
|
|
2
|
+
|
|
3
|
+
First off, thank you for considering contributing to PyCodeCommenter! It's people like you who make it a great tool for everyone.
|
|
4
|
+
|
|
5
|
+
## How Can I Contribute?
|
|
6
|
+
|
|
7
|
+
### Reporting Bugs
|
|
8
|
+
* Check the [Issues](https://github.com/AmosQuety/PyCodeCommenter/issues) to see if it has already been reported.
|
|
9
|
+
* If not, open a new issue. Include a clear title, a description of the problem, and steps to reproduce (like a small code snippet).
|
|
10
|
+
|
|
11
|
+
### Proposing Enhancements
|
|
12
|
+
* Open an issue to discuss your idea before starting work.
|
|
13
|
+
* Explain why this feature would be useful and how it should work.
|
|
14
|
+
|
|
15
|
+
### Pull Requests
|
|
16
|
+
1. Fork the repo and create your branch from `main`.
|
|
17
|
+
2. Follow the existing code style.
|
|
18
|
+
3. Add tests if you're adding new functionality.
|
|
19
|
+
4. Ensure all tests pass.
|
|
20
|
+
5. Update documentation (including `README.md`) if necessary.
|
|
21
|
+
6. Open a Pull Request with a clear description of your changes.
|
|
22
|
+
|
|
23
|
+
## Code Style
|
|
24
|
+
* Use [black](https://github.com/psf/black) for formatting.
|
|
25
|
+
* Follow Google-style docstrings (since that's what we generate!).
|
|
26
|
+
* Maintain Python 3.8+ compatibility.
|
|
27
|
+
|
|
28
|
+
## Need Help?
|
|
29
|
+
Feel free to open a discussion or an issue if you have any questions!
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
v2.1.0 — Safety & Trust · Jun 10 → Jun 30
|
|
2
|
+
This is the "stop scaring users" release. All four items are independent so you can ship them in any order.
|
|
3
|
+
--dry-run and --backup first — they're the most urgent. Dry-run prints a unified diff to stdout. Backup simply does shutil.copy(path, path + ".bak") before any in-place write. Maybe 2 days each.
|
|
4
|
+
Config loader next. Add a config.py module that walks up the directory tree looking for .pycodecommenter.yaml and loads it with ruamel.yaml. Wire the values to the existing hard-coded defaults. A week's work max.
|
|
5
|
+
Smarter parameter inference is also v2.1 — see the dedicated audit prompt below.
|
|
6
|
+
Test rewrite is ongoing across all phases but the baseline pass (assertions on critical paths) should land here.
|
|
7
|
+
|
|
8
|
+
v2.2.0 — Accuracy & Output · Jul 1 → Aug 15
|
|
9
|
+
This is the "be correct and be composable" release. Decorator awareness cleans up the false-positive noise. JSON output unlocks every downstream integration — make it a flag on both validate and coverage. The Sphinx :raises: fix is a targeted one-liner in validator.py.
|
|
10
|
+
|
|
11
|
+
v3.0.0 — Safe, Configurable, Extensible · Aug 16 → Nov 1
|
|
12
|
+
The big one. The merge algorithm is the hardest item in the entire roadmap — budget 3–4 weeks for it alone. The approach: parse the existing docstring into sections, generate fresh sections, then do a section-by-section merge where any section with human content that doesn't match the auto-generated template is preserved. Multi-style support travels alongside — once the generator is style-aware, NumPy and Sphinx become config flags.
|
|
13
|
+
|
|
14
|
+
v3.1.0 — Integrations · Nov 2, 2026 → Mar 1, 2027
|
|
15
|
+
VS Code extension, GitHub Action for PR automation, SARIF output. These all depend on the v3.0 foundation being solid. Don't start them until merge and JSON output are stable.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# PyCodeCommenter — v2.1.0 Safety & Trust Implementation
|
|
2
|
+
|
|
3
|
+
## MANDATORY FIRST STEP — READ BEFORE WRITING ANY CODE
|
|
4
|
+
|
|
5
|
+
Before proposing or implementing anything, you must read and cross-check
|
|
6
|
+
the following files. Do not assume anything about how they work. If a file
|
|
7
|
+
does not exist, say so explicitly before continuing.
|
|
8
|
+
|
|
9
|
+
Files to read in full:
|
|
10
|
+
- PyCodeCommenter/cli.py
|
|
11
|
+
- PyCodeCommenter/commenter.py
|
|
12
|
+
- PyCodeCommenter/__init__.py
|
|
13
|
+
- pyproject.toml
|
|
14
|
+
- All existing test_*.py files at the project root
|
|
15
|
+
|
|
16
|
+
For each file, confirm:
|
|
17
|
+
1. The exact function/class names involved in the feature you are about to touch
|
|
18
|
+
2. The exact argument names and defaults for the CLI subcommands
|
|
19
|
+
3. Whether any config-loading code already exists anywhere (search for
|
|
20
|
+
"yaml", "config", "load", "settings" across all files before assuming
|
|
21
|
+
config is absent)
|
|
22
|
+
4. What testing library is currently used and whether conftest.py exists
|
|
23
|
+
|
|
24
|
+
Report your findings as a short inventory before writing a single line of code.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Feature 1: --dry-run flag for `generate`
|
|
29
|
+
|
|
30
|
+
### What to build
|
|
31
|
+
Add a `--dry-run` flag to the `generate` CLI subcommand. When set:
|
|
32
|
+
- Generate the patched code in memory (do not write to disk)
|
|
33
|
+
- Print a unified diff between the original file content and the patched
|
|
34
|
+
content to stdout using Python's built-in `difflib.unified_diff`
|
|
35
|
+
- Exit with code 0 if no changes would be made, code 1 if changes exist
|
|
36
|
+
(allows CI to detect undocumented files)
|
|
37
|
+
|
|
38
|
+
### Constraints
|
|
39
|
+
- The flag must be `--dry-run` (hyphenated), stored as `dry_run` in argparse
|
|
40
|
+
- Do not modify any file on disk when --dry-run is active
|
|
41
|
+
- The diff output must be human-readable (use `lineterm=""` in unified_diff)
|
|
42
|
+
- Only touch cli.py and commenter.py. Do not touch validator.py, coverage.py,
|
|
43
|
+
or any test file for this feature.
|
|
44
|
+
- If commenter.py's generate/patch flow writes to disk inside the class rather
|
|
45
|
+
than in cli.py, identify exactly where and adjust accordingly — do not guess.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Feature 2: --backup flag for `generate`
|
|
50
|
+
|
|
51
|
+
### What to build
|
|
52
|
+
Add a `--backup` flag to the `generate` CLI subcommand. When set alongside
|
|
53
|
+
`-i` / `--inplace`:
|
|
54
|
+
- Before writing the patched file, copy the original to `{original_path}.bak`
|
|
55
|
+
using `shutil.copy2` (preserves metadata)
|
|
56
|
+
- Print a confirmation line: `Backup saved: {path}.bak`
|
|
57
|
+
- If the .bak file already exists, overwrite it (do not prompt)
|
|
58
|
+
|
|
59
|
+
### Constraints
|
|
60
|
+
- `--backup` has no effect unless `--inplace` is also set; if --backup is
|
|
61
|
+
passed without --inplace, print a warning and continue normally
|
|
62
|
+
- Only touch cli.py. Do not touch commenter.py or any other module.
|
|
63
|
+
- Use shutil.copy2, not shutil.copy or manual file reads.
|
|
64
|
+
- Do not modify the behavior of --inplace in any way other than inserting
|
|
65
|
+
the backup step before the write.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Feature 3: Config file loader
|
|
70
|
+
|
|
71
|
+
### What to build
|
|
72
|
+
Create a new file `PyCodeCommenter/config.py` containing a `load_config`
|
|
73
|
+
function that:
|
|
74
|
+
|
|
75
|
+
1. Accepts an optional `start_path: str | None = None` parameter (defaults
|
|
76
|
+
to `os.getcwd()` if None)
|
|
77
|
+
2. Walks UP the directory tree from start_path looking for
|
|
78
|
+
`.pycodecommenter.yaml`
|
|
79
|
+
3. Returns the parsed config as a plain Python dict on success
|
|
80
|
+
4. Returns an empty dict `{}` if no config file is found anywhere in the tree
|
|
81
|
+
5. Raises `ConfigError` (a custom exception defined in the same file) with
|
|
82
|
+
a clear message if the file is found but cannot be parsed
|
|
83
|
+
|
|
84
|
+
The config dict must support these keys (with these exact names and types):
|
|
85
|
+
|
|
86
|
+
style: str # "google" | "numpy" | "sphinx", default "google"
|
|
87
|
+
validation:
|
|
88
|
+
level: str # "strict" | "moderate" | "lenient", default "moderate"
|
|
89
|
+
check_types: bool # default true
|
|
90
|
+
check_exceptions: bool # default true
|
|
91
|
+
coverage:
|
|
92
|
+
threshold: float # default 80.0
|
|
93
|
+
fail_below: bool # default true
|
|
94
|
+
exclude:
|
|
95
|
+
|
|
96
|
+
str # list of exclusion patterns, default []
|
|
97
|
+
|
|
98
|
+
5. After loading raw YAML, validate the keys against the schema above.
|
|
99
|
+
Unknown keys should log a warning but not raise.
|
|
100
|
+
6. Wire `load_config` into cli.py so that every subcommand loads config at
|
|
101
|
+
startup and passes relevant values to the underlying classes.
|
|
102
|
+
|
|
103
|
+
### Constraints
|
|
104
|
+
- Use `ruamel.yaml` for YAML parsing. If it is not in pyproject.toml,
|
|
105
|
+
add it to the [dependencies] section before implementing.
|
|
106
|
+
- Do not use PyYAML — check pyproject.toml first to see what is available.
|
|
107
|
+
- Do not modify commenter.py, validator.py, or coverage.py to accept config
|
|
108
|
+
directly — pass values through the existing constructor/method arguments
|
|
109
|
+
that already exist. If an argument does not exist, check before adding one.
|
|
110
|
+
- The function must never crash on a missing file — only on a malformed one.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Feature 4: Test suite rewrite
|
|
115
|
+
|
|
116
|
+
### What to build
|
|
117
|
+
Rewrite all existing `test_*.py` files at the project root to use proper
|
|
118
|
+
pytest assertions. Do not delete any existing test file — rewrite each one
|
|
119
|
+
in place.
|
|
120
|
+
|
|
121
|
+
### Rules
|
|
122
|
+
- Read every existing test_*.py file before touching any of them.
|
|
123
|
+
- For each test that currently just prints or runs code without asserting,
|
|
124
|
+
add explicit `assert` statements that verify:
|
|
125
|
+
- The number of issues found matches an expected count
|
|
126
|
+
- The severity of each issue matches (use the actual Severity enum values
|
|
127
|
+
from validator.py — read the file to get exact names)
|
|
128
|
+
- The message text contains expected substrings where relevant
|
|
129
|
+
- Do not change what is being tested — only add assertions to what already
|
|
130
|
+
runs.
|
|
131
|
+
- If a test currently catches an exception silently, make it assert the
|
|
132
|
+
exception is raised using `pytest.raises`.
|
|
133
|
+
- Add a `conftest.py` at the project root with any shared fixtures (e.g.,
|
|
134
|
+
a helper that creates a temporary Python file from a string).
|
|
135
|
+
- Do not add new test cases in this pass — only harden existing ones.
|
|
136
|
+
New test cases belong in test_inference.py (already planned).
|
|
137
|
+
|
|
138
|
+
### Constraints
|
|
139
|
+
- Read validator.py's Severity enum and ValidationIssue dataclass before
|
|
140
|
+
writing any assertion — use the exact field names.
|
|
141
|
+
- Read coverage.py's FileCoverage and ProjectCoverage before asserting
|
|
142
|
+
coverage values — use the exact attribute names.
|
|
143
|
+
- Do not add imports that are not already available in the project.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# PyCodeCommenter — v2.2.0 Accuracy & Output Implementation
|
|
2
|
+
|
|
3
|
+
## MANDATORY FIRST STEP — READ BEFORE WRITING ANY CODE
|
|
4
|
+
|
|
5
|
+
Before proposing or implementing anything, read the following files in full:
|
|
6
|
+
- PyCodeCommenter/validator.py (entire file)
|
|
7
|
+
- PyCodeCommenter/commenter.py (entire file)
|
|
8
|
+
- PyCodeCommenter/cli.py (entire file)
|
|
9
|
+
- PyCodeCommenter/docstring_parser.py (entire file)
|
|
10
|
+
- PyCodeCommenter/__init__.py
|
|
11
|
+
- pyproject.toml
|
|
12
|
+
|
|
13
|
+
For each file confirm:
|
|
14
|
+
1. The exact class and method names you will touch for each feature
|
|
15
|
+
2. Whether any JSON output, decorator detection, or Sphinx raise handling
|
|
16
|
+
already exists anywhere — search before assuming it is absent
|
|
17
|
+
3. The exact Severity enum values and ValidationIssue field names
|
|
18
|
+
4. What arguments `DocstringValidator.__init__` and `validate()` currently
|
|
19
|
+
accept
|
|
20
|
+
|
|
21
|
+
Report a short inventory of findings before writing any code.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Feature 1: Decorator and method-type awareness in validator
|
|
26
|
+
|
|
27
|
+
### What to build
|
|
28
|
+
Update `DocstringValidator` in `validator.py` to detect and handle these
|
|
29
|
+
decorator types:
|
|
30
|
+
- `@property` — skip return-doc check on setter/deleter variants; getter
|
|
31
|
+
should still have a return doc
|
|
32
|
+
- `@classmethod` — treat `cls` the same as `self` (already excluded from
|
|
33
|
+
param checks, but verify this is actually the case by reading the code)
|
|
34
|
+
- `@staticmethod` — no `self`/`cls` at all; ensure the heuristic that
|
|
35
|
+
detects methods does not misfire on static methods with a non-self first arg
|
|
36
|
+
|
|
37
|
+
### How to detect decorators
|
|
38
|
+
Read `func_node.decorator_list` from the AST node. Each decorator is an
|
|
39
|
+
`ast.Name` or `ast.Attribute`. Match on `.id` for simple decorators
|
|
40
|
+
(`@property`, `@staticmethod`, `@classmethod`).
|
|
41
|
+
|
|
42
|
+
### Constraints
|
|
43
|
+
- Read the current method-detection heuristic in validator.py first and
|
|
44
|
+
document exactly what it does before changing it.
|
|
45
|
+
- Do not change the public API of `DocstringValidator` — no new constructor
|
|
46
|
+
arguments.
|
|
47
|
+
- Do not touch commenter.py, coverage.py, or cli.py.
|
|
48
|
+
- Add test cases for each decorator type to `test_validation.py` (rewrite
|
|
49
|
+
it in place, do not create a new file).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Feature 2: Structured JSON output for validate and coverage
|
|
54
|
+
|
|
55
|
+
### What to build
|
|
56
|
+
Add `--output-format` flag to both `validate` and `coverage` subcommands
|
|
57
|
+
in cli.py. Accepted values: `text` (default, existing behavior) and `json`.
|
|
58
|
+
|
|
59
|
+
When `--output-format json`:
|
|
60
|
+
- For `validate`: serialize the ValidationReport to JSON and print to stdout.
|
|
61
|
+
The JSON shape must be:
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"file": "<path>",
|
|
65
|
+
"stats": {
|
|
66
|
+
"total": 0,
|
|
67
|
+
"errors": 0,
|
|
68
|
+
"warnings": 0,
|
|
69
|
+
"info": 0,
|
|
70
|
+
"coverage_percentage": 0.0
|
|
71
|
+
},
|
|
72
|
+
"issues": [
|
|
73
|
+
{
|
|
74
|
+
"line": 0,
|
|
75
|
+
"severity": "ERROR|WARNING|INFO",
|
|
76
|
+
"check": "<check name>",
|
|
77
|
+
"message": "<message>"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
- For `coverage`: serialize ProjectCoverage to JSON. The shape must match
|
|
83
|
+
whatever `to_json()` already returns — read coverage.py first to confirm
|
|
84
|
+
this method exists and what it returns before adding anything.
|
|
85
|
+
|
|
86
|
+
### Constraints
|
|
87
|
+
- Use Python's built-in `json` module only — no third-party serializers.
|
|
88
|
+
- If ValidationReport does not have a `to_dict()` method, add one to
|
|
89
|
+
validator.py. Read the full class first to check.
|
|
90
|
+
- If ValidationIssue is a dataclass, use `dataclasses.asdict`. Verify this
|
|
91
|
+
before assuming it.
|
|
92
|
+
- The Severity enum must serialize to its string name (e.g., `"ERROR"` not
|
|
93
|
+
`<Severity.ERROR: 1>`). Handle this explicitly.
|
|
94
|
+
- Do not change text output behavior in any way — json mode is additive only.
|
|
95
|
+
- Do not touch commenter.py or coverage.py beyond what is needed for
|
|
96
|
+
to_dict()/to_json() additions.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Feature 3: Sphinx :raises: detection fix
|
|
101
|
+
|
|
102
|
+
### What to build
|
|
103
|
+
Update the exception documentation check in `validator.py` so that it
|
|
104
|
+
recognises Sphinx-style raises syntax (`:raises ExcType:`) in addition to
|
|
105
|
+
the existing Google-style (`Raises:` section header).
|
|
106
|
+
|
|
107
|
+
### How to find the current check
|
|
108
|
+
Search validator.py for the string `'Raises'` and `raises`. Read the full
|
|
109
|
+
method that performs this check before touching it. Document exactly what
|
|
110
|
+
substring/regex it currently uses.
|
|
111
|
+
|
|
112
|
+
### What to change
|
|
113
|
+
The check for whether a "Raises" section exists should match any of:
|
|
114
|
+
- `Raises:` (Google style — already works, do not break it)
|
|
115
|
+
- `:raises ` (Sphinx style — note the trailing space to avoid false matches)
|
|
116
|
+
- `Raises\n` or `Raises\r\n` (bare header variant)
|
|
117
|
+
|
|
118
|
+
Do this with a helper function `_has_raises_section(docstring: str) -> bool`
|
|
119
|
+
added to validator.py. Replace all existing inline checks with calls to this
|
|
120
|
+
helper.
|
|
121
|
+
|
|
122
|
+
### Constraints
|
|
123
|
+
- Read the entire exception-check method before writing the helper.
|
|
124
|
+
- Do not use a third-party regex library — use the `re` module from stdlib.
|
|
125
|
+
- Write one test case for Sphinx-style raises in `test_validation.py`.
|
|
126
|
+
- Do not touch any other file.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# PyCodeCommenter — v3.0.0 Smart Merge & Multi-Style Implementation
|
|
2
|
+
|
|
3
|
+
## MANDATORY FIRST STEP — READ BEFORE WRITING ANY CODE
|
|
4
|
+
|
|
5
|
+
This is the most complex release. More than any other phase, the risk is
|
|
6
|
+
building on wrong assumptions. You must read and fully understand the
|
|
7
|
+
existing code before designing anything.
|
|
8
|
+
|
|
9
|
+
Read these files in full before writing a single line:
|
|
10
|
+
- PyCodeCommenter/commenter.py (entire file — this is the core)
|
|
11
|
+
- PyCodeCommenter/docstring_parser.py (entire file)
|
|
12
|
+
- PyCodeCommenter/templates.py (entire file)
|
|
13
|
+
- PyCodeCommenter/parameter_descriptions.py
|
|
14
|
+
- PyCodeCommenter/inference.py (added in v2.1.0 — confirm it exists)
|
|
15
|
+
- PyCodeCommenter/config.py (added in v2.1.0 — confirm it exists)
|
|
16
|
+
- PyCodeCommenter/cli.py
|
|
17
|
+
- PyCodeCommenter/__init__.py
|
|
18
|
+
- pyproject.toml
|
|
19
|
+
|
|
20
|
+
For each file, document:
|
|
21
|
+
1. Exactly how `generate_docstrings()` produces and inserts docstring text
|
|
22
|
+
2. Whether `get_patched_code()` does string manipulation or AST rewriting
|
|
23
|
+
3. How `DocstringParser` breaks a docstring into sections — what the output
|
|
24
|
+
structure looks like (dict? dataclass? list?)
|
|
25
|
+
4. Whether the parser already handles NumPy or Sphinx style, or only Google
|
|
26
|
+
5. How the config system (from v2.1.0) passes `style` to the generator —
|
|
27
|
+
if it does not yet, document the gap
|
|
28
|
+
|
|
29
|
+
Report this inventory before proceeding. Do not design the merge algorithm
|
|
30
|
+
until you understand exactly how the current insertion works.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Feature 1: Smart docstring merge algorithm
|
|
35
|
+
|
|
36
|
+
### What to build
|
|
37
|
+
Today, `generate_docstrings()` replaces any existing docstring entirely.
|
|
38
|
+
Change this so that when a docstring already exists:
|
|
39
|
+
|
|
40
|
+
1. Parse the existing docstring into sections using `DocstringParser`
|
|
41
|
+
2. Generate a fresh docstring for the same function
|
|
42
|
+
3. Merge: for each section in the generated docstring, check if the
|
|
43
|
+
corresponding section in the existing docstring was human-written
|
|
44
|
+
(i.e., its content does not match what the generator would have
|
|
45
|
+
auto-produced)
|
|
46
|
+
4. If the section is human-written → keep the existing content
|
|
47
|
+
5. If the section is missing in existing → insert the generated version
|
|
48
|
+
6. If the section matches the auto-generated template exactly → replace
|
|
49
|
+
with the freshly generated version (it may now be more accurate)
|
|
50
|
+
|
|
51
|
+
### Defining "auto-generated content"
|
|
52
|
+
A section is considered auto-generated if it matches a template from
|
|
53
|
+
`templates.py` or `inference.py` (from v2.1.0). Read these files and
|
|
54
|
+
define the exact matching criteria before implementing.
|
|
55
|
+
|
|
56
|
+
### Where to implement
|
|
57
|
+
Add a `DocstringMerger` class to a new file `PyCodeCommenter/merger.py`.
|
|
58
|
+
It must have this interface:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
class DocstringMerger:
|
|
62
|
+
def merge(
|
|
63
|
+
self,
|
|
64
|
+
existing_docstring: str,
|
|
65
|
+
generated_docstring: str,
|
|
66
|
+
function_name: str,
|
|
67
|
+
param_names: list[str],
|
|
68
|
+
) -> str:
|
|
69
|
+
"""Return the merged docstring string, ready to insert."""
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Integrate it into `commenter.py` by calling `DocstringMerger().merge()`
|
|
73
|
+
wherever an existing docstring would currently be replaced.
|
|
74
|
+
|
|
75
|
+
### Constraints
|
|
76
|
+
- Read exactly how commenter.py currently detects and replaces an existing
|
|
77
|
+
docstring before writing any merger logic.
|
|
78
|
+
- The merger must never produce an invalid docstring — if merging fails for
|
|
79
|
+
any reason, fall back to the existing docstring unchanged and log a warning.
|
|
80
|
+
- Do not change the public API of `PyCodeCommenter` — no new constructor
|
|
81
|
+
arguments required for basic usage.
|
|
82
|
+
- Export `DocstringMerger` from `__init__.py`.
|
|
83
|
+
- Write tests in `test_merger.py` covering:
|
|
84
|
+
- A function with no existing docstring (merger is not called)
|
|
85
|
+
- A function with a fully auto-generated docstring (gets replaced)
|
|
86
|
+
- A function with a human-written summary (summary preserved)
|
|
87
|
+
- A function with human-written Args entries (entries preserved)
|
|
88
|
+
- A function where the signature changed (new param added to Args)
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Feature 2: NumPy and Sphinx style generation
|
|
93
|
+
|
|
94
|
+
### What to build
|
|
95
|
+
Make the generator emit NumPy or Sphinx style docstrings when configured.
|
|
96
|
+
The `style` config key (added in v2.1.0 config.py) controls this.
|
|
97
|
+
|
|
98
|
+
### Step 1: Extend the parser
|
|
99
|
+
Read `docstring_parser.py` in full. Document which styles it currently
|
|
100
|
+
handles. Extend `DocstringParser.parse()` to fully handle:
|
|
101
|
+
- **NumPy style**: `Parameters\n----------\nparam_name : type\n description`
|
|
102
|
+
- **Sphinx style**: `:param name: description\n:type name: type\n:returns:`
|
|
103
|
+
|
|
104
|
+
The parse output structure must be identical regardless of input style —
|
|
105
|
+
the validator and merger must not need to know which style was parsed.
|
|
106
|
+
|
|
107
|
+
### Step 2: Add style templates
|
|
108
|
+
Add NumPy and Sphinx output formatters alongside the existing Google formatter.
|
|
109
|
+
Structure them as separate functions or a class with a `format(style)` method
|
|
110
|
+
— read `templates.py` first to see the existing pattern, then extend it
|
|
111
|
+
consistently.
|
|
112
|
+
|
|
113
|
+
### Step 3: Wire to config
|
|
114
|
+
In `commenter.py`, read the `style` value from the loaded config and pass it
|
|
115
|
+
to the formatter. Default to `"google"` if not set.
|
|
116
|
+
|
|
117
|
+
### Constraints
|
|
118
|
+
- Google style must remain the default and must be completely unaffected.
|
|
119
|
+
- The `DocstringParser` output structure must not change — keep the same
|
|
120
|
+
dict/dataclass keys. Add new keys only if absolutely necessary, and document
|
|
121
|
+
each addition.
|
|
122
|
+
- Do not touch `validator.py` — validation is style-agnostic at this stage.
|
|
123
|
+
- Write tests in `test_styles.py` covering generation and parsing round-trips
|
|
124
|
+
for all three styles.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Integration requirement
|
|
129
|
+
After both features are implemented, run the full test suite. Every existing
|
|
130
|
+
test must still pass. If any test fails due to the merge algorithm changing
|
|
131
|
+
generated output, update the test's expected value — do not suppress the
|
|
132
|
+
failure.
|