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.
Files changed (48) hide show
  1. pycodecommenter-2.1.0/.github/workflows/publish.yml +33 -0
  2. pycodecommenter-2.1.0/.gitignore +56 -0
  3. pycodecommenter-2.1.0/CHANGELOG.md +40 -0
  4. pycodecommenter-2.1.0/CONTRIBUTING.md +29 -0
  5. pycodecommenter-2.1.0/Future Work/Future Release WorkPlan.txt +15 -0
  6. pycodecommenter-2.1.0/Future Work/v2.1.0 /342/200/224 Remaining Items (dry-run, backup, config loader, test rewrite).txt" +143 -0
  7. pycodecommenter-2.1.0/Future Work/v2.2.0 /342/200/224 Accuracy & Output.txt" +126 -0
  8. pycodecommenter-2.1.0/Future Work/v3.0.0 /342/200/224 Safe, Configurable, Extensible.txt" +132 -0
  9. pycodecommenter-2.1.0/Future Work/v3.1.0 /342/200/224 Integrations.txt" +139 -0
  10. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/LICENSE +21 -21
  11. {pycodecommenter-2.0.3/pycodecommenter.egg-info → pycodecommenter-2.1.0}/PKG-INFO +322 -281
  12. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/__init__.py +27 -26
  13. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/cli.py +101 -72
  14. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/commenter.py +477 -450
  15. pycodecommenter-2.1.0/PyCodeCommenter/config.py +82 -0
  16. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/coverage.py +124 -124
  17. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/docstring_parser.py +121 -121
  18. pycodecommenter-2.1.0/PyCodeCommenter/inference.py +150 -0
  19. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/parameter_descriptions.py +76 -76
  20. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/templates.py +95 -95
  21. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/type_analyzer.py +203 -203
  22. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/PyCodeCommenter/validator.py +563 -563
  23. pycodecommenter-2.1.0/README.md +289 -0
  24. pycodecommenter-2.1.0/conftest.py +1 -0
  25. pycodecommenter-2.1.0/examples/basic_usage.py +35 -0
  26. pycodecommenter-2.1.0/examples/ci_integration.py +29 -0
  27. pycodecommenter-2.1.0/examples/coverage_example.py +18 -0
  28. pycodecommenter-2.1.0/examples/validation_example.py +26 -0
  29. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0/pycodecommenter.egg-info}/PKG-INFO +322 -281
  30. pycodecommenter-2.1.0/pycodecommenter.egg-info/SOURCES.txt +44 -0
  31. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/requires.txt +1 -0
  32. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pyproject.toml +49 -49
  33. pycodecommenter-2.1.0/scratch/test_infer.py +17 -0
  34. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/setup.cfg +4 -4
  35. pycodecommenter-2.1.0/test_backwards_compatibility.py +39 -0
  36. pycodecommenter-2.1.0/test_basic_validation.py +56 -0
  37. pycodecommenter-2.1.0/test_coverage.py +30 -0
  38. pycodecommenter-2.1.0/test_edge_cases.py +58 -0
  39. pycodecommenter-2.1.0/test_integration.py +74 -0
  40. pycodecommenter-2.1.0/test_modern.py +37 -0
  41. pycodecommenter-2.1.0/test_type_analyzer.py +32 -0
  42. pycodecommenter-2.1.0/test_validation.py +170 -0
  43. pycodecommenter-2.0.3/README.md +0 -249
  44. pycodecommenter-2.0.3/pycodecommenter.egg-info/SOURCES.txt +0 -19
  45. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/main.py +0 -0
  46. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/dependency_links.txt +0 -0
  47. {pycodecommenter-2.0.3 → pycodecommenter-2.1.0}/pycodecommenter.egg-info/entry_points.txt +0 -0
  48. {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.