pycodecommenter 2.0.3__tar.gz → 2.2.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.2.0/.github/workflows/docs.yml +66 -0
- pycodecommenter-2.2.0/.github/workflows/publish.yml +33 -0
- pycodecommenter-2.2.0/.gitignore +56 -0
- pycodecommenter-2.2.0/.well-known/ai-plugin.json +23 -0
- pycodecommenter-2.2.0/CHANGELOG.md +63 -0
- pycodecommenter-2.2.0/CITATION.cff +32 -0
- pycodecommenter-2.2.0/CONTRIBUTING.md +29 -0
- pycodecommenter-2.2.0/Future Work/Future Release WorkPlan.txt +15 -0
- pycodecommenter-2.2.0/Future Work/Vulnerabilties.md +301 -0
- pycodecommenter-2.2.0/Future Work/v2.1.0 /342/200/224 Remaining Items (dry-run, backup, config loader, test rewrite).txt" +143 -0
- pycodecommenter-2.2.0/Future Work/v2.2.0 /342/200/224 Accuracy & Output.txt" +126 -0
- pycodecommenter-2.2.0/Future Work/v3.0.0 /342/200/224 Safe, Configurable, Extensible.txt" +132 -0
- pycodecommenter-2.2.0/Future Work/v3.1.0 /342/200/224 Integrations.txt" +140 -0
- pycodecommenter-2.2.0/PKG-INFO +405 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/__init__.py +3 -1
- pycodecommenter-2.2.0/PyCodeCommenter/cli.py +130 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/commenter.py +46 -10
- pycodecommenter-2.2.0/PyCodeCommenter/config.py +82 -0
- pycodecommenter-2.2.0/PyCodeCommenter/inference.py +150 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/validator.py +117 -17
- pycodecommenter-2.2.0/README.md +365 -0
- pycodecommenter-2.2.0/conftest.py +1 -0
- pycodecommenter-2.2.0/docs/assets/.gitkeep +12 -0
- pycodecommenter-2.2.0/docs/changelog.md +76 -0
- pycodecommenter-2.2.0/docs/cli-reference.md +270 -0
- pycodecommenter-2.2.0/docs/configuration.md +124 -0
- pycodecommenter-2.2.0/docs/contributing.md +114 -0
- pycodecommenter-2.2.0/docs/docstring-styles.md +148 -0
- pycodecommenter-2.2.0/docs/faq.md +249 -0
- pycodecommenter-2.2.0/docs/getting-started.md +120 -0
- pycodecommenter-2.2.0/docs/index.md +185 -0
- pycodecommenter-2.2.0/docs/javascripts/custom.js +61 -0
- pycodecommenter-2.2.0/docs/python-api.md +626 -0
- pycodecommenter-2.2.0/docs/recipes.md +294 -0
- pycodecommenter-2.2.0/docs/robots.txt +20 -0
- pycodecommenter-2.2.0/docs/stylesheets/extra.css +157 -0
- pycodecommenter-2.2.0/docs/validation-checks.md +491 -0
- pycodecommenter-2.2.0/examples/basic_usage.py +35 -0
- pycodecommenter-2.2.0/examples/ci_integration.py +29 -0
- pycodecommenter-2.2.0/examples/coverage_example.py +18 -0
- pycodecommenter-2.2.0/examples/validation_example.py +26 -0
- pycodecommenter-2.2.0/llms.txt +71 -0
- pycodecommenter-2.2.0/mkdocs.yml +90 -0
- pycodecommenter-2.2.0/pycodecommenter.egg-info/PKG-INFO +405 -0
- pycodecommenter-2.2.0/pycodecommenter.egg-info/SOURCES.txt +67 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/pycodecommenter.egg-info/requires.txt +1 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/pyproject.toml +35 -6
- pycodecommenter-2.2.0/scratch/test_infer.py +17 -0
- pycodecommenter-2.2.0/scratch/test_mixed_returns.py +31 -0
- pycodecommenter-2.2.0/scratch/test_unicode.py +13 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/setup.cfg +4 -4
- pycodecommenter-2.2.0/test_backwards_compatibility.py +39 -0
- pycodecommenter-2.2.0/test_basic_validation.py +56 -0
- pycodecommenter-2.2.0/test_coverage.py +30 -0
- pycodecommenter-2.2.0/test_edge_cases.py +58 -0
- pycodecommenter-2.2.0/test_integration.py +74 -0
- pycodecommenter-2.2.0/test_modern.py +37 -0
- pycodecommenter-2.2.0/test_type_analyzer.py +33 -0
- pycodecommenter-2.2.0/test_validation.py +373 -0
- pycodecommenter-2.0.3/PKG-INFO +0 -281
- pycodecommenter-2.0.3/PyCodeCommenter/cli.py +0 -72
- pycodecommenter-2.0.3/README.md +0 -249
- pycodecommenter-2.0.3/pycodecommenter.egg-info/PKG-INFO +0 -281
- pycodecommenter-2.0.3/pycodecommenter.egg-info/SOURCES.txt +0 -19
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/LICENSE +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/coverage.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/docstring_parser.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/parameter_descriptions.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/templates.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/PyCodeCommenter/type_analyzer.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/main.py +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/pycodecommenter.egg-info/dependency_links.txt +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/pycodecommenter.egg-info/entry_points.txt +0 -0
- {pycodecommenter-2.0.3 → pycodecommenter-2.2.0}/pycodecommenter.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# .github/workflows/docs.yml
|
|
2
|
+
# Builds and deploys the MkDocs documentation site to GitHub Pages.
|
|
3
|
+
#
|
|
4
|
+
# Trigger: any push to `main` that touches docs/ or this workflow file.
|
|
5
|
+
# Manual trigger: workflow_dispatch (run from the Actions tab at any time).
|
|
6
|
+
#
|
|
7
|
+
# REQUIRED ONE-TIME SETUP:
|
|
8
|
+
# GitHub repo → Settings → Pages → Source → select "GitHub Actions"
|
|
9
|
+
# Without that change the deploy job runs but the site never goes live.
|
|
10
|
+
|
|
11
|
+
name: Deploy Documentation
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
branches:
|
|
16
|
+
- main
|
|
17
|
+
paths:
|
|
18
|
+
- 'docs/**'
|
|
19
|
+
- 'mkdocs.yml'
|
|
20
|
+
- '.github/workflows/docs.yml'
|
|
21
|
+
workflow_dispatch:
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
pages: write
|
|
26
|
+
id-token: write
|
|
27
|
+
|
|
28
|
+
concurrency:
|
|
29
|
+
group: "pages"
|
|
30
|
+
cancel-in-progress: false
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
build:
|
|
34
|
+
name: Build Documentation Site
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout repository
|
|
38
|
+
uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Set up Python
|
|
41
|
+
uses: actions/setup-python@v5
|
|
42
|
+
with:
|
|
43
|
+
python-version: '3.x'
|
|
44
|
+
|
|
45
|
+
- name: Install MkDocs and theme
|
|
46
|
+
run: pip install mkdocs mkdocs-material
|
|
47
|
+
|
|
48
|
+
- name: Build site
|
|
49
|
+
run: mkdocs build --strict --site-dir _site
|
|
50
|
+
|
|
51
|
+
- name: Upload Pages artifact
|
|
52
|
+
uses: actions/upload-pages-artifact@v3
|
|
53
|
+
with:
|
|
54
|
+
path: _site
|
|
55
|
+
|
|
56
|
+
deploy:
|
|
57
|
+
name: Deploy to GitHub Pages
|
|
58
|
+
needs: build
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment:
|
|
61
|
+
name: github-pages
|
|
62
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
63
|
+
steps:
|
|
64
|
+
- name: Deploy to GitHub Pages
|
|
65
|
+
id: deployment
|
|
66
|
+
uses: actions/deploy-pages@v4
|
|
@@ -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,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "v1",
|
|
3
|
+
"name_for_human": "PyCodeCommenter",
|
|
4
|
+
"name_for_model": "pycodecommenter",
|
|
5
|
+
"description_for_human": "Python docstring generator and validator. Generates Google-style docstrings from AST, validates them against real function signatures, and measures documentation coverage.",
|
|
6
|
+
"description_for_model": "PyCodeCommenter is a deterministic, AST-based Python tool. It can: (1) generate Google-style docstrings for undocumented Python functions and classes from their AST, (2) validate existing docstrings against real function signatures across six check categories, (3) measure documentation coverage per file or project, and (4) export structured JSON reports. It requires no AI, no network access, and no API keys. Install with 'pip install pycodecommenter'. Main classes: PyCodeCommenter (generation), DocstringValidator (validation), CoverageAnalyzer (coverage).",
|
|
7
|
+
"auth": {
|
|
8
|
+
"type": "none"
|
|
9
|
+
},
|
|
10
|
+
"api": {
|
|
11
|
+
"type": "none"
|
|
12
|
+
},
|
|
13
|
+
"logo_url": "https://amosquety.github.io/PyCodeCommenter/assets/logo.png",
|
|
14
|
+
"contact_email": "amosnabasa4@gmail.com",
|
|
15
|
+
"legal_info_url": "https://github.com/AmosQuety/PyCodeCommenter/blob/main/LICENSE",
|
|
16
|
+
"homepage": "https://amosquety.github.io/PyCodeCommenter/",
|
|
17
|
+
"repository": "https://github.com/AmosQuety/PyCodeCommenter",
|
|
18
|
+
"pypi": "https://pypi.org/project/pycodecommenter/",
|
|
19
|
+
"install_command": "pip install pycodecommenter",
|
|
20
|
+
"version": "2.2.0",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Nabasa Amos (Amos Quety)"
|
|
23
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PyCodeCommenter will be documented in this file.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
5
|
+
|
|
6
|
+
## [2.2.0] - 2026-07-12
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- **Decorator-aware validation** — `@property` setter and deleter variants no longer produce false-positive
|
|
10
|
+
"missing Returns section" warnings. `@classmethod` (`cls`) and `@staticmethod` were verified already correct.
|
|
11
|
+
- **`--output-format json`** flag on both `validate` and `coverage` subcommands. Prints machine-readable
|
|
12
|
+
JSON to stdout; text output is completely unchanged.
|
|
13
|
+
- **`ValidationReport.to_dict()`** updated to spec-compliant shape: `stats.total`, `stats.info`,
|
|
14
|
+
`stats.coverage_percentage`; issues now include `line` (integer), `severity` (uppercase), `check`, `message`.
|
|
15
|
+
- **`_has_raises_section()` helper** in `validator.py` — recognises `Raises:` (Google), `Raises\n`
|
|
16
|
+
(bare header), and `:raises ` (Sphinx, trailing space prevents false matches).
|
|
17
|
+
- **`llms.txt`** file at repo root — AI agent and LLM crawler discovery file.
|
|
18
|
+
- **SEO/AEO optimisation** — keyword-rich README, PyPI classifiers/keywords, per-page meta tags on all
|
|
19
|
+
doc pages, JSON-LD `SoftwareApplication` schema on docs homepage.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `test_validation.py` rewritten from script-style to proper pytest (17 tests, all pass).
|
|
23
|
+
- `pyproject.toml` keywords expanded to 20 terms; classifiers expanded with `Code Generators`,
|
|
24
|
+
`Libraries :: Python Modules`, `Environment :: Console`, `Operating System :: OS Independent`.
|
|
25
|
+
- `mkdocs.yml` enriched with `site_author`, explicit `language: en`, `navigation.indexes`,
|
|
26
|
+
`search.share`, `toc.follow`, and `meta` markdown extension for per-page SEO tags.
|
|
27
|
+
|
|
28
|
+
## [2.0.0] - 2026-01-25
|
|
29
|
+
|
|
30
|
+
### Major Release - Complete Rewrite
|
|
31
|
+
|
|
32
|
+
#### Added
|
|
33
|
+
- **Comprehensive Validation System** - 6 types of documentation checks
|
|
34
|
+
- **Coverage Analysis** - Project-wide documentation metrics
|
|
35
|
+
- **Modern Type Support** - PEP 604 unions, PEP 585 generics
|
|
36
|
+
- **Async Function Support** - Full support for `async def`
|
|
37
|
+
- **Multiple Export Formats** - JSON, Markdown, console output
|
|
38
|
+
- **Smart Docstring Parsing** - Preserves existing documentation
|
|
39
|
+
- **Structured AST Traversal** - NodeVisitor pattern for reliability
|
|
40
|
+
- **Professional Reporting** - Actionable error messages with suggestions
|
|
41
|
+
- **CI/CD Ready** - Easy integration with pipelines
|
|
42
|
+
|
|
43
|
+
#### Changed
|
|
44
|
+
- Replaced basic type inference with comprehensive `TypeAnalyzer`
|
|
45
|
+
- Improved docstring generation with better templates
|
|
46
|
+
- Enhanced error handling with proper logging
|
|
47
|
+
- Better handling of edge cases and malformed code
|
|
48
|
+
|
|
49
|
+
#### Fixed
|
|
50
|
+
- Duplicate `_infer_type` methods consolidated
|
|
51
|
+
- Brittle patching logic made robust
|
|
52
|
+
- Import resolution issues
|
|
53
|
+
- Unicode/encoding handling
|
|
54
|
+
|
|
55
|
+
#### Breaking Changes
|
|
56
|
+
- Minimum Python version: 3.8+
|
|
57
|
+
- Some internal APIs changed (public API remains compatible)
|
|
58
|
+
|
|
59
|
+
## [1.0.0] - Earlier Version
|
|
60
|
+
|
|
61
|
+
- Basic docstring generation
|
|
62
|
+
- Template-based descriptions
|
|
63
|
+
- File and string input support
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use PyCodeCommenter in your research or project, please cite it using this metadata."
|
|
3
|
+
type: software
|
|
4
|
+
title: PyCodeCommenter
|
|
5
|
+
abstract: >
|
|
6
|
+
PyCodeCommenter is an open-source Python tool for automatically generating
|
|
7
|
+
Google-style docstrings from Python AST, validating existing docstrings
|
|
8
|
+
against real function signatures, and measuring documentation coverage.
|
|
9
|
+
It is deterministic, rule-based, and requires no AI or network access.
|
|
10
|
+
authors:
|
|
11
|
+
- family-names: Amos
|
|
12
|
+
given-names: Nabasa
|
|
13
|
+
alias: Amos Quety
|
|
14
|
+
email: amosnabasa4@gmail.com
|
|
15
|
+
website: https://nabasa-amos.netlify.app
|
|
16
|
+
orcid: ""
|
|
17
|
+
version: 2.2.0
|
|
18
|
+
date-released: "2026-07-12"
|
|
19
|
+
license: MIT
|
|
20
|
+
repository-code: https://github.com/AmosQuety/PyCodeCommenter
|
|
21
|
+
url: https://amosquety.github.io/PyCodeCommenter/
|
|
22
|
+
keywords:
|
|
23
|
+
- python
|
|
24
|
+
- docstring
|
|
25
|
+
- documentation
|
|
26
|
+
- validation
|
|
27
|
+
- coverage
|
|
28
|
+
- google-style
|
|
29
|
+
- ast
|
|
30
|
+
- developer-tools
|
|
31
|
+
- ci-cd
|
|
32
|
+
- static-analysis
|
|
@@ -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,301 @@
|
|
|
1
|
+
# PyCodeCommenter — Principal Engineer & DX Analysis
|
|
2
|
+
|
|
3
|
+
> Reviewed by: Antigravity (Principal SE / DX Expert)
|
|
4
|
+
> Codebase version: v2.2.0 · Files reviewed: all source, all docs, all tests
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Question 1 — Is This Tool Actually Useful, or Is It a Novelty?
|
|
9
|
+
|
|
10
|
+
**Honest verdict: It is real, but only in one narrow workflow.**
|
|
11
|
+
|
|
12
|
+
The strongest use case — the one where this tool earns its install — is:
|
|
13
|
+
|
|
14
|
+
> **You join a legacy Python project. It has 400 functions. Zero docstrings. You need to get it to a documentable state before a code review, open-source release, or handover.**
|
|
15
|
+
|
|
16
|
+
In that scenario, `pycodecommenter generate . --inplace` gives you structural scaffolding (correct parameters, correct types, correct sections) in seconds. Even though the *descriptions* are weak, you now have the *structure* to fill in, which is faster than writing from scratch. The validator then catches regressions as the codebase evolves.
|
|
17
|
+
|
|
18
|
+
**Where it does NOT compete:**
|
|
19
|
+
|
|
20
|
+
- Active, well-maintained projects — they already use docstring conventions enforced via pre-commit + `pydocstyle`/`ruff D` rules, which are richer and team-proven.
|
|
21
|
+
- Projects using AI coding assistants (Copilot, Cursor, Gemini) — docstrings get generated automatically from context, at higher quality.
|
|
22
|
+
- Greenfield projects — the generate-then-fix workflow adds friction rather than removing it.
|
|
23
|
+
|
|
24
|
+
**The tool's real competitive edge is the validator**, not the generator. `pydocstyle` checks *style*. PyCodeCommenter checks *semantic accuracy* (is parameter `timeout` actually in the `Args:` section?). That's a genuinely differentiated check that existing linters don't do as directly.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Question 2 — Biggest Technical Limitations & Code-Corruption Risks
|
|
29
|
+
|
|
30
|
+
These are ordered by severity. The top two can silently corrupt user files.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
### 🔴 CRITICAL: The Patcher Can Corrupt Multi-Line Signatures
|
|
35
|
+
|
|
36
|
+
**File:** `commenter.py`, `get_patched_code()`, lines 119–162.
|
|
37
|
+
|
|
38
|
+
The patcher finds the `def` line by scanning forward from `node.lineno` looking for a line that starts with `def`, `class`, or `async def`. It then uses `node.body[0].lineno - 1` as the insertion point.
|
|
39
|
+
|
|
40
|
+
**The failure case:**
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
def very_long_function_name(
|
|
44
|
+
argument_one: str,
|
|
45
|
+
argument_two: int, # <-- lineno of body[0] is THIS line
|
|
46
|
+
argument_three: bool,
|
|
47
|
+
) -> dict:
|
|
48
|
+
pass
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`ast` sets `lineno` to the `def` line, but `body[0].lineno` points to the *first statement inside the body*. For a multi-line signature, the first body statement starts *after the closing parenthesis and colon*. The patcher inserts the docstring at `body[0].lineno - 1`, which is actually inside the signature continuation lines. **Result: the file is corrupted.** This is not a hypothetical — any function with a multi-line signature hits this.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### 🔴 CRITICAL: `get_patched_code()` Uses Line-Number Arithmetic on Mutable `lines[]`
|
|
56
|
+
|
|
57
|
+
**File:** `commenter.py`, lines 153–160.
|
|
58
|
+
|
|
59
|
+
The patcher accumulates `changes` (tuples of `(start, end, content)`), sorts them in reverse, then applies them. The sort is on `x[0]` (start line). But when an *insertion* is made (`start > end`), it calls `lines.insert(start, content)` which shifts all subsequent line numbers by 1. If two insertions land close together and are processed in an order where one's `start` overlaps with another's post-shift position, the second edit lands on the wrong line.
|
|
60
|
+
|
|
61
|
+
**Existing tests never catch this** because `test_validation.py` tests the *validator*, and none of the other test files test `get_patched_code()` on multi-function files with real line shifts.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### 🟡 HIGH: `ast.walk()` in `validate_all()` Is Order-Indeterminate and Visits Nested Functions Twice
|
|
66
|
+
|
|
67
|
+
**File:** `validator.py`, lines 182–188.
|
|
68
|
+
|
|
69
|
+
`ast.walk()` does a breadth-first traversal. A nested function inside a class inside another function will be visited — and validated — independently. But the *parent* class body is also walked, so the nested function's stats (`total_functions`) get double-counted. If a class method is inside a nested class, it gets counted three times.
|
|
70
|
+
|
|
71
|
+
This causes the `coverage_percentage` in the validation report to be wrong for any non-trivial project with nested classes.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 🟡 HIGH: `DocstringParser._parse_google()` Uses a Regex That Drops Multi-Line Param Descriptions
|
|
76
|
+
|
|
77
|
+
**File:** `docstring_parser.py`, lines 79–94.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
sections = re.split(r'(?m)^ *(Args|Returns|Attributes|Methods):$', content)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This regex requires the section header to be on its own line with nothing after the colon. But the continuation-line handling in `_parse_google_args()` only recognises lines starting with **8 spaces**:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
elif current_arg and line.startswith(' '): # 8 spaces hardcoded
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Any project using 2-space indentation (common in Django, Flask) or 4-space body + 2-space continuation will silently drop continuation lines. The description gets truncated after the first line. No warning is raised. **This causes the merger in `get_patched_code()` to silently overwrite human-written multi-line descriptions.**
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 🟠 MEDIUM: `check_signature_match()` Self/Cls Heuristic Is Name-Based, Not AST-Based
|
|
94
|
+
|
|
95
|
+
**File:** `validator.py`, lines 271–276.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
if actual_params and actual_params[0] in ('self', 'cls'):
|
|
99
|
+
actual_params = actual_params[1:]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If a developer names their first parameter `self` on a module-level function (unusual but valid), the validator silently strips it. Conversely, if a classmethod's `cls` is not the first parameter (impossible under normal usage but possible in generated/metaprogrammed code), the strip doesn't fire. The fix from v2.2.0 (decorator detection) partially addresses this for `@classmethod`, but the underlying heuristic is still name-based and fragile.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 🟠 MEDIUM: `generate` CLI Does Not Accept Directory Paths
|
|
107
|
+
|
|
108
|
+
**File:** `cli.py`, line 37.
|
|
109
|
+
|
|
110
|
+
`pycodecommenter generate myfile.py` works. `pycodecommenter generate ./src/` does not — it fails silently or errors out. `coverage` accepts directories; `validate` accepts only files; `generate` accepts only files. This asymmetry is documented but it's a DX cliff: every new user tries `pycodecommenter generate .` first.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 🟡 HIGH: `validate` CLI Also Does Not Accept Directories
|
|
115
|
+
|
|
116
|
+
**File:** `cli.py`, lines 81–85.
|
|
117
|
+
|
|
118
|
+
Same problem as generate. The pre-commit recipe works around this with `pass_filenames: true`, but running `pycodecommenter validate src/` manually — the most natural thing to type — silently passes on `DocstringValidator(file_path="src/")` which opens a directory and fails in `ast.parse()`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 🟠 MEDIUM: `PEP 604` Union Type Renders as `Union[X, Y]` Not `X | Y`
|
|
123
|
+
|
|
124
|
+
**File:** `type_analyzer.py`, line 138–140.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
if isinstance(annotation.op, ast.BitOr):
|
|
128
|
+
return f"Union[{left}, {right}]"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
A type hint written as `int | str` (modern Python) gets documented as `Union[int, str]` — the older style. In a Python 3.10+ codebase, this is visually inconsistent and potentially confusing.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### 🟠 MEDIUM: Config File Is Loaded But Ignored at Runtime
|
|
136
|
+
|
|
137
|
+
**File:** `config.py` is complete and correct. The problem is it's never called from `cli.py` or any core class. The `--exclude` flag is implemented independently in the CLI without ever reading `.pycodecommenter.yaml`. A user who creates a config file gets zero effect. This is documented in the configuration page but it's a credibility problem — if the config doesn't work, sophisticated users leave.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Question 3 — API Design Review
|
|
142
|
+
|
|
143
|
+
### What Works
|
|
144
|
+
|
|
145
|
+
The fluent builder pattern is clean:
|
|
146
|
+
```python
|
|
147
|
+
PyCodeCommenter().from_file("f.py").get_patched_code()
|
|
148
|
+
```
|
|
149
|
+
This is a good DX decision. It's Pythonic and readable.
|
|
150
|
+
|
|
151
|
+
### What Is Broken or Confusing
|
|
152
|
+
|
|
153
|
+
**1. The `validate()` method on `PyCodeCommenter` is a redundant wrapper that hides a bug.**
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# commenter.py line 434
|
|
157
|
+
validator = DocstringValidator(code_string=self.code, file_path=None)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`file_path=None` is hardcoded. So `report.file_path` is always `None` when called via `commenter.validate()`, even though the commenter loaded from a file. Every issue's `location` string starts with `code:` instead of the real file path. The user sees `[ERROR] code:12:my_func` instead of `[ERROR] src/api.py:12:my_func`. **The file path information is lost.**
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# Fix: pass self.file_path
|
|
164
|
+
validator = DocstringValidator(code_string=self.code, file_path=self.file_path)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**2. Two different ways to validate — neither documented to prefer one over the other.**
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
# Path A — via commenter
|
|
171
|
+
report = PyCodeCommenter().from_file("f.py").validate()
|
|
172
|
+
|
|
173
|
+
# Path B — via validator directly
|
|
174
|
+
report = DocstringValidator(file_path="f.py").validate_all()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Path A loses the file path (see above). Path B uses a different method name (`validate_all()` vs `validate()`). The docs use both without explaining the difference. New users pick one randomly.
|
|
178
|
+
|
|
179
|
+
**API fix:** Deprecate `PyCodeCommenter.validate()` or make it delegate correctly. Standardise on `validate_all()` or rename it to `validate()` on the validator.
|
|
180
|
+
|
|
181
|
+
**3. `ValidationReport.to_dict()` and `to_markdown()` have no corresponding `from_dict()`.**
|
|
182
|
+
|
|
183
|
+
You can export but not import. This means you can't round-trip a report — e.g., store the JSON, load it later, add new issues, re-export. Minor for now, but becomes a problem when building dashboards or trend analysis.
|
|
184
|
+
|
|
185
|
+
**4. The `check_coverage()` method on `PyCodeCommenter` returns a `FileCoverage` with `path="<string>"`.**
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
# commenter.py line 456
|
|
189
|
+
coverage = FileCoverage(path="<string>")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
If the commenter was loaded from a file, the path should be the actual file path. `"<string>"` is an internal implementation detail that leaks to the user.
|
|
193
|
+
|
|
194
|
+
**5. `ValidationStats` uses `infos` (plural) but `ValidationReport.to_dict()` now uses `info` (singular) after v2.2.0.**
|
|
195
|
+
|
|
196
|
+
The internal attribute is `stats.infos`; the JSON key is `"info"`. This is an inconsistency that will confuse anyone reading both the Python API docs and the JSON output docs side by side.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Question 4 — Top 3 Changes Required for Production-Grade Adoption
|
|
201
|
+
|
|
202
|
+
### #1 — Fix the Patcher: Replace Line-Number Arithmetic with AST-Position-Aware Rewriting
|
|
203
|
+
|
|
204
|
+
**Priority: BLOCKING. Teams will not use a tool that can corrupt their files.**
|
|
205
|
+
|
|
206
|
+
The current patcher (`get_patched_code()`) is a string-manipulation layer built on top of AST line numbers. This is the correct *concept* but the *execution* is fragile.
|
|
207
|
+
|
|
208
|
+
**What to do:**
|
|
209
|
+
|
|
210
|
+
Replace the line-number approach with `libcst` (Concrete Syntax Tree). CST-based rewriting is the industry standard for safe code modification — it's what `black`, `isort`, `rope`, and `jedi` all use. With CST:
|
|
211
|
+
|
|
212
|
+
- Multi-line signatures are handled correctly because the CST knows exactly where the body begins.
|
|
213
|
+
- Existing comments and blank lines are preserved.
|
|
214
|
+
- The edit is applied at the AST node level, not the string-manipulation level.
|
|
215
|
+
- There is no index-shift bug.
|
|
216
|
+
|
|
217
|
+
If adding `libcst` is too heavy, the minimum safe fix is: **use `ast.unparse()` + `ast.fix_missing_locations()`** — parse → modify the AST directly → unparse. This is lossy (comments are dropped) but at least it can't corrupt the file.
|
|
218
|
+
|
|
219
|
+
Until this is fixed, the generate command should **always require `--backup`** when using `--inplace`, and the docs should warn explicitly that multi-line signatures are not yet safe.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### #2 — Make `validate` and `generate` Accept Directories (and Recursive Globbing)
|
|
224
|
+
|
|
225
|
+
**Priority: HIGH. This is the single biggest DX friction point.**
|
|
226
|
+
|
|
227
|
+
Every user's first instinct is `pycodecommenter validate .` or `pycodecommenter validate src/`. Today this silently fails or errors. The `coverage` command already accepts directories — the asymmetry is jarring and implies the tool is unfinished.
|
|
228
|
+
|
|
229
|
+
**What to do:**
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
# cli.py validate handler
|
|
233
|
+
if os.path.isdir(args.file):
|
|
234
|
+
from pathlib import Path
|
|
235
|
+
py_files = list(Path(args.file).rglob("*.py"))
|
|
236
|
+
# apply exclude patterns
|
|
237
|
+
# run validator on each, aggregate report
|
|
238
|
+
else:
|
|
239
|
+
# existing single-file path
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Also add `--recursive` / `-r` flag. Add `--exclude` to `validate` (it's already on `coverage`).
|
|
243
|
+
|
|
244
|
+
This is ~50 lines of code that removes the most common first-use failure.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### #3 — Wire the Config File Into the Runtime, and Add `--fail-below` to the Coverage CLI
|
|
249
|
+
|
|
250
|
+
**Priority: HIGH. Without this, the tool cannot be adopted by teams.**
|
|
251
|
+
|
|
252
|
+
Right now a team lead cannot enforce "all PRs must have >80% doc coverage" via a config file. They have to write a custom Python script (`check_coverage.py` — the recipe we documented). That is not acceptable for a tool that bills itself as CI-ready.
|
|
253
|
+
|
|
254
|
+
**Two things to do, both required:**
|
|
255
|
+
|
|
256
|
+
**3a. Wire `load_config()` into the CLI.**
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
# cli.py, top of main()
|
|
260
|
+
from .config import load_config, ConfigError
|
|
261
|
+
try:
|
|
262
|
+
config = load_config()
|
|
263
|
+
except ConfigError as e:
|
|
264
|
+
print(f"Warning: {e}", file=sys.stderr)
|
|
265
|
+
config = {}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Then honour at minimum these two keys:
|
|
269
|
+
- `coverage.threshold` → used by `coverage` subcommand as `--fail-below` default
|
|
270
|
+
- `exclude` → used by `coverage` and `validate` as default exclude list
|
|
271
|
+
|
|
272
|
+
**3b. Add `--fail-below` to the `coverage` CLI.**
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
pycodecommenter coverage ./src --fail-below 80
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
This is the killer CI feature. Without it, `coverage` is a reporting tool, not an enforcement tool. With it, a team can add one line to their GitHub Actions workflow and get hard coverage gating. This is what makes the difference between "I tried it once" and "we installed it as a mandatory check."
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Summary Table
|
|
283
|
+
|
|
284
|
+
| Issue | Severity | Effort |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| Multi-line signature patcher corrupts files | 🔴 Critical | Large (CST rewrite) |
|
|
287
|
+
| `validate`/`generate` don't accept directories | 🟡 High | Small (50 lines) |
|
|
288
|
+
| `--fail-below` missing from coverage CLI | 🟡 High | Small (20 lines) |
|
|
289
|
+
| Config file is loaded but ignored | 🟡 High | Medium (wire into CLI) |
|
|
290
|
+
| `PyCodeCommenter.validate()` loses file path | 🟠 Medium | Trivial (1 line) |
|
|
291
|
+
| `ast.walk()` double-counts nested functions | 🟠 Medium | Small |
|
|
292
|
+
| Hard-coded 8-space continuation in parser | 🟠 Medium | Small |
|
|
293
|
+
| PEP 604 renders as `Union[X,Y]` not `X\|Y` | 🟠 Medium | Trivial |
|
|
294
|
+
| `infos` vs `info` internal/external naming inconsistency | 🟢 Low | Trivial |
|
|
295
|
+
| `check_coverage()` returns `path="<string>"` | 🟢 Low | Trivial |
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Bottom Line
|
|
300
|
+
|
|
301
|
+
PyCodeCommenter has a real, defensible use case (legacy codebase bootstrapping + signature-accuracy validation) and solid bones (the AST-walking validator is genuinely useful). But it has **two critical reliability issues** (file corruption on multi-line signatures, directory-mode missing) that will cause any team's first serious use to fail. Fix those two first. Then wire the config file. After those three changes, this is a legitimate addition to a Python team's standard toolkit.
|