Extract Python API signatures and detect breaking changes for documentation generation.
—
Comprehensive docstring parsing system supporting multiple documentation formats. Griffe can parse and structure docstrings from Google, NumPy, and Sphinx styles, extracting parameters, return values, exceptions, examples, and other documentation elements into structured data.
Primary entry points for docstring parsing with format detection and specific parsers.
def parse(
text: str,
parser: Parser | str | None = None,
**options: Any,
) -> list[DocstringSection]:
"""
Parse a docstring using a specified parser.
Main entry point for docstring parsing. Can use automatic detection
or a specific parser format.
Args:
text: Raw docstring text to parse
parser: Parser to use ("auto", "google", "numpy", "sphinx") or Parser enum
**options: Parser-specific options passed to the parsing function
Returns:
list[DocstringSection]: Structured sections from the docstring
Examples:
Auto-detect format:
>>> sections = griffe.parse(docstring_text)
Use specific parser:
>>> sections = griffe.parse(docstring_text, parser="google")
With options:
>>> sections = griffe.parse(docstring_text, parser="numpy", style="numpy")
"""
def parse_auto(text: str, **options: Any) -> list[DocstringSection]:
"""
Parse a docstring by automatically detecting the style it uses.
Analyzes the docstring content to determine whether it uses Google,
NumPy, or Sphinx formatting conventions and parses accordingly.
Args:
text: Raw docstring text to parse
**options: Options passed to the detected parser
Returns:
list[DocstringSection]: Structured sections from the docstring
Examples:
>>> sections = griffe.parse_auto('''
... Brief description.
...
... Args:
... param1: Description of param1.
... param2: Description of param2.
...
... Returns:
... Description of return value.
... ''')
"""Dedicated parsers for each supported docstring format.
def parse_google(text: str, **options: Any) -> list[DocstringSection]:
"""
Parse a Google-style docstring into structured sections and elements.
Parses docstrings following Google's Python style guide conventions
with sections like Args, Returns, Raises, Examples, etc.
Args:
text: Google-style docstring text
**options: Google parser options including:
- style: Parsing style variations
- trim_doctest_flags: Remove doctest flags from examples
Returns:
list[DocstringSection]: Parsed sections
Examples:
>>> sections = griffe.parse_google('''
... Function description.
...
... Args:
... name (str): The person's name.
... age (int, optional): The person's age. Defaults to 0.
...
... Returns:
... str: A greeting message.
...
... Raises:
... ValueError: If name is empty.
... ''')
"""
def parse_numpy(text: str, **options: Any) -> list[DocstringSection]:
"""
Parse a NumPy/SciPy-style docstring into structured sections and elements.
Parses docstrings following NumPy documentation conventions with
sections separated by underlined headers.
Args:
text: NumPy-style docstring text
**options: NumPy parser options
Returns:
list[DocstringSection]: Parsed sections
Examples:
>>> sections = griffe.parse_numpy('''
... Brief function description.
...
... Parameters
... ----------
... name : str
... The person's name.
... age : int, optional
... The person's age (default is 0).
...
... Returns
... -------
... str
... A greeting message.
... ''')
"""
def parse_sphinx(text: str, **options: Any) -> list[DocstringSection]:
"""
Parse a Sphinx-style docstring into structured sections and elements.
Parses docstrings using Sphinx/reStructuredText field conventions
with :param:, :returns:, :raises: directives.
Args:
text: Sphinx-style docstring text
**options: Sphinx parser options
Returns:
list[DocstringSection]: Parsed sections
Examples:
>>> sections = griffe.parse_sphinx('''
... Brief function description.
...
... :param name: The person's name.
... :type name: str
... :param age: The person's age.
... :type age: int
... :returns: A greeting message.
... :rtype: str
... :raises ValueError: If name is empty.
... ''')
"""Functions for detecting and inferring docstring formats.
def infer_docstring_style(
text: str,
detection_method: DocstringDetectionMethod = DocstringDetectionMethod.HEURISTICS
) -> DocstringStyle | None:
"""
Infer the docstring style from content using heuristics.
Analyzes docstring text patterns to determine the most likely
documentation format being used.
Args:
text: Docstring text to analyze
detection_method: Method to use for detection
Returns:
DocstringStyle | None: Detected style or None if uncertain
Examples:
>>> style = griffe.infer_docstring_style('''
... Args:
... param1: Description
... Returns:
... Something
... ''')
>>> print(style) # DocstringStyle.GOOGLE
"""
# Available parsers mapping
parsers: dict[str, callable]
"""Dictionary mapping parser names to their parsing functions."""Foundation classes for docstring representation and parsing.
class DocstringSection:
"""
Base class for docstring sections (Parameters, Returns, etc.).
Represents a major section within a structured docstring such as
parameter lists, return descriptions, or example code.
"""
def __init__(self, kind: DocstringSectionKind, title: str | None = None) -> None:
"""
Initialize docstring section.
Args:
kind: Type of section (parameters, returns, etc.)
title: Optional custom title for the section
"""
@property
def kind(self) -> DocstringSectionKind:
"""The section type/kind."""
@property
def title(self) -> str | None:
"""Optional section title."""
class DocstringElement:
"""
Base class for individual elements within docstring sections.
Represents discrete pieces of information within sections, such as
individual parameters, return values, or exceptions.
"""
def __init__(self, description: str = "") -> None:
"""
Initialize docstring element.
Args:
description: Element description text
"""
@property
def description(self) -> str:
"""Element description text."""
class DocstringNamedElement(DocstringElement):
"""
Base class for named docstring elements (parameters, attributes, etc.).
Extends DocstringElement with name and type annotation support
for elements that have identifiers.
"""
def __init__(
self,
name: str,
description: str = "",
annotation: str | None = None,
) -> None:
"""
Initialize named element.
Args:
name: Element name/identifier
description: Element description
annotation: Type annotation string
"""
@property
def name(self) -> str:
"""Element name."""
@property
def annotation(self) -> str | None:
"""Type annotation string."""Concrete implementations for different kinds of docstring elements.
class DocstringParameter(DocstringNamedElement):
"""
Class representing parameter documentation in docstrings.
Used for function/method parameters with names, types, descriptions,
and default value information.
"""
def __init__(
self,
name: str,
description: str = "",
annotation: str | None = None,
default: str | None = None,
) -> None:
"""
Initialize parameter documentation.
Args:
name: Parameter name
description: Parameter description
annotation: Type annotation
default: Default value string
"""
@property
def default(self) -> str | None:
"""Default value string."""
class DocstringReturn(DocstringElement):
"""
Class representing return value documentation in docstrings.
Documents function return values with type and description information.
"""
def __init__(
self,
description: str = "",
annotation: str | None = None,
) -> None:
"""
Initialize return documentation.
Args:
description: Return value description
annotation: Return type annotation
"""
@property
def annotation(self) -> str | None:
"""Return type annotation."""
class DocstringRaise(DocstringNamedElement):
"""
Class representing exception/raise documentation in docstrings.
Documents exceptions that functions may raise with type and description.
"""
class DocstringYield(DocstringElement):
"""
Class representing yield documentation for generator functions.
Documents values yielded by generator functions.
"""
def __init__(
self,
description: str = "",
annotation: str | None = None,
) -> None:
"""
Initialize yield documentation.
Args:
description: Yield value description
annotation: Yield type annotation
"""
class DocstringAttribute(DocstringNamedElement):
"""
Class representing attribute documentation in docstrings.
Used for documenting class attributes, instance variables, and
module-level variables.
"""
class DocstringAdmonition(DocstringElement):
"""
Class representing admonition elements in docstrings.
Handles special notices like Note, Warning, See Also, etc.
"""
def __init__(
self,
kind: str,
description: str = "",
title: str | None = None,
) -> None:
"""
Initialize admonition.
Args:
kind: Admonition type (note, warning, etc.)
description: Admonition content
title: Optional custom title
"""
@property
def kind(self) -> str:
"""Admonition type."""
@property
def title(self) -> str | None:
"""Optional admonition title."""Concrete section implementations for different docstring areas.
class DocstringSectionParameters(DocstringSection):
"""Section containing function parameter documentation."""
def __init__(self, parameters: list[DocstringParameter]) -> None:
"""Initialize parameters section."""
@property
def parameters(self) -> list[DocstringParameter]:
"""List of documented parameters."""
class DocstringSectionReturns(DocstringSection):
"""Section containing return value documentation."""
def __init__(self, returns: list[DocstringReturn]) -> None:
"""Initialize returns section."""
@property
def returns(self) -> list[DocstringReturn]:
"""List of return value documentation."""
class DocstringSectionRaises(DocstringSection):
"""Section containing exception/raises documentation."""
def __init__(self, raises: list[DocstringRaise]) -> None:
"""Initialize raises section."""
@property
def raises(self) -> list[DocstringRaise]:
"""List of exception documentation."""
class DocstringSectionExamples(DocstringSection):
"""Section containing usage examples and code samples."""
def __init__(self, examples: list[tuple[str, str]]) -> None:
"""
Initialize examples section.
Args:
examples: List of (kind, text) tuples for examples
"""
@property
def examples(self) -> list[tuple[str, str]]:
"""List of examples as (kind, text) tuples."""
class DocstringSectionText(DocstringSection):
"""Section containing plain text content."""
def __init__(self, text: str) -> None:
"""Initialize text section."""
@property
def text(self) -> str:
"""Section text content."""from enum import Enum
class DocstringStyle(Enum):
"""Enumeration of supported docstring styles."""
AUTO = "auto"
GOOGLE = "google"
NUMPY = "numpy"
SPHINX = "sphinx"
class DocstringDetectionMethod(Enum):
"""Enumeration of methods for automatically detecting docstring styles."""
HEURISTICS = "heuristics"
class DocstringSectionKind(Enum):
"""Enumeration of docstring section kinds."""
TEXT = "text"
PARAMETERS = "parameters"
OTHER_PARAMETERS = "other_parameters"
RETURNS = "returns"
YIELDS = "yields"
RECEIVES = "receives"
RAISES = "raises"
WARNS = "warns"
EXAMPLES = "examples"
ATTRIBUTES = "attributes"
FUNCTIONS = "functions"
CLASSES = "classes"
MODULES = "modules"
DEPRECATED = "deprecated"
ADMONITION = "admonition"
class Parser(Enum):
"""Enumeration of available docstring parsers."""
AUTO = "auto"
GOOGLE = "google"
NUMPY = "numpy"
SPHINX = "sphinx"import griffe
# Parse with auto-detection
docstring_text = '''
Brief function description.
Args:
name (str): The person's name.
age (int, optional): The person's age. Defaults to 0.
Returns:
str: A greeting message.
Raises:
ValueError: If name is empty.
Example:
>>> greet("Alice", 25)
"Hello, Alice (age: 25)!"
'''
sections = griffe.parse_auto(docstring_text)
print(f"Found {len(sections)} sections:")
for section in sections:
print(f" - {section.kind.value}")import griffe
from griffe import DocstringSectionKind
# Parse a Google-style docstring
sections = griffe.parse_google(docstring_text)
# Find specific sections
for section in sections:
if section.kind == DocstringSectionKind.PARAMETERS:
print("Parameters:")
for param in section.parameters:
print(f" {param.name}: {param.annotation} - {param.description}")
if param.default:
print(f" Default: {param.default}")
elif section.kind == DocstringSectionKind.RETURNS:
print("Returns:")
for ret in section.returns:
print(f" {ret.annotation}: {ret.description}")
elif section.kind == DocstringSectionKind.RAISES:
print("Raises:")
for exc in section.raises:
print(f" {exc.name}: {exc.description}")
elif section.kind == DocstringSectionKind.EXAMPLES:
print("Examples:")
for kind, text in section.examples:
print(f" {kind}:")
print(f" {text}")import griffe
# Test different docstring styles
google_style = '''
Brief description.
Args:
param1: Description 1.
param2: Description 2.
Returns:
Something useful.
'''
numpy_style = '''
Brief description.
Parameters
----------
param1 : str
Description 1.
param2 : int
Description 2.
Returns
-------
bool
Something useful.
'''
sphinx_style = '''
Brief description.
:param param1: Description 1.
:type param1: str
:param param2: Description 2.
:type param2: int
:returns: Something useful.
:rtype: bool
'''
# Detect styles
styles = [
("Google", google_style),
("NumPy", numpy_style),
("Sphinx", sphinx_style)
]
for name, docstring in styles:
detected = griffe.infer_docstring_style(docstring)
print(f"{name} style detected as: {detected}")
# Parse with detected style
if detected:
sections = griffe.parse(docstring, parser=detected.value)
print(f" Parsed into {len(sections)} sections")import griffe
# Load a module and parse its docstrings
module = griffe.load("requests")
# Find a function and parse its docstring
if "get" in module.functions:
get_func = module.functions["get"]
if get_func.docstring:
sections = get_func.docstring.parse(parser="auto")
print(f"Function: {get_func.name}")
print(f"Docstring sections: {[s.kind.value for s in sections]}")
# Extract parameter documentation
for section in sections:
if section.kind == griffe.DocstringSectionKind.PARAMETERS:
print("Documented parameters:")
for param in section.parameters:
print(f" {param.name}: {param.description}")
# Parse all function docstrings in module
for func_name, func in module.functions.items():
if func.docstring:
try:
sections = func.docstring.parse()
param_count = sum(
len(s.parameters) for s in sections
if s.kind == griffe.DocstringSectionKind.PARAMETERS
)
print(f"{func_name}: {param_count} documented parameters")
except Exception as e:
print(f"{func_name}: Failed to parse docstring - {e}")import griffe
from griffe import DocstringSectionKind
class DocstringAnalyzer:
"""Analyze docstring completeness and quality."""
def analyze_function(self, func: griffe.Function) -> dict:
"""Analyze a function's docstring."""
result = {
"has_docstring": func.docstring is not None,
"has_description": False,
"documented_params": 0,
"undocumented_params": 0,
"has_return_doc": False,
"has_examples": False,
"issues": []
}
if not func.docstring:
result["issues"].append("Missing docstring")
return result
# Parse the docstring
try:
sections = func.docstring.parse()
except Exception as e:
result["issues"].append(f"Failed to parse docstring: {e}")
return result
# Check for description
text_sections = [s for s in sections if s.kind == DocstringSectionKind.TEXT]
if text_sections and text_sections[0].text.strip():
result["has_description"] = True
# Check parameter documentation
param_sections = [s for s in sections if s.kind == DocstringSectionKind.PARAMETERS]
documented_param_names = set()
if param_sections:
for section in param_sections:
for param in section.parameters:
documented_param_names.add(param.name)
# Compare with actual parameters
actual_param_names = {p.name for p in func.parameters if p.name not in ("self", "cls")}
result["documented_params"] = len(documented_param_names)
result["undocumented_params"] = len(actual_param_names - documented_param_names)
# Check for undocumented parameters
undocumented = actual_param_names - documented_param_names
if undocumented:
result["issues"].append(f"Undocumented parameters: {', '.join(undocumented)}")
# Check return documentation
return_sections = [s for s in sections if s.kind == DocstringSectionKind.RETURNS]
result["has_return_doc"] = bool(return_sections)
# Check for examples
example_sections = [s for s in sections if s.kind == DocstringSectionKind.EXAMPLES]
result["has_examples"] = bool(example_sections)
return result
# Use the analyzer
analyzer = DocstringAnalyzer()
module = griffe.load("mypackage")
for func_name, func in module.functions.items():
analysis = analyzer.analyze_function(func)
print(f"\n{func_name}:")
print(f" Description: {'✓' if analysis['has_description'] else '✗'}")
print(f" Parameters: {analysis['documented_params']}/{analysis['documented_params'] + analysis['undocumented_params']}")
print(f" Return doc: {'✓' if analysis['has_return_doc'] else '✗'}")
print(f" Examples: {'✓' if analysis['has_examples'] else '✗'}")
if analysis["issues"]:
print(f" Issues: {'; '.join(analysis['issues'])}")from enum import Enum
from typing import Any
# Docstring parsing types
class DocstringStyle(Enum): ...
class DocstringDetectionMethod(Enum): ...
class DocstringSectionKind(Enum): ...
class Parser(Enum): ...
# Section and element base classes
class DocstringSection: ...
class DocstringElement: ...
class DocstringNamedElement(DocstringElement): ...
# Parser functions mapping
parsers: dict[str, callable]Install with Tessl CLI
npx tessl i tessl/pypi-griffe