Skip to content

Releases: data-science-extensions/docstring-format-checker

v1.11.4

25 Jan 08:08

Choose a tag to compare

📋 Overview

Significantly expand the project documentation with comprehensive usage guides and detailed CLI walkthroughs. This release also introduces performance optimisations for file discovery on Linux systems, refines the integration instructions for pre-commit, and standardises the grammatical tone across the entire codebase.

✨ New Features

📘 Introduce comprehensive usage documentation

Create three new major documentation sections to assist developers at all experience levels.

  • Provide a clear installation path and a guided first check in the getting_started.md guide.
  • Detail every global and section-specific configuration option with practical examples and troubleshooting tips in the configuration.md page.
  • Deliver an extensive walkthrough of command-line interactions, including sample terminal outputs and format comparisons, in the command_line_interface.md guide.

🚀 Optimise file discovery performance

Refactor the get_all_files() function in scripts.py to utilise the Linux find command for significantly faster file retrieval in large repositories. Maintain a robust fallback to the Path.glob() method to ensure cross-platform compatibility.

⚙️ Technical Improvements

🛡️ Refine file exclusion logic for documentation

Enhance the check_blacken_docs() and run_blacken_docs() functions to exclude documentation markdown files from the blacken-docs process. This ensures that intentional "bad" code examples used for demonstration purposes remain unfixed by the formatter, preserving their educational value.

🔗 Improve pre-commit and installation guides

Update the README.md with modern installation instructions for every major package manager, referencing the latest 1.* version. Introduce a dedicated section for pre-commit integration with an example configuration for .pre-commit-config.yaml to help users automate their docstring validation.

🛠️ Clean up internal callbacks and metadata

Remove redundant parameter descriptions for ctx, param, and value within the _show_usage_examples_callback() and _show_config_example_callback() functions in cli.py. Update the GlobalConfig() and SectionConfig() dataclasses in config.py with descriptive field() metadata to improve IDE tooltip clarity.

✍️ Documentation and Styling

🎨 Enhance visual documentation styling

Introduce custom CSS styling in code_chunks.css to display the TOML logo icon next to configuration code blocks. Update the mkdocs.yaml configuration to enable the content.code.select and content.code.copy features, and standardise the code font to improve readability.

📋 Standardise internal grammatical tone

Perform a comprehensive linguistic sweep to ensure that all internal docstrings and comments follow a consistent grammatical structure. Standardise descriptions of dfc behaviour to use the third-person singular (e.g., "reports", "fails", "checks") to provide a professional and unified tone throughout the project.

💪 Pull Requests

  • Enhance documentation, introduce comprehensive usage guides, and improve file discovery performance by @chrimaho in #39

Full Changelog: v1.11.3...v1.11.4

v1.11.3

24 Jan 06:12

Choose a tag to compare

📃 Overview

Introduce a comprehensive JSON Schema generation pipeline to automate the validation of pyproject.toml configurations. This release also enhances the configuration models with rich metadata for improved IDE support and refines the CI workflow to ensure schema integrity across the codebase.

✨ New Features

🏗️ Implement JSON Schema Generation Pipeline

Introduce the DFCSchemaGenerator() and PyprojectSchemaGenerator() classes to automatically generate JSON schemas from internal Python configuration models. This ensures that the configuration options are always synchronised with the current implementation.

⚙️ Technical Improvements

📝 Enhance Configuration Metadata

Extend the GlobalConfig() and SectionConfig() dataclasses in config.py with descriptive metadata using the field() function. This enables modern IDEs such as VS Code to provide real-time tooltips and autocomplete for the [tool.dfc] section in pyproject.toml.

🛡️ Integrate Schema Integrity Workflow in CI

Update the CI pipeline in ci.yml to automatically generate and verify JSON schemas. The workflow now ensures that any changes to configuration models are reflected in the generated schemas, preventing documentation drift.

⚙️ Refine Schema Generator Robustness

Improve the reliability of the generate_config_schema.py utility with several robust enhancements.

  • Handle Optional and Union types more effectively, ensuring correct mapping to JSON Schema type arrays and null values.
  • Standardise the detection of Literal types using the get_origin() function.
  • Optimise package information retrieval by replacing the lru_cache() decorator with the cached_property() decorator for better performance.
  • Implement conditional imports for tomllib to maintain compatibility with Python versions below 3.11 using the tomli package.

🐛 Fix Documentation and Formatting

Resolve issues with broken URLs and standardise formatting across documentation files to improve clarity and maintainability.

📙 Documentation

📘 Document the JSON Schema System

Initialise a comprehensive README.md in the src/schemas/json/ directory to guide developers on how to enable and maintain JSON Schema validation for their local project configurations.

💪 Pull Requests

  • Introduce automated JSON Schema generation for pyproject.toml configuration validation by @chrimaho in #38

Full Changelog: v1.11.2...v1.11.3

v1.11.2 - Doctest Utilities and Configuration Refinement

14 Jan 03:48

Choose a tag to compare

📃 Overview

Introduce new utility functions for executing doctests and refine the configuration loading process to better handle unordered sections. This release also standardises documentation metadata and improves the reliability of the coverage reporting workflow.

✨ New Features

🔍 Integrate Doctest Checking Functions

Introduce automated doctest execution to verify code examples within docstrings.

  • Implement the check_doctest() function in src/utils/scripts.py to run doctests across all Python files in the package.
  • Implement the check_doctest_module() function to target specific modules for doctest validation.
  • Implement the check_doctest_cli() function to provide a command-line interface for module-specific doctest checking.

🐛 Bug Fixes

⚙️ Refine Configuration Order Validation

Resolve an issue where multiple sections without an explicit order value caused duplicate key errors.

  • Update the SectionConfig() class to consistently allow None for the order attribute.
  • Update the _parse_sections_config() function in config.py to remove the default value of 0 when extracting order from configuration data.
  • Ensure that sections without an explicit order are correctly sorted to the end of the validation sequence.

⚙️ Technical Improvements

🚀 Enhance Project Workflow

Improve the robustness of the development and documentation workflows.

  • Update the git_add_coverage_report() function to use the --force flag when adding the coverage report directory, ensuring reports are captured regardless of ignore rules.
  • Fix typographical errors and standardise the project title to docstring-format-checker across documentation files.
  • Refine the documentation home page to use a dedicated coverpage_icon_source variable in mkdocs.yaml for better maintainability.

💪 Pull Requests

  • Enhance Configuration Handling for non-Ordered Sections by @chrimaho in #37

Full Changelog: v1.11.1...v1.11.2

v1.11.1 - Static Type Checking and Robust Sorting

04 Jan 23:21

Choose a tag to compare

📃 Overview

Introduce static type checking with Pyright and refine the section sorting logic to improve the robustness and reliability of the docstring validation process. This release also enhances the test suite with more explicit assertions and optimises the development workflow.

✨ New Features

🔍 Integrate Pyright Static Analysis

Integrate pyright into the development workflow to ensure strict type safety across the codebase.

  • Add pyright to the dev dependency group in pyproject.toml.
  • Implement the check_pyright() function in src/utils/scripts.py to perform automated static analysis.
  • Update the check() function to include Pyright validation as a standard step in the project's quality assurance process.

🐛 Bug Fixes

⚙️ Refine Section Sorting Logic

Improve the robustness of the section sorting mechanism when handling optional order values.

  • Update the _parse_sections_config() function in config.py to handle None values for section orders by defaulting to float("inf"). This ensures that unordered sections are consistently placed at the end of the sequence.
  • Standardise the sorting logic within the ._build_section_patterns() and ._build_expected_section_order() methods in the DocstringChecker() class to handle optional orders gracefully.

⚙️ Technical Improvements

🧪 Enhance Test Assertions

Strengthen the test suite by introducing more explicit assertions and type validations.

  • Add assertions to verify that func_node is an instance of the ast.FunctionDef() or ast.AsyncFunctionDef() class in various test cases.
  • Update the TestParameterMismatch() class to verify that docstring and error_message are not None before performing string operations, resolving potential type errors and improving test reliability.

🧹 Optimise Validation Workflow

Refine the project's validation script and repository maintenance.

  • Reorder the check() function in scripts.py to execute check_mkdocs() after check_build(), ensuring that the documentation build is verified after the package build.
  • Update the .gitignore file to include the .complexipy_cache/* pattern, preventing local cache artefacts from being tracked.

💪 Pull Requests

  • Integrate Pyright and Refine Section Sorting Logic by @chrimaho in #36

Full Changelog: v1.11.0...v1.11.1

v1.11.0 - Flexible Section Ordering and Multi-word Headers

04 Jan 03:08

Choose a tag to compare

📃 Overview

Introduce support for unordered docstring sections and multi-word section headers to provide greater flexibility in docstring formatting. This release also includes bug fixes for section name validation and improvements to the test suite.

✨ New Features

🔓 Support Unordered Sections

Allow sections to be defined with order = null in the configuration. These sections can appear anywhere within a docstring without triggering sequence validation errors. This is particularly useful for sections like Deprecation Warning or Note that may appear at different positions depending on the context.

📝 Support Multi-word Section Headers

Update the section detection logic to support headers containing multiple words. This enables the use of descriptive section names such as Custom List or Deprecation Warning while maintaining strict validation of other rules like colon usage and title casing.

🐛 Bug Fixes

🐛 Fix Multi-word Section Validation

Resolve an issue where multi-word section names were incorrectly triggering "requires parenthesized types" errors. The validation regex now correctly handles spaces within section headers.

🛠️ Fix Test Suite Syntax Error

Correct a SyntaxError in the test helper _check_docstring() caused by improper indentation of generated Python content.

⚙️ Technical Improvements

🧪 Expand Test Coverage

Add a comprehensive suite of tests for unordered sections, covering various placements, case-insensitivity, and interaction with required sections. Maintain 100% code coverage across the entire project.

📖 Update Documentation

Update the README.md to include details and examples for the new flexible section ordering feature.

💪 Pull Requests

  • Support Unordered Docstring Sections and Multi-word Names by @chrimaho in #35

Full Changelog: v1.10.1...v1.11.0

v1.10.1 - Standardise Dependencies and Modernise CI/CD Workflows

04 Jan 01:38

Choose a tag to compare

📝 Summary

This release focuses on standardising the project's dependency management and modernising the CI/CD workflows to ensure robust support across multiple Python versions. Introduce environment markers in pyproject.toml to allow for version-specific package requirements, specifically supporting Python 3.9 while leveraging newer package versions for Python 3.10 and above. Upgrade several key GitHub Actions to their latest versions to improve security, performance, and reliability. Ensure a more consistent and maintainable development environment through these targeted enhancements.

📊 Release Statistics

Attribute Note
Version: v1.10.1
Python Support: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
Test Coverage: 100% (1035 statements)
Pylint Score: 10.00/10
Complexity: All functions ≤13 threshold
Functions: 106
Tests Passing: 250/250
Files Changed: 3
Lines Added: 37
Lines Removed: 30
Commits: 12
Pull Requests Merged: 6 (PR #29, #30, #31, #32, #33, #34)

🎯 Standardise Dependencies with Python Version Markers

🔍 Overview

Improve the project's dependency management by introducing environment markers that allow for version-specific package requirements. This ensures that the project remains compatible with Python 3.9 while taking advantage of newer features and bug fixes available in more recent package versions for Python 3.10 and above.

🛠️ Key Improvements

Introduce Environment Markers

Refactor pyproject.toml to use environment markers for several key dependencies. This allows the project to specify different version ranges based on the Python runtime version.

  • Update dev dependencies:
    • ipykernel: Use 6.* for Python <3.10 and 7.* for Python >=3.10.
    • isort: Use 6.* for Python <3.10 and 7.* for Python >=3.10.
    • pylint: Use 3.* for Python <3.10 and 4.* for Python >=3.10.
  • Adjust docs requirements:
    • docstring-inheritance: Use 2.* for Python <3.10 and 3.* for Python >=3.10.
    • mkdocstrings: Use 0.* for Python <3.10 and 1.* for Python >=3.10.
    • mkdocstrings-python: Use 1.* for Python <3.10 and 2.* for Python >=3.10.
  • Bump test dependencies:
    • pytest: Use 8.* for Python <3.10 and 9.* for Python >=3.10.
    • complexipy: Upgrade to 5.* to leverage the latest complexity analysis features.

Standardise Dependency Formatting

Ensure consistent formatting across all dependency definitions. Standardise the whitespace and structure of environment markers to improve readability and maintainability.

⚙️ Modernise CI/CD Workflows and GitHub Actions

🔍 Overview

Upgrade the project's CI/CD infrastructure by bumping several key GitHub Actions to their latest versions. This ensures that the project benefits from the latest security patches, performance improvements, and feature updates provided by the action maintainers.

🛠️ Key Improvements

Upgrade GitHub Actions

Bump the versions of several essential GitHub Actions used in the ci.yml and cd.yml workflows:

  • actions/checkout: Upgrade from v5 to v6.
  • actions/setup-python: Upgrade from v5 to v6.
  • actions/upload-artifact: Upgrade from v4 to v6.
  • actions/download-artifact: Upgrade from v5 to v7.
  • astral-sh/setup-uv: Upgrade from v6 to v7.

Refine Workflow Configurations

Update the workflow files to ensure consistent environment handling and version referencing. Standardise the use of ${{ env.VERSION }} and other environment variables to improve the reliability of the automated build and release processes.

💪 Pull Requests

New Contributors

Full Changelog: v1.10.0...v1.10.1

v1.10.0 - Enhance Section Validation and Update Dependencies

04 Jan 00:34

Choose a tag to compare

📝 Summary

This release focuses on improving the robustness of docstring section validation, particularly regarding case sensitivity and error reporting. Standardise section header detection to handle various capitalisation styles while preserving original casing in error messages. Modernise the project's dependency management by introducing Dependabot and upgrading several pre-commit hooks. Refactor utility scripts for better clarity and update package metadata to align with standard practices. Ensure a more consistent and user-friendly experience through these enhancements.

📊 Release Statistics

Attribute Note
Version: v1.10.0
Python Support: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
Test Coverage: 100% (1035 statements, +2 from v1.9.0)
Pylint Score: 10.00/10
Complexity: All functions ≤13 threshold
Functions: 106 (unchanged from v1.9.0)
Tests Passing: 250/250 (unchanged from v1.9.0)
Files Changed: 8
Lines Added: 76
Lines Removed: 53
Commits: 10
Pull Requests Merged: 1 (PR #29)

🎯 Enhance Docstring Section Validation

🔍 Overview

Improve the reliability of section detection and validation within docstrings. Ensure that the tool correctly identifies configured sections regardless of their case in the docstring, while providing clearer error messages.

🛠️ Key Improvements

Case-Insensitive Matching

Refactor several internal methods to handle section names more robustly. Lowercase section names for configuration lookups but preserve the original case when reporting errors to the user.

  • Update ._validate_single_admonition() to use a lowercased version of the section title for configuration checks.
  • Refactor ._validate_admonition_has_no_colon() to ensure consistent case-insensitive lookup.
  • Improve ._check_non_admonition_colon_usage() to correctly identify non-admonition sections regardless of case.
  • Standardise section header detection in ._detect_any_section_header() and ._detect_section_header().

Clearer Error Reporting

Update ._validate_all_required_sections() to wrap missing section names in single quotes. This makes the error messages more readable and consistent with other validation errors.

Example of new output:
Missing required section: 'summary'

⚙️ Update Dependencies and CI/CD Workflows

🔍 Overview

Modernise the development environment and automate dependency maintenance to ensure the project remains secure and up-to-date.

🛠️ Key Improvements

Automate Dependency Updates

Introduce a new .github/dependabot.yml configuration to enable weekly automated updates for GitHub Actions. Include custom labels and designated reviewers to streamline the maintenance process.

Upgrade Pre-commit Hooks

Bump the versions of several key pre-commit hooks to leverage the latest improvements and bug fixes:

Hook Old Version New Version
black 25.1.0 25.12.0
blacken-docs 1.19.1 1.20.0
isort 6.0.1 7.0.0
pyupgrade v3.20.0 v3.21.2
pycln v2.5.0 v2.6.0
uv-pre-commit 0.8.8 0.9.21

Refine CI/CD Workflow

Update the .github/workflows/cd.yml workflow to use ${{ env.VERSION }} consistently for version references. Expose GITHUB_TOKEN and REPOSITORY_NAME to the changelog generation step to ensure it has the necessary context.

🧹 Refactor Utility Scripts and Metadata

🔍 Overview

Clean up internal utility scripts and ensure package metadata is correctly defined.

🛠️ Key Improvements

Improve Script Clarity

Add a comprehensive file header to src/utils/scripts.py that outlines its purpose, usage, and provides examples. Improve the discoverability and usability of the internal tooling.

Simplify Git Operations

Refactor git_fix_tag_reference() to remove redundant comments and simplify the implementation. Fix a minor formatting issue in git_refresh_current_branch() by removing an extra space in the git pull command.

Update Package Metadata

Refactor src/docstring_format_checker/__init__.py to use the correct Author-email metadata key. Ensure that the author's email is correctly exposed in the package metadata as __author_email__.

🧪 Improve Test Consistency

🔍 Overview

Update the test suite to align with the improved error message formatting.

🛠️ Key Improvements

Update Assertions

Refactor tests in src/tests/test_cli.py and src/tests/test_core.py to expect the new quoted format for missing section errors. Ensure that the test suite remains in sync with the core validation logic.

What's Changed

  • Enhance Section Validation and Update Dependencies by @chrimaho in #28

Full Changelog: v1.9.0...v1.10.0

v1.9.0 - Improve Parameter Mismatch Reporting and Test Robustness

28 Dec 05:34

Choose a tag to compare

📝 Summary

The focus of this release is on improving the clarity of parameter mismatch error messages and enhancing the robustness of the test suite. Introduce targeted detection for variadic parameters (*args, **kwargs) documented with leading asterisks in docstrings, and provide actionable guidance to remove them. Refactor test assertions to use native Python assert statements, standardise return type annotations in tests, and fix various formatting issues in test data generation. Ensure a more user-friendly experience and a more maintainable codebase through these enhancements.

📊 Release Statistics

Attribute Note
Version: v1.9.0
Python Support: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
Test Coverage: 100% (1033 statements, +11 from v1.8.0)
Pylint Score: 10.00/10
Complexity: All functions ≤13 threshold
Functions: 106 (unchanged from v1.8.0)
Tests Passing: 250/250 (+2 from v1.8.0)
Files Changed: 6
Lines Added: 119
Lines Removed: 20
Commits: 12
Pull Requests Merged: 1 (PR #27)

🎯 Improve Parameter Mismatch Reporting

🔍 Overview

Enhance the parameter mismatch error output to provide clearer, more actionable feedback when variadic parameters are documented with leading asterisks. Reduce confusion by identifying that the parameter names match once the asterisks are ignored, rather than reporting them as entirely separate missing and extra parameters.

❓ Problem Statement

When validating functions with *args or **kwargs, the tool previously reported a mismatch if the docstring included the asterisks (e.g., *args (Any):). This resulted in a confusing error message that listed the parameter as both missing from the docstring (without asterisks) and extra in the docstring (with asterisks).

Example of previous confusing output:

Params section mismatch:
    - In signature but not in docstring: 'args', 'kwargs'
    - In docstring but not in signature: '*args', '**kwargs'

💡 Solution

Update the mismatch detection logic to recognise when a parameter name in the docstring matches a signature parameter after stripping leading asterisks.

Targeted Asterisk Detection

Update ._build_param_mismatch_error() to detect asterisk-only mismatches. When found, the tool now emits a specific message:

Parameter mismatch:
  - Parameter 'args' found in docstring as '*args'. Please remove the asterisk.
  - Parameter 'kwargs' found in docstring as '**kwargs'. Please remove the asterisks.

Robust Parameter Extraction

Strengthen the regex pattern in ._extract_documented_params() to correctly capture parameters with exactly zero, one, or two leading asterisks using \*{0,2}. Ensure that only valid Python parameter prefix patterns are matched.

🧪 Enhance Test Suite Robustness

🔍 Overview

Refactor the test suite to improve readability, maintainability, and alignment with modern Python testing standards. Standardise assertions, improve type safety, and fix formatting issues in test data.

🛠️ Key Improvements

Standardise Assertions

Replace unittest style assertions (e.g., .assertIn(), .assertFalse()) with native Python assert statements across the test suite. Align the codebase with pytest conventions and improve the readability of test failures.

Improve Type Safety

Add explicit None return type annotations to various test methods in src/tests/test_core.py. Ensure better type checking and consistency across the test suite.

Fix Test Data Formatting

Utilise dedent() for all dynamically generated Python file content in tests. Ensure that leading whitespace is correctly handled, preventing potential parsing issues or incorrect indentation in temporary test files.

Resolve Syntax Conflicts

Fix nested docstring syntax in test cases by replacing inner triple double quotes with triple single quotes. Prevent syntax errors when parsing code blocks that contain their own docstrings.

⚙️ Internal Refactorings

🛡️ Avoid Input Mutation

Refactor ._build_param_mismatch_error() to work with local copies of the missing_in_docstring and extra_in_docstring lists. Prevent unintended side effects on caller functions that might rely on the original lists remaining unchanged.

📏 Improve Test Output Visibility

Increase the default diff width for test output to 120 characters in pyproject.toml. Ensure that long error messages and diffs are clearly visible in the terminal without being prematurely wrapped.

💪 Pull Requests

  • Improve Error Messages for Asterisk Parameter Mismatches by @chrimaho in #27

Full Changelog: v1.8.0...v1.9.0

v1.8.0 - Support All Python Function Parameter Types

20 Dec 05:09

Choose a tag to compare

Summary

This release introduces comprehensive support for all Python function parameter types, ensuring accurate docstring validation for complex function signatures. It adds recognition for positional-only parameters (before /), keyword-only parameters (after *), variable positional arguments (*args), and variable keyword arguments (**kwargs). Additionally, this release fixes default value detection for positional-only arguments and updates the package configuration. These enhancements ensure that the docstring format checker correctly identifies and validates parameters across all modern Python function definitions.

Release Statistics

Attribute Note
Version: v1.8.0
Python Support: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
Test Coverage: 100% (1022 statements, +23 from v1.7.0)
Pylint Score: 10.00/10
Complexity: All functions ≤13 threshold
Functions: 106 (-3 from v1.7.0)
Tests Passing: 248/248 (+7 from v1.7.0)
Files Changed: 3
Lines Added: 2520
Lines Removed: 2168
Commits: 4
Pull Requests Merged: 1 (PR #26)

🎯 Enhance Parameter Extraction

Overview

Introduce comprehensive parameter extraction logic to support all five Python parameter types: positional-only, positional-or-keyword, variable positional, keyword-only, and variable keyword arguments. This ensures that the docstring format checker correctly identifies and validates parameters in complex function signatures, including those using / and * separators.

Problem Statement

Incomplete Parameter Extraction

The docstring format checker previously only extracted standard positional parameters (args.args) from function signatures. It failed to recognise:

  1. Positional-Only Parameters (before /): Parameters that must be passed by position.
  2. Keyword-Only Parameters (after *): Parameters that must be passed by name.
  3. Variable Positional Arguments (*args): Arbitrary positional arguments.
  4. Variable Keyword Arguments (**kwargs): Arbitrary keyword arguments.

This limitation caused validation errors or false positives when checking functions that utilised these modern Python features.

Real-World Example:

Consider this function using keyword-only parameters:

@overload
def print_or_log_output(message: str, print_or_log: Literal["print"]) -> None: ...
@overload
def print_or_log_output(
    message: str,
    print_or_log: Literal["log"],
    *,
    log: Logger,
    log_level: log_levels = "info",
) -> None: ...
def print_or_log_output(
    message: str,
    print_or_log: Literal["print", "log"] = "print",
    *,
    log: Optional[Logger] = None,
    log_level: log_levels = "info",
) -> None:
    """
    Print or log the output.

    Params:
        message (str): The message to print or log.
        print_or_log (Literal["print", "log"]): The action to perform.
        log (Optional[Logger]): The logger to use.
        log_level (log_levels): The log level to use.
    """
    ...

Previously, the checker would fail to find log and log_level in the function signature, reporting them as undocumented parameters or extra parameters in the docstring.

Solution

Comprehensive Parameter Extraction

Implement a new ._extract_all_params() method in the DocstringChecker class that iterates through all parameter categories in the AST arguments node:

  • posonlyargs: Positional-only arguments.
  • args: Positional-or-keyword arguments.
  • vararg: Variable positional arguments (*args).
  • kwonlyargs: Keyword-only arguments.
  • kwarg: Variable keyword arguments (**kwargs).

Enhanced Type Annotation Capture

Update the ._extract_param_types() method to utilise ._extract_all_params(), ensuring that type annotations are captured for every parameter found. This allows the validator to correctly match docstring types with signature types for all parameter kinds.

Improved Validation Logic

Refactor ._is_params_section_required() and ._validate_param_types() to account for the presence of any parameter type, ensuring that docstrings are required and validated whenever any parameters exist in the signature.

💪 Pull Requests

  • Enhance Parameter Extraction to Support All Python Function Parameter Types by @chrimaho in #26

Full Changelog: v1.7.0...v1.8.0

v1.7.0 - Add Configurable Optional Suffix Validation

19 Dec 12:04

Choose a tag to compare

Summary

This release introduces a major new feature: configurable validation for the , optional suffix in parameter docstrings through three distinct modes ("silent", "validate", "strict") that accommodate different documentation styles from legacy codebases to strict standards. Additionally, this release modernises the type checking infrastructure by migrating from [mypy] to [ty], delivering faster performance and better Python 3.14 support. GitHub Actions workflows are updated to Python 3.14, removing deprecated configuration parameters whilst maintaining comprehensive CI/CD coverage. The implementation includes five new validation methods with complete test coverage, bringing the total to 241 passing tests whilst maintaining 100% code coverage (999 statements) and a perfect Pylint score of 10.00/10. These enhancements enable fine-grained control over optional parameter documentation patterns whilst modernising the project's tooling infrastructure for continued Python evolution.

Release Statistics

Attribute Note
Version: [v1.7.0]
Python Support: 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
Test Coverage: 100% (999 statements, +48 from v1.6.3)
Pylint Score: 10.00/10
Complexity: All functions ≤13 threshold
Functions: 109 (+3 validation methods)
Tests Passing: 241/241 (+18 from v1.6.3)
Files Changed: 9
Lines Added: 684
Lines Removed: 48
Commits: 4 (3 feature commits + 1 merge)
Pull Requests Merged: 1 (PR #25)
Type Checker: Ty v0.0.4 (migrated from MyPy v1.14.1)
Python Version: 3.14 (upgraded from 3.13 in workflows)

🎯 Configurable Optional Suffix Validation

Overview

Introduce comprehensive validation system for the , optional suffix in parameter docstrings with three configurable modes that accommodate different documentation philosophies: from legacy compatibility to strict enforcement. This feature addresses the long-standing inconsistency in Python docstring conventions where some projects require explicit , optional suffixes for parameters with default values whilst others omit them entirely, relying on type hints or default value mentions.

Problem Statement

Documentation Inconsistency Challenge

Python docstrings lack a standardised convention for indicating optional parameters (those with default values). Different projects adopt varying approaches:

  • NumPy Style Projects: Use , optional suffix explicitly (e.g., param (int, optional):)
  • Google Style Projects: Often omit suffix, rely on default value mention in description
  • Sphinx Style Projects: Inconsistent usage across different codebases
  • Modern Type Hint Projects: Already specify optionality via Optional[] or defaults

This inconsistency creates several challenges:

  1. No Tool Support: Existing docstring validators don't enforce , optional usage patterns
  2. Maintenance Burden: Manually tracking which parameters need , optional is error-prone
  3. Refactoring Risk: Adding/removing defaults doesn't automatically update docstrings
  4. False Positives: Type checkers may report mismatches when , optional is present
  5. Unclear Requirements: Teams lack guidance on whether to use , optional suffix

Real-World Example:

Consider this function evolution during refactoring:

# Initial implementation
def create_report(data: pd.DataFrame, format: str) -> Report:
    """
    Create a report from data.
    
    Params:
        data (pd.DataFrame):
            The input data.
        format (str):
            Output format.
    """
    ...

# After refactoring - added optional parameter
def create_report(data: pd.DataFrame, format: str = "pdf") -> Report:
    """
    Create a report from data.
    
    Params:
        data (pd.DataFrame):
            The input data.
        format (str):
            Output format.  # <-- Should this be 'str, optional'?
    """
    ...

Questions Development Teams Face:

  • Should the docstring be updated to format (str, optional):?
  • If yes, who ensures consistency across the entire codebase?
  • If no, how do documentation readers know which parameters are optional?
  • What about existing docstrings with , optional on required parameters?

Type Mismatch Confusion

When , optional suffix appears in docstrings, it creates type annotation mismatches:

def example(x: int, y: int = 0) -> None:
    """
    Example function.
    
    Params:
        x (int):
            Required parameter.
        y (int, optional):  # <-- Type checker sees: "int, optional" ≠ "int"
            Optional parameter.
    """
    ...

DFC's parameter type validation (introduced in v1.6.0) would report:

Parameter type mismatch for 'y':
  - Signature: int
  - Docstring: int, optional

This is a "false positive" - the types match, but the , optional suffix causes validation to fail. Teams needed a way to handle this suffix appropriately based on their documentation standards.

Solution Architecture

Three Validation Modes

Implement three distinct validation modes to accommodate different project requirements and documentation philosophies:

Mode Behaviour Use Case
"silent" Strip , optional from docstring types before comparison Legacy codebases with inconsistent , optional usage
"validate" Error if , optional appears on required parameters Ensure , optional only used correctly when present
"strict" Require , optional for all parameters with defaults Enforce consistent , optional usage across entire codebase

Mode Comparison:

def example(x: int, y: int = 0) -> None:
    """
    Params:
        x (int, optional): Wrong - x is required
        y (int): Missing optional suffix
    """
    ...

# "silent" mode: No errors (strips all ', optional' suffixes)
# "validate" mode: Error - x has ', optional' but no default value
# "strict" mode: Two errors - x has ', optional' but no default, y missing ', optional'

Configuration Integration

Add new optional_style configuration field to GlobalConfig class:

Files Modified:

  • src/docstring_format_checker/config.py
  • src/docstring_format_checker/cli.py

Configuration Changes:

# In src/docstring_format_checker/config.py
@dataclass
class GlobalConfig:
    allow_undefined_sections: bool = False
    require_docstrings: bool = True
    check_private: bool = False
    validate_param_types: bool = True
    optional_style: Literal["silent", "validate", "strict"] = "validate"

Location: Lines 115-118 in src/docstring_format_checker/config.py

Configuration File Example:

# In pyproject.toml
[tool.dfc]
allow_undefined_sections = false
require_docstrings = true
check_private = true
validate_param_types = true
optional_style = "validate"  # Options: "silent", "validate", "strict"
sections = [...]

Configuration Validation

Add validation logic in _parse_global_config() function to ensure optional_style contains valid values:

# In src/docstring_format_checker/config.py
def _parse_global_config(tool_config: dict[str, Any]) -> GlobalConfig:
    # Validate optional_style if provided
    optional_style: str = tool_config.get("optional_style", "validate")
    valid_styles: tuple[str, str, str] = ("silent", "validate", "strict")
    if optional_style not in valid_styles:
        raise InvalidConfigError(
            f"Invalid optional_style: '{optional_style}'. Must be one of: {', '.join(valid_styles)}"
        )
    
    return GlobalConfig(
        allow_undefined_sections=tool_config.get("allow_undefined_sections", False),
        require_docstrings=tool_config.get("require_docstrings", True),
        check_private=tool_config.get("check_private", False),
        validate_param_types=tool_config.get("validate_param_types", True),
        optional_style=optional_style,  # type:ignore
    )

Location: Lines 452-464 in src/docstring_format_checker/config.py

Validation Benefits:

  • Fail fast with clear error message for invalid configuration values
  • Prevent runtime errors from configuration typos
  • Provide explicit list of valid options in error message
  • Maintain type safety with Literal type hint in dataclass

Implementation Details

Method 1: Parameter Default Detection

Implement _get_params_with_defaults() method to identify which parameters have default values:

# In src/docstring_format_checker/core.py
def _get_params_with_defaults(
    self, 
    node: Union[ast.FunctionDef, ast.AsyncFunctionDef]
) -> set[str]:
    """
    Get set of parameter names that have default val...
Read more