Automatic documentation from sources, for MkDocs.
—
Markdown extension and processors for parsing and rendering ::: identifier autodoc blocks within Markdown documents. The processing system integrates with Python-Markdown to provide seamless documentation extraction during Markdown conversion.
Primary Markdown extension that integrates mkdocstrings processing into the Markdown conversion pipeline.
class MkdocstringsExtension(Extension):
"""Main Markdown extension for mkdocstrings."""
def __init__(self, handlers: Handlers, autorefs: AutorefsPlugin, **kwargs: Any) -> None:
"""
Initialize the extension.
Args:
handlers: Handlers instance for processing
autorefs: AutorefsPlugin instance for cross-references
**kwargs: Additional extension arguments
"""
def extendMarkdown(self, md: Markdown) -> None:
"""
Register processors with Markdown instance.
Args:
md: Markdown instance to extend
"""Usage Example:
from markdown import Markdown
from mkdocstrings import MkdocstringsExtension, Handlers
# Create handlers
handlers = Handlers(
theme="material",
default="python",
inventory_project="my-project"
)
# Create extension
extension = MkdocstringsExtension(handlers=handlers, autorefs=None)
# Add to Markdown
md = Markdown(extensions=[extension])
# Process markdown with autodoc blocks
markdown_text = """
# My Documentation
::: my_module.MyClass
options:
show_source: false
::: my_module.my_function
"""
html_output = md.convert(markdown_text)Block processor that identifies and processes ::: identifier autodoc blocks in Markdown content.
class AutoDocProcessor(BlockProcessor):
"""Our 'autodoc' Markdown block processor."""
regex: re.Pattern = re.compile(r"^(?P<heading>#{1,6} *|)::: ?(?P<name>.+?) *$", flags=re.MULTILINE)
"""The regular expression to match our autodoc instructions."""
def __init__(self, md: Markdown, *, handlers: Handlers, autorefs: AutorefsPlugin) -> None:
"""
Initialize the object.
Args:
md: A markdown.Markdown instance
handlers: The handlers container
autorefs: The autorefs plugin instance
"""
def test(self, parent: Element, block: str) -> bool:
"""
Match our autodoc instructions.
Args:
parent: The parent element in the XML tree
block: The block to be tested
Returns:
Whether this block should be processed or not
"""
def run(self, parent: Element, blocks: MutableSequence[str]) -> None:
"""
Run code on the matched blocks.
Args:
parent: The parent element in the XML tree
blocks: The matched blocks
"""AutoDoc Block Format:
The processor recognizes blocks with this syntax:
::: identifier
options:
option1: value1
option2: value2
selection:
members:
- member1
- member2
rendering:
show_source: false
heading_level: 2Usage Examples:
Basic usage:
::: my_module.MyClassWith options:
::: my_module.MyClass
options:
show_source: false
docstring_style: googleWith member selection:
::: my_module
selection:
members:
- MyClass
- my_function
filters:
- "!^_" # Exclude private membersExtension for processing Markdown sub-documents within handlers, enabling nested Markdown processing.
class MkdocstringsInnerExtension(Extension):
"""Extension for Markdown sub-documents processed by handlers."""
def __init__(self, headings: list[Element]) -> None:
"""
Initialize with heading elements.
Args:
headings: List of heading elements to track
"""
def extendMarkdown(self, md: Markdown) -> None:
"""
Configure Markdown for inner processing.
Args:
md: Markdown instance to configure
"""Usage in Handlers:
def render(self, data: CollectorItem, options: HandlerOptions, *, locale: str | None = None) -> str:
# Create inner extension for nested Markdown
headings = []
inner_extension = MkdocstringsInnerExtension(headings)
# Process docstring Markdown
inner_md = Markdown(extensions=[inner_extension])
docstring_html = inner_md.convert(data.docstring)
# Use in template
return template.render(
data=data,
docstring_html=docstring_html,
headings=headings
)The AutoDoc processor uses regex patterns to identify autodoc blocks:
::: followed by an identifierWhen an autodoc block is found:
The processing system handles various error conditions:
try:
# Collect documentation data
data = handler.collect(identifier, options)
# Render to HTML
html = handler.render(data, options)
except CollectionError as e:
# Log collection failure and continue
logger.error(f"Collection failed for {identifier}: {e}")
html = f"<div class='error'>Failed to collect {identifier}</div>"
except Exception as e:
# Log unexpected errors
logger.exception(f"Unexpected error processing {identifier}")
html = f"<div class='error'>Error processing {identifier}</div>"Options can be specified at multiple levels:
# Global options in mkdocs.yml
plugins:
- mkdocstrings:
handlers:
python:
options:
show_source: false
docstring_style: google<!-- Local options override global -->
::: my_module.MyClass
options:
show_source: true # Overrides global settingControl which members are documented:
::: my_module
selection:
members:
- MyClass
- my_function
filters:
- "!^_" # Exclude private members
- "!^test_" # Exclude test functions
inherited_members: true
docstring_sections:
- attributes
- parameters
- returnsControl how documentation is rendered:
::: my_module.MyClass
rendering:
show_source: false
show_root_heading: true
show_root_toc_entry: false
heading_level: 2
show_category_heading: true
members_order: alphabeticalIntegration with autorefs for cross-referencing:
# In handler render method
def render(self, data: CollectorItem, options: HandlerOptions, *, locale: str | None = None) -> str:
# Register cross-references
if self.autorefs:
self.autorefs.register_anchor(data.name, data.url)
# Render with cross-reference support
return template.render(data=data, autorefs=self.autorefs)This enables automatic linking between documentation sections and external references.
Install with Tessl CLI
npx tessl i tessl/pypi-mkdocstrings