Skip to main content

A Python docstring linter with auto-fix support

Project description

pydocfix

PyPI - Version PyPI - Python Version

A Python docstring linter that checks signature ↔ docstring consistency and auto-fixes violations.

Inspired by pydoclint, pydocfix goes further by automatically repairing the issues it finds.

[!NOTE] This project is in beta (v0.1.0b2). APIs and behavior may change before the stable release.

Why pydocfix?

pydoclint pioneered fast signature ↔ docstring consistency checking for Python. However, it can only report violations — all corrections must be done by hand.

pydocfix is built on pydocstring-rs, a CST (Concrete Syntax Tree) parser for docstrings written in Rust by the same author. CST preserves every token's byte offset, whitespace, and formatting, enabling:

  • Byte-level diagnostics — point to the exact token (parameter name, type annotation, section header), not just the line
  • Surgical auto-fix — edits replace precise byte ranges, so fixes never corrupt adjacent content
  • Iterative fix loop — apply non-overlapping fixes, re-parse, repeat until stable

Features

  • Auto-fix — Automatically repair docstring issues with safe/unsafe classification
  • Many rules across multiple categories (Summary, Parameters, Returns, Yields, Raises, Docstring)
  • Google & NumPy style support (powered by pydocstring-rs)
  • Signature ↔ docstring consistency — type mismatches, missing/extra parameters, ordering
  • Default value checking — detect missing optional / default annotations
  • Precise diagnostics — byte-level position information for every violation
  • Baseline — suppress existing violations so only new ones are reported
  • noqa — suppress specific violations inline or file-wide

Benchmark

pydocfix vs pydoclint

pydocfix performs linting and auto-fix generation in a single pass, yet is significantly faster than pydoclint (lint-only) thanks to parallel file processing and a Rust-based CST parser:

Project Files Lines pydocfix pydoclint Speedup
numpy 425 252K 0.74 sec 2.93 sec 4.0x
scikit-learn 635 372K 0.70 sec 4.41 sec 6.3x

Median of 5 runs (+ 1 warmup). pydocfix automatically parallelises across CPU cores (-j flag); pydoclint runs single-threaded.

Feature comparison

pydocfix pydoclint
Auto-fix (safe + unsafe)
Google style
NumPy style
Sphinx style
Parameter checking
Return type checking
Yield checking
Raises checking
Class docstring / __init__ rules -
Class attribute checking -
Default value checking (optional / default)
Byte-level diagnostics
Baseline suppression
Inline # noqa
flake8 plugin
pre-commit hook
Parallel execution

Installation

pip install pydocfix

Requires Python 3.11+.

Quick Start

# Check docstrings (report only)
pydocfix check src/

# Show diff of proposed fixes
pydocfix check src/ --diff

# Apply safe fixes
pydocfix check src/ --fix

# Apply safe + unsafe fixes
pydocfix check src/ --fix --unsafe-fixes

# Select / ignore specific rules or categories
pydocfix check src/ --select PRM --ignore RTN,YLD

# Parallel execution (auto-detected for ≥8 files; override with --jobs)
pydocfix check src/ --jobs 4

Configuration

Configure via pyproject.toml:

[tool.pydocfix]
# Rule selection (see "Rule selectors" for syntax details)
select = ["ALL"]
ignore = ["RIS"]
extend-safe-fixes = ["PRM"]
extend-unsafe-fixes = ["RTN", "YLD"]

# Type annotation style: "signature" | "docstring" | "both" | omitted (default)
#   omitted    — PRM103/RTN103/YLD103 and PRM104/RTN104/YLD104 are all disabled
#   signature  — redundant docstring types flagged (x104); missing signature annotations flagged (x105)
#   docstring  — missing docstring types flagged (x103); redundant signature annotations flagged (x106)
#   both       — missing docstring types flagged (x103); missing signature annotations flagged (x105)
type_annotation_style = "signature"

# Paths/patterns to exclude (in addition to built-in defaults)
exclude = ["tests/", "docs/"]

# Skip section-level rules (PRM001, RTN001, YLD001, RIS001) for one-line docstrings (default: true)
skip_short_docstrings = true

# Treat Optional[T], T | None, and Union[T, None] as equivalent to T
# when comparing types in PRM101/RTN101/YLD101 (default: false)
allow_optional_shorthand = false

# Path to the baseline file (relative to pyproject.toml)
baseline = ".pydocfix-baseline.json"

Rules

Each rule is classified as safe fix, unsafe fix, or report-only.

  • Safe fixes can be applied automatically with --fix (no risk of changing semantics)
  • Unsafe fixes require --fix --unsafe-fixes (may alter docstring meaning)

Summary (SUM)

Code Default Fix Description
SUM001 Missing summary line
SUM002 safe Summary doesn't end with period

Parameters (PRM)

Code Default Fix Description
PRM001 unsafe Missing Args/Parameters section
PRM002 safe Unnecessary Args/Parameters section
PRM003 safe self/cls documented in docstring
PRM004 unsafe Parameter in signature missing from docstring
PRM005 unsafe Parameter in docstring not in signature
PRM006 unsafe Parameter order mismatch
PRM007 unsafe Duplicate parameter name
PRM008 Parameter has no description
PRM009 safe Missing */** prefix on *args/**kwargs
PRM101 unsafe Docstring type doesn't match signature annotation
PRM102 unsafe No type in docstring or signature
PRM103 unsafe No type in docstring
PRM104 safe Redundant type in docstring (signature has annotation)
PRM105 No type annotation in signature (type_annotation_style = "signature" or "both")
PRM106 Redundant type annotation in signature (type_annotation_style = "docstring")
PRM201 unsafe Missing optional for parameter with default
PRM202 unsafe Missing default for parameter with default

Returns (RTN)

Code Default Fix Description
RTN001 unsafe Missing Returns section
RTN002 safe Unnecessary Returns section
RTN003 Returns entry has no description
RTN101 unsafe Return type mismatch
RTN102 unsafe No return type anywhere
RTN103 unsafe No return type in docstring
RTN104 safe Redundant return type in docstring
RTN105 No return type annotation in signature (type_annotation_style = "signature" or "both")
RTN106 Redundant return type annotation in signature (type_annotation_style = "docstring")

Yields (YLD)

Code Default Fix Description
YLD001 unsafe Missing Yields section
YLD002 safe Unnecessary Yields section
YLD003 Yields entry has no description
YLD101 unsafe Yield type mismatch
YLD102 unsafe No yield type anywhere
YLD103 unsafe No yield type in docstring
YLD104 safe Redundant yield type in docstring
YLD105 No yield type annotation in signature (type_annotation_style = "signature" or "both")
YLD106 Redundant yield type annotation in signature (type_annotation_style = "docstring")

Raises (RIS)

Code Default Fix Description
RIS001 unsafe Missing Raises section
RIS002 safe Unnecessary Raises section
RIS003 Raises entry has no description
RIS004 unsafe Raised exception not documented
RIS005 unsafe Documented exception not raised

Docstring (DOC)

Code Default Fix Description
DOC001 unsafe Section order doesn't match convention

Rule selectors

--select, --ignore, --extend-safe-fixes, --extend-unsafe-fixes (CLI) and their pyproject.toml equivalents all accept the same rule selector syntax:

Format Example Matches
Exact code PRM001 PRM001 only
Category prefix PRM All PRM rules
ALL ALL Every rule

Suppressing violations

Inline suppression (# noqa)

Add a # noqa comment on the closing """ line to suppress violations for that docstring.

def foo(x):
    """Short summary."""  # noqa                    # suppress all rules for this docstring

def bar(x):
    """Short summary."""  # noqa: PRM001            # suppress only PRM001

def baz(x):
    """Short summary."""  # noqa: PRM001, RTN001    # suppress multiple rules

# For multiline docstrings, put the comment on the closing """ line
def qux(x: int) -> int:
    """Short summary.

    Args:
        x: A value.
    """  # noqa: RTN001
    return x

Unused # noqa codes are reported as NOQ001 (and removed by --fix).

File-level suppression

Put a # pydocfix: noqa comment on its own line anywhere in the file to suppress violations for every docstring in the file.

# pydocfix: noqa            # suppress all rules in this file
# pydocfix: noqa: PRM001    # suppress only PRM001 in this file

Baseline

The baseline lets you record the current violation state of a project and suppress those existing violations on future runs — so only new violations are reported. This makes gradual adoption easier: fix violations at your own pace.

# Record all current violations as the baseline
pydocfix check src/ --baseline .pydocfix-baseline.json --generate-baseline

# Future runs only report violations not in the baseline
pydocfix check src/ --baseline .pydocfix-baseline.json

Or configure the baseline path in pyproject.toml so you don't need the flag every time:

[tool.pydocfix]
baseline = ".pydocfix-baseline.json"

Then generate and use it:

pydocfix check src/ --generate-baseline    # write baseline
pydocfix check src/                        # only new violations reported

The baseline file is a JSON file that records violations by symbol name (e.g. MyClass.my_method) rather than line number, so it stays stable when unrelated code is added or removed. Fixed violations are automatically removed from the baseline on the next run.

pre-commit

Add to .pre-commit-config.yaml:

repos:
  - repo: https://github.com/ryumasai/pydocfix
    rev: v0.1.0b2
    hooks:
      - id: pydocfix

To enable auto-fix:

      - id: pydocfix
        args: [--fix]

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydocfix-0.1.0b2.tar.gz (90.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydocfix-0.1.0b2-py3-none-any.whl (77.8 kB view details)

Uploaded Python 3

File details

Details for the file pydocfix-0.1.0b2.tar.gz.

File metadata

  • Download URL: pydocfix-0.1.0b2.tar.gz
  • Upload date:
  • Size: 90.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydocfix-0.1.0b2.tar.gz
Algorithm Hash digest
SHA256 9c379b375734e14fd2d940934cc8c3d3b3914a029370daad7cf70d78fadc91e7
MD5 9c2e202d8816c14aa46f36fc8fd69c4e
BLAKE2b-256 764f25846caa34bfe06bc19c3cbbb65c17411ba630e1b2574a137fb58b2babfd

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydocfix-0.1.0b2.tar.gz:

Publisher: release.yml on ryumasai/pydocfix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydocfix-0.1.0b2-py3-none-any.whl.

File metadata

  • Download URL: pydocfix-0.1.0b2-py3-none-any.whl
  • Upload date:
  • Size: 77.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydocfix-0.1.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 495ee5857bd26c8f646bb3d36df8a704f498ddb2d6a26cd630d6beb0325d8924
MD5 7e737e9c36d6fc5142b1d068484bc94e
BLAKE2b-256 ed82b0974b13948618be3966994b66804272da1d5c10f941de63dd1d9b072bab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydocfix-0.1.0b2-py3-none-any.whl:

Publisher: release.yml on ryumasai/pydocfix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page