A Python docstring linter that checks arguments, returns, yields, and raises sections
—
AST-based analysis engine that traverses Python code to validate docstring compliance against function signatures, with support for all docstring styles and comprehensive validation rules.
The main AST visitor that performs comprehensive docstring analysis by traversing Python source code and validating docstring compliance.
class Visitor(ast.NodeVisitor):
"""
AST visitor for analyzing Python docstrings against function signatures.
Traverses Python AST nodes to validate docstring compliance with function
signatures, supporting numpy, google, and sphinx docstring styles with
comprehensive validation rules.
"""
def __init__(
self,
style: str = 'numpy',
argTypeHintsInSignature: bool = True,
argTypeHintsInDocstring: bool = True,
checkArgOrder: bool = True,
skipCheckingShortDocstrings: bool = True,
skipCheckingRaises: bool = False,
allowInitDocstring: bool = False,
checkReturnTypes: bool = True,
checkYieldTypes: bool = True,
ignoreUnderscoreArgs: bool = True,
ignorePrivateArgs: bool = False,
checkClassAttributes: bool = True,
shouldDocumentPrivateClassAttributes: bool = False,
treatPropertyMethodsAsClassAttributes: bool = False,
onlyAttrsWithClassVarAreTreatedAsClassAttrs: bool = False,
requireReturnSectionWhenReturningNothing: bool = False,
requireYieldSectionWhenYieldingNothing: bool = False,
shouldDocumentStarArguments: bool = True,
shouldDeclareAssertErrorIfAssertStatementExists: bool = False,
checkStyleMismatch: bool = False,
checkArgDefaults: bool = False,
) -> None:
"""
Initialize visitor with validation configuration.
Parameters:
- style: Docstring style to validate ('numpy', 'google', 'sphinx')
- argTypeHintsInSignature: Require type hints in function signatures
- argTypeHintsInDocstring: Require type hints in docstring arguments
- checkArgOrder: Validate argument order matches between signature and docstring
- skipCheckingShortDocstrings: Skip validation for summary-only docstrings
- skipCheckingRaises: Skip validation of raises sections against raise statements
- allowInitDocstring: Allow both __init__ and class to have docstrings
- checkReturnTypes: Validate return types match between signature and docstring
- checkYieldTypes: Validate yield types match between signature and docstring
- ignoreUnderscoreArgs: Ignore underscore arguments (_, __, etc.) in validation
- ignorePrivateArgs: Ignore private arguments (leading underscore) in validation
- checkClassAttributes: Validate class attributes against class docstring
- shouldDocumentPrivateClassAttributes: Require private class attributes in docstring
- treatPropertyMethodsAsClassAttributes: Treat @property methods as class attributes
- onlyAttrsWithClassVarAreTreatedAsClassAttrs: Only ClassVar annotations as class attrs
- requireReturnSectionWhenReturningNothing: Require return section for None returns
- requireYieldSectionWhenYieldingNothing: Require yields section for None yields
- shouldDocumentStarArguments: Require *args/**kwargs in docstrings
- shouldDeclareAssertErrorIfAssertStatementExists: Declare AssertionError for assert statements
- checkStyleMismatch: Validate consistent style within docstrings
- checkArgDefaults: Validate default values in docstring type hints match signature
"""
def visit(self, node: ast.AST) -> None:
"""
Visit AST node and perform docstring analysis.
Traverses the AST and analyzes function definitions, class definitions,
and method definitions for docstring compliance.
Parameters:
- node: AST node to visit and analyze
"""
@property
def violations(self) -> list[Violation]:
"""
Get list of violations found during analysis.
Returns:
list[Violation]: All violations detected during AST traversal
"""The visitor implements specific methods for different AST node types to perform targeted analysis.
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
"""
Visit function definition node.
Analyzes function docstrings against signatures, including:
- Argument validation
- Return type validation
- Yield type validation
- Raises section validation
- Type hint consistency
Parameters:
- node: Function definition AST node
"""
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
"""
Visit async function definition node.
Analyzes async function docstrings with same validation as regular functions,
with special handling for async-specific patterns.
Parameters:
- node: Async function definition AST node
"""
def visit_ClassDef(self, node: ast.ClassDef) -> None:
"""
Visit class definition node.
Analyzes class docstrings and class attributes, including:
- Class attribute validation against docstring
- __init__ method docstring validation
- Property method handling
- Private attribute documentation rules
Parameters:
- node: Class definition AST node
"""import ast
from pydoclint.visitor import Visitor
# Parse Python source code
source = '''
def example_function(x: int, y: str = "default") -> bool:
"""Example function.
Parameters
----------
x : int
First parameter
y : str
Second parameter
Returns
-------
bool
Whether operation succeeded
"""
return True
'''
tree = ast.parse(source)
visitor = Visitor(style="numpy")
visitor.visit(tree)
# Check for violations
for violation in visitor.violations:
print(f"Line {violation.line}: {violation.fullErrorCode} - {violation.msg}")# Strict validation with all checks enabled
visitor = Visitor(
style="google",
checkArgOrder=True,
checkReturnTypes=True,
checkYieldTypes=True,
checkClassAttributes=True,
shouldDocumentStarArguments=True,
checkStyleMismatch=True,
requireReturnSectionWhenReturningNothing=True
)
# Lenient validation for legacy code
visitor = Visitor(
style="numpy",
skipCheckingShortDocstrings=True,
skipCheckingRaises=True,
ignoreUnderscoreArgs=True,
ignorePrivateArgs=True,
allowInitDocstring=True
)source = '''
class ExampleClass:
"""Example class with attributes.
Attributes
----------
public_attr : str
Public class attribute
_private_attr : int
Private class attribute
"""
public_attr: str = "default"
_private_attr: int = 42
def __init__(self):
"""Initialize instance."""
pass
'''
tree = ast.parse(source)
visitor = Visitor(
style="numpy",
checkClassAttributes=True,
shouldDocumentPrivateClassAttributes=True
)
visitor.visit(tree)
# Will validate that documented attributes match actual class attributes# Google style validation
google_visitor = Visitor(style="google")
# Sphinx style validation
sphinx_visitor = Visitor(style="sphinx")
# Style mismatch detection
mismatch_visitor = Visitor(
style="numpy",
checkStyleMismatch=True # Will flag docstrings that don't match numpy style
)source = '''
async def async_generator(items: list[str]) -> AsyncGenerator[str, None]:
"""Process items asynchronously.
Parameters
----------
items : list[str]
Items to process
Yields
------
str
Processed item
"""
for item in items:
yield f"processed: {item}"
'''
tree = ast.parse(source)
visitor = Visitor(
style="numpy",
checkYieldTypes=True,
requireYieldSectionWhenYieldingNothing=False
)
visitor.visit(tree)
# Will validate yield type consistency and yields section requirementsInstall with Tessl CLI
npx tessl i tessl/pypi-pydoclint