Sphinx extension to support docstrings in Numpy format
52
Evaluation — 52%
↑ 1.13xAgent success when using this tile
The numpydoc hooks module provides pre-commit integration for automated docstring validation. It enables project-wide enforcement of docstring quality standards through Git hooks and continuous integration workflows.
def run_hook(files, config=None, ignore=None):
"""
Main hook function for pre-commit validation.
Processes a list of Python files for docstring validation,
using AST parsing to extract and validate docstrings from
functions, classes, and methods.
Parameters
----------
files : list of str
List of file paths to validate
config : dict, optional
Configuration dictionary with validation settings
If None, attempts to load from project configuration files
ignore : set of str, optional
Set of validation error codes to ignore
Returns
-------
int
Exit code (0 for success, non-zero if validation errors found)
Examples
--------
>>> from numpydoc.hooks.validate_docstrings import run_hook
>>> exit_code = run_hook(['src/mymodule.py'])
>>> print(f"Validation result: {exit_code}")
"""def parse_config(dir_path=None):
"""
Parse validation config from pyproject.toml/setup.cfg.
Searches for numpydoc validation configuration in standard
Python project configuration files, with pyproject.toml
taking precedence over setup.cfg.
Parameters
----------
dir_path : str, optional
Directory to search for config files
If None, uses current working directory
Returns
-------
dict
Configuration dictionary with keys:
- 'checks': set of validation check codes to apply
- 'ignore': set of error codes to ignore
- 'exclude': set of file patterns to exclude
- 'override': dict mapping object patterns to rule overrides
Examples
--------
>>> config = parse_config()
>>> print(config['checks'])
{'all', 'GL08'}
>>> print(config['exclude'])
{'tests/.*', '.*/_private.py'}
"""def process_file(filepath: str, config: dict):
"""
Process single file for validation.
Uses AST parsing to extract docstrings from Python source
code and validates them according to the provided configuration.
Handles syntax errors gracefully and reports validation issues.
Parameters
----------
filepath : str
Path to Python file to process
config : dict
Configuration dictionary with validation settings
Returns
-------
list of tuple
List of (line_number, error_code, message) validation errors
Examples
--------
>>> config = {'checks': {'all'}, 'ignore': set()}
>>> errors = process_file('src/mymodule.py', config)
>>> for line, code, msg in errors:
... print(f"{line}: {code}: {msg}")
"""class AstValidator(validate.Validator):
"""
AST-based validator extending base Validator class.
Specialized validator that works with AST nodes to validate
docstrings extracted from Python source code. Handles the
relationship between AST nodes and their docstring content.
Parameters
----------
node : ast.AST
AST node (FunctionDef, ClassDef, etc.) to validate
obj_name : str
Qualified name of the object
**kwargs
Additional validation configuration options
Attributes
----------
node : ast.AST
The AST node being validated
obj_name : str
Qualified object name for error reporting
"""class DocstringVisitor(ast.NodeVisitor):
"""
AST visitor for extracting docstrings from Python source.
Traverses the AST to find function and class definitions,
extracts their docstrings, and applies validation rules.
Handles nested classes and methods properly.
Parameters
----------
config : dict
Validation configuration
filepath : str
Path to file being processed (for error reporting)
Attributes
----------
config : dict
Validation configuration dictionary
filepath : str
Current file path
errors : list
Accumulated validation errors
"""
def visit_FunctionDef(self, node):
"""
Visit function definition nodes.
Extracts and validates docstrings from function definitions,
including methods within classes.
Parameters
----------
node : ast.FunctionDef
Function definition AST node
"""
def visit_ClassDef(self, node):
"""
Visit class definition nodes.
Extracts and validates docstrings from class definitions
and recursively processes methods within the class.
Parameters
----------
node : ast.ClassDef
Class definition AST node
"""def find_project_root(srcs: List[str]) -> str:
"""
Find project root from config files.
Searches up the directory tree from the given source files
to find the project root, identified by configuration files
like pyproject.toml, setup.cfg, setup.py, or .git directory.
Parameters
----------
srcs : list of str
List of source file paths to start search from
Returns
-------
str
Path to project root directory
Examples
--------
>>> root = find_project_root(['src/mymodule.py'])
>>> print(root)
'/path/to/project'
"""Add numpydoc validation to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/numpy/numpydoc
rev: v1.9.0
hooks:
- id: numpydoc-validation
files: \.py$For local pre-commit hooks, use:
repos:
- repo: local
hooks:
- id: numpydoc-validation
name: numpydoc docstring validation
entry: python -m numpydoc.hooks.validate_docstrings
language: system
files: \.py$
pass_filenames: true[tool.numpydoc_validation]
checks = [
"all", # Enable all validation checks
"GL08", # Require docstrings
]
ignore = [
"GL01", # Allow docstring not starting immediately after quotes
"SS01", # Allow missing summary
]
exclude = [
"tests/.*", # Exclude test files
".*/_private.py", # Exclude private modules
"docs/conf.py", # Exclude Sphinx config
]
# Per-object validation overrides
[tool.numpydoc_validation.override]
"mypackage.legacy.*" = {all = false} # Disable all checks for legacy code
"mypackage.experimental.func" = {GL01 = false} # Disable specific check[numpydoc_validation]
checks = all,GL08
ignore = GL01,SS01
exclude =
tests/.*
.*/_private.py
docs/conf.py
# Override format: object_pattern:error_code=false
override =
mypackage.legacy.*:all=false
mypackage.experimental.func:GL01=false# Run validation hook on specific files
python -m numpydoc.hooks.validate_docstrings src/mymodule.py src/utils.py
# Run with configuration file
python -m numpydoc.hooks.validate_docstrings --config pyproject.toml src/*.py
# Run with specific validation checks
python -m numpydoc.hooks.validate_docstrings --checks GL01,SS01 src/# Install pre-commit hooks
pre-commit install
# Run hooks manually
pre-commit run numpydoc-validation
# Run on all files
pre-commit run numpydoc-validation --all-files
# Run with verbose output
pre-commit run numpydoc-validation --verbosefrom numpydoc.hooks.validate_docstrings import run_hook, parse_config
# Load project configuration
config = parse_config()
# Run validation on changed files
files = ['src/module1.py', 'src/module2.py']
exit_code = run_hook(files, config=config)
if exit_code == 0:
print("All docstrings valid!")
else:
print("Validation errors found")from numpydoc.hooks.validate_docstrings import run_hook
# Custom validation configuration
config = {
'checks': {'GL01', 'SS01', 'PR01'},
'ignore': {'GL08'},
'exclude': {'tests/.*'},
'override': {
'mymodule.legacy_func': {'all': False}
}
}
# Run with custom config
exit_code = run_hook(['src/mymodule.py'], config=config)import ast
from numpydoc.hooks.validate_docstrings import DocstringVisitor
# Parse Python source
with open('src/mymodule.py', 'r') as f:
source = f.read()
tree = ast.parse(source)
# Extract and validate docstrings
config = {'checks': {'all'}, 'ignore': set()}
visitor = DocstringVisitor(config, 'src/mymodule.py')
visitor.visit(tree)
# Print validation errors
for error in visitor.errors:
print(f"Line {error[0]}: {error[1]}: {error[2]}")# GitHub Actions workflow
name: Docstring Validation
on: [push, pull_request]
jobs:
validate-docstrings:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install numpydoc
- name: Validate docstrings
run: |
python -m numpydoc.hooks.validate_docstrings src/The hooks module provides comprehensive error handling:
Exit codes follow standard conventions:
Install with Tessl CLI
npx tessl i tessl/pypi-numpydocevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9