Recipes & Common Workflows¶
This page provides complete, copy-paste-ready examples for the most common PyCodeCommenter use cases. Every command and code snippet has been verified against the actual source code.
Recipe 1: Pre-commit Hook Setup¶
Validate docstrings on every commit so documentation issues are caught before they reach the repository.
Using pre-commit framework¶
Create or update .pre-commit-config.yaml in your project root:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: validate-docstrings
name: Validate Docstrings
entry: pycodecommenter validate
language: system
types: [python]
pass_filenames: true
Note:
pycodecommenter validateaccepts a directory too (since v2.3.0), butpass_filenames: trueis still the right choice for a pre-commit hook — it calls the hook once per staged Python file, so the check only runs against what actually changed instead of re-validating the whole tree on every commit.
Install the hook:
From now on, every git commit will run pycodecommenter validate on each staged Python file and block the commit if any ERROR-level issues are found.
Recipe 2: The CI Configurator¶
Run a documentation quality check on every push and pull request. Use the configurator below to generate the exact YAML snippet for your provider and package manager.
Recipe 3: Documenting an Existing Codebase Safely¶
When adding docstrings to a codebase that has none, use this three-step workflow to avoid accidental data loss.
Step 1 — Preview what will change¶
Read through the diff carefully. Any prose the tool can't extract from the AST — what a parameter or function actually means — is left as a placeholder marker (TODO(pycodecommenter): describe) that you will want to resolve.
Step 2 — Back up, then apply¶
This creates src/api.py.bak before modifying src/api.py. If anything goes wrong, restore from the backup:
Step 3 — Review and refine¶
Open src/api.py and update the generated docstrings:
- Replace every TODO(pycodecommenter): describe marker with a real description.
- Check that parameter descriptions are accurate (the rule-based descriptions are starting points).
- Verify class docstrings describe the actual purpose of the class.
Step 4 — Validate the result¶
Fix any remaining WARNING or INFO issues, then commit. Step 4 will now also flag any unresolved TODO(pycodecommenter): describe markers you missed in Step 3 as a quality-category WARNING — the same placeholder check that already blacklists TODO catches leftover guess markers, so an unfinished Step 3 is surfaced here instead of silently passing.
Recipe 4: Coverage Gating in CI¶
Fail the CI build if documentation coverage falls below a threshold. Since v2.3.0, the CLI coverage subcommand does this natively with --fail-below — no wrapper script needed:
Add to your GitHub Actions workflow:
- name: Check coverage threshold
run: pycodecommenter coverage ./src --exclude migrations tests --fail-below 80
You can also set the threshold once in .pycodecommenter.yaml instead of repeating --fail-below in every CI config:
An explicit --fail-below on the command line always overrides the config value. See Configuration for the full key reference.
When you'd still reach for the Python API¶
--fail-below covers the common case. Use the API directly instead when you need something the CLI flag doesn't offer — e.g. combining coverage with other checks in one script, or custom logging/formatting beyond --output-format json:
# check_coverage.py
import sys
from PyCodeCommenter import CoverageAnalyzer
THRESHOLD = 80.0 # Minimum acceptable coverage percentage
analyzer = CoverageAnalyzer()
project = analyzer.analyze_directory("./src", exclude_patterns=["migrations", "tests"])
project.print_report()
if project.total_coverage < THRESHOLD:
print(f"\nFAILED: Coverage {project.total_coverage:.1f}% is below threshold {THRESHOLD}%")
sys.exit(1)
print(f"\nPASSED: Coverage {project.total_coverage:.1f}% meets threshold {THRESHOLD}%")
sys.exit(0)
Recipe 5: Excluding Test Files¶
When running coverage on a project, you often want to exclude test files and generated code.
Via the CLI:
Each --exclude value is matched against a path component (a directory or file name), not as a substring against the whole path — rebuild_index.py is not skipped just because it contains build. A dot-prefixed pattern like .egg-info also matches a component it's a suffix of; an underscore-suffixed pattern like test_ also matches a component it's a prefix of.
Via the Python API:
from PyCodeCommenter import CoverageAnalyzer
analyzer = CoverageAnalyzer()
project = analyzer.analyze_directory(
"./",
exclude_patterns=["migrations", "vendor"]
)
project.print_report()
Default exclusions:
CoverageAnalyzer.analyze_directory()always applies its built-in defaults (__pycache__,.git,.venv,venv,env,.tox,.nox,__pypackages__,site-packages,build,dist,.eggs,.egg-info,.mypy_cache,.pytest_cache,node_modules,tests,test_) — includingtests/test_, so you don't need to repeat those.exclude_patternsis added to that list, not a replacement for it; the example above only needs to namemigrations/vendor, the extra patterns the defaults don't already cover.
Recipe 6: Checking a Single Function Programmatically¶
Use the Python API to check the docstring quality of specific code, without touching a file on disk.
from PyCodeCommenter import PyCodeCommenter
code = """
def send_email(to_address: str, subject: str, body: str) -> bool:
\"\"\"Send an email message.
Args:
to_address (str): Recipient email address.
subject (str): Subject of the email.
Returns:
bool: True if the email was sent successfully.
\"\"\"
# body parameter is missing from Args — validator will catch this
import smtplib
return True
"""
commenter = PyCodeCommenter().from_string(code)
report = commenter.validate()
report.print_summary()
# Check programmatically
for issue in report.issues:
print(f"[{issue.severity.value}] {issue.message}")
if issue.suggestion:
print(f" Fix: {issue.suggestion}")
Expected output:
============================================================
VALIDATION REPORT
============================================================
File: None
Coverage: 100.0%
Total Issues: 1
- Errors: 1
- Warnings: 0
- Info: 0
ISSUES:
[ERROR] code:2:send_email: Parameter 'body' is not documented in docstring
→ Suggestion: Add 'body' to the Args section
Recipe 7: Generating and Immediately Validating¶
Generate docstrings and then run validation in one script — useful for CI pipelines that need to both add docs and verify quality in a single run.
import sys
from PyCodeCommenter import PyCodeCommenter
file_path = "src/api.py"
# Step 1: Load and generate
commenter = PyCodeCommenter().from_file(file_path)
if not commenter.parsed_code:
print(f"ERROR: Could not parse {file_path}")
sys.exit(1)
patched_code = commenter.get_patched_code()
# Step 2: Write the patched code back
with open(file_path, "w", encoding="utf-8") as f:
f.write(patched_code)
# Step 3: Validate the updated file
from PyCodeCommenter import DocstringValidator
validator = DocstringValidator(file_path=file_path)
report = validator.validate_all()
report.print_summary()
if report.stats.errors > 0:
sys.exit(1)
print(f"Done. Coverage: {report.stats.coverage_percentage:.1f}%")
Related¶
- CLI Reference — all flags and exit codes
- Python API — full class and method reference
- Configuration —
.pycodecommenter.yamlsetup - Validation Checks — what the validator looks for