pydoclint

repository·main·Indexed 42 days ago

https://github.com/jsh9/pydoclint

A high-performance Python docstring linter (version 0.9.1) that verifies if docstring sections—such as arguments, returns, yields, and raises—match actual function signatures and implementations. It supports NumPy, Google, and Sphinx docstring styles and can be used as a standalone command line tool or a flake8 plugin.

Tokens
18.7K
Snippets
53
Records
77
Agent score
52%

What's inside pydoclint

  1. Sphinx style deviations in pydoclint

    main
    When using the Sphinx docstring style, pydoclint uses a specific header for yield types to avoid confusion with return types. Instead of the common rtype header, pydoclint expects ytype to specify the type of what a function yields.
  2. Writing type hints for pydoclint

    main

    To prevent style violations, ensure that docstring type annotations match the signature type annotations exactly. pydoclint does not currently resolve equivalencies between different type hint syntaxes.

    For example, the following equivalencies are not recognized as identical:

    • Optional[str] vs str | None
    • Union[str, int] vs int | str
    • Tuple[str, int] vs tuple[str, int]

    Additionally, avoid using descriptive strings like int, optional in place of Optional[int], as pydoclint requires verbatim matching.

  3. Use inline docstrings for class attributes

    main

    If you enable the --require-inline-class-var-docs option, pydoclint requires that class attributes be documented using inline docstrings (string literals placed directly after the assignment) instead of an Attributes section in the class docstring.

    This applies to Numpy, Google, and Sphinx styles. The type can be specified as the first part of the docstring followed by a colon.

    class MyClass:
        """My class that does things."""
    
        field1 = 5
        """int: My first field"""
  4. Compare Native vs flake8 usage

    main

    Choosing between the native tool and the flake8 plugin depends on your workflow:

    FeatureNative toolflake8 plugin
    SpeedSlightly fasterSlightly slower (runs other plugins)
    OmissionSupports baseline [*] and inline # noqaSupports inline and project-wide omission
    BaselineSupports logging current violation stateNot mentioned

    Note on inline suppression in Native mode: You can suppress violations using # noqa: DOCxxx. Use the --native-mode-noqa-location option to specify if the comment should be on the definition line or at the end of the docstring (after the triple quotes).

  5. Understand pydoclint's static analysis limitations

    main

    Because pydoclint uses Python's official ast module for static syntax analysis (rather than executing code), it does not resolve aliases or recognize non-standard Pythonic naming conventions. To avoid false positives or linting failures, avoid the following patterns:

    • Renaming decorators: Using custom names for classmethod or staticmethod (e.g., hello = classmethod).
    • Non-standard method arguments: Using names other than self or cls for the first argument of methods.
    • Type alias mismatches: Renaming type annotations in the signature using from typing import List as hello but using the original name (e.g., List[int]) in the docstring. pydoclint expects the docstring type annotations to match the signature type annotations verbatim.
  6. Numpy style deviations in pydoclint

    main

    When using the numpy docstring style, pydoclint enforces specific formats for type annotations and default values to ensure consistency and avoid ambiguity.

    Type Annotations

    pydoclint rejects natural language descriptions (e.g., iterable object, list of str). Instead, it requires type hints that match Python function signatures (e.g., Iterable[int], list[str]).

    Default Values

    pydoclint rejects informal ways of specifying defaults (e.g., int, optional or default 2). You must use the explicit default=VALUE syntax.

    # Accepted Numpy Style
    
    Parameters
    ----------
    iterable : Iterable[int]
    shape : int | tuple[int, ...]
    files : list[str]
    flag : int | None, default=None
  7. Understand docstring style mismatch (DOC003)

    main

    The DOC003 violation code is triggered when pydoclint detects that a docstring's actual format differs from the style specified in your configuration via the --style option.

    Detection Mechanism

    pydoclint uses lightweight keyword heuristics at the docstring's indentation level to identify styles:

    • NumPy: Looks for section headers followed by dashed underlines (e.g., Returns + -------).
    • Google: Looks for top-level headers like Args:, Returns:, Yields:, Raises:, Examples:, or Notes:.
    • Sphinx/reST: Looks for top-level field lists like :param, :type, :raises, :return:, :rtype:, :yield:, or :ytype:.

    Handling Logic

    • Exactly one match: If the detected style differs from your configured --style, DOC003 is emitted. Note that malformed Google sections are treated as mismatches.
    • No matches: The tool assumes the docstring matches your configured style and skips mismatch warnings.
    • Multiple matches: If a docstring mixes styles (e.g., Google Args: and Sphinx :param), DOC003 is emitted for every configured style.

    Behavior after detection

    When DOC003 is triggered, pydoclint still parses the docstring using your configured style, but it suppresses follow-up checks (like argument type-hint expectations or return/yield consistency) to prevent cascading false positives. You should resolve the style mismatch first.

  8. Use baselines to manage existing violations

    main

    The baseline feature allows you to record current violations so that pydoclint only reports new ones. This is useful for gradually adopting the tool in existing projects.

    1. Set a baseline file: Pass the path to a file via --baseline. You can also define this in pyproject.toml under [tool.pydoclint].
    2. Generate a baseline: Use --generate-baseline=True to create a file containing all current violations.
    3. Automatic updates: With --auto-regenerate-baseline (default: True), the baseline file is automatically updated whenever you fix violations and rerun the tool.

    By default, if --generate-baseline is not passed, pydoclint reads the baseline file and ignores all violations listed within it.

    [tool.pydoclint]
    baseline = "pydoclint-baseline.txt"
    # Generate the initial baseline file
    pydoclint --baseline pydoclint-baseline.txt --generate-baseline
  9. Gradually adopt pydoclint using the baseline feature

    main

    To introduce pydoclint to a legacy project without fixing all existing errors immediately, use the baseline feature. This allows you to log the current state of violations so that you only need to fix new ones introduced in subsequent commits.

    Use these configuration options to manage the baseline:

    • --baseline
    • --generate-baseline
    • --auto-regenerate-baseline
  10. Google style deviations in pydoclint

    main

    When using the Google docstring style, pydoclint has specific requirements for type annotations and default values, though these can be adjusted via configuration.

    Type Annotations

    By default, pydoclint requires argument types to be present in the docstring and checks for consistency in return and yield types.

    To change this behavior, use these configuration options:

    • --arg-type-hints-in-docstring: Set to False to stop requiring types in Args.
    • --check-return-types: Set to False to disable return type consistency checks.
    • --check-yield-types: Set to False to disable yield type consistency checks.

    Default Values

    pydoclint rejects the Defaults to X prose style. You must use the (type, default=VALUE) format within the argument description.

    # Accepted Google Style
    """
    This is a function.
    
    Args:
        arg1 (int): Arg 1
        arg2 (float): Arg 2
        arg3 (Optional[Union[float, int, str]]): Arg 3
    
    Returns:
        int: Result
    """
    
    # For default values, use this format:
    """
    Args:
        flag (int, default=None): The flag
    """
  11. Configure pydoclint as a pre-commit hook

    main

    You can integrate pydoclint into your pre-commit workflow using either native mode or the flake8 plugin mode. Replace <latest_tag> with the actual release tag from the GitHub releases page.

    # Native mode
    - repo: https://github.com/jsh9/pydoclint
      rev: <latest_tag>
      hooks:
        - id: pydoclint
          args: [--style=google, --check-return-types=False]
    
    # flake8 plugin mode
    - repo: https://github.com/jsh9/pydoclint
      rev: <latest_tag>
      hooks:
        - id: pydoclint-flake8
          args: [--style=google, --check-return-types=False]
  12. Ignore violations when using pydoclint as a flake8 plugin

    main

    When using pydoclint as a flake8 plugin, suppression follows standard flake8 conventions. You can ignore specific violation codes or entire categories by adding a # noqa: comment to the relevant function or class definition.

    • To ignore specific codes: # noqa: DOC201, DOC301
    • To ignore a category: # noqa: DOC2 (suppresses all DOC2xx violations)
    def my_function(  # noqa: DOC201, DOC301
            arg1,
            arg2,
    ) -> None:
        ...
    
    
    def my_function_category(  # noqa: DOC2
            arg1,
            arg2,
    ) -> None:
        ...