Docstring styles
Griffe parses your docstrings before this plugin renders anything. Your docstrings must use
one of the four conventions it knows: google (the default), numpy, sphinx, or auto.
You set the style per package, so one site can document packages written in different
styles.
starlightPydocs({ packages: [ { name: 'mypkg', search: ['../src'], docstringStyle: 'numpy' }, { name: 'legacy', search: ['../legacy'], docstringStyle: 'sphinx' }, { name: 'newpkg', search: ['../new'] }, ],});A package that sets no style gets google. auto is the fourth choice. With auto, Griffe
picks a parser for each docstring. Use auto when a package’s docstrings do not all follow
the same style.
If you name one of the other three, Griffe uses only that parser. Point the numpy parser
at a google docstring, and it reads Args: as ordinary prose. You get no parameter table
and no Returns block, but the build still succeeds. Griffe’s own warnings reach your build
log with a griffe: prefix, but not every mis-parse produces a warning.
The same docstring, three ways
Section titled “The same docstring, three ways”def resample(grid: Grid, factor: float = 2.0) -> Grid: """Scale a grid by a factor.
Args: grid: The grid to scale. factor: Multiplier applied to both dimensions.
Returns: A new, scaled grid.
Raises: ValueError: If `factor` is not positive. """Google style needs a recognised title, a colon, and an indented block. This is the
default style. The demopkg fixture behind this site’s
example pages uses it. A parameter needs no type in the
docstring: name: description is enough, because the annotation supplies the type.
def resample(grid: Grid, factor: float = 2.0) -> Grid: """Scale a grid by a factor.
Parameters ---------- grid : Grid The grid to scale. factor : float, optional Multiplier applied to both dimensions.
Returns ------- Grid A new, scaled grid.
Raises ------ ValueError If `factor` is not positive. """The underline makes a section. Leave one out, and Griffe reads the title above it as
prose. Types go on the parameter line itself, after a space-padded colon (name : type).
See it rendered: numpkg.
def resample(grid: Grid, factor: float = 2.0) -> Grid: """Scale a grid by a factor.
:param grid: The grid to scale. :param factor: Multiplier applied to both dimensions. :type factor: float :returns: A new, scaled grid. :raises ValueError: If `factor` is not positive. """Sphinx style uses reStructuredText field lists. Types come from a :type name: field, or
from the annotation when there is none. Your site’s Markdown processor renders the prose
inside a field. This package does not understand reStructuredText, so write
cross-references with the
mkdocstrings reference syntax instead of an
rST role such as :func:. See it rendered: sphpkg.
All three arrive as the same structured sections, so all three render the same way. The
summary renders as prose, then comes a parameter table, then typed Returns and Raises
blocks with the exception type linked.
Parser options
Section titled “Parser options”Griffe’s parsers take their own options. docstringOptions passes these through as griffe’s
-D flag:
6 collapsed lines
import starlight from '@astrojs/starlight';import { defineConfig } from 'astro/config';import starlightPydocs, { pydocsSidebarGroup } from 'starlight-pydocs';
export default defineConfig({ integrations: [ starlight({ title: 'My project', plugins: [ starlightPydocs({ packages: [ { name: 'mypkg', search: ['../src'], docstringStyle: 'google', docstringOptions: { warn_unknown_params: false, returns_named_value: false, },8 collapsed lines
}, ], }), ], sidebar: [{ label: 'API reference', items: [pydocsSidebarGroup] }], }), ],});The option names are Griffe’s own, and they differ per parser. See Griffe’s docstring parser options. Options are part of the extraction cache key, so changing one re-extracts the package.
Sections that render
Section titled “Sections that render”Whatever the style, Griffe produces the same structured sections. Each renders as its own block, in docstring order:
| Section | Rendered as |
|---|---|
| Prose | Markdown, through the site’s own processor |
| Parameters, other parameters, type parameters | A table of name, type, default and description, with linked types |
| Attributes | The same table without the default column |
| Returns, yields, receives | A list of typed values with their descriptions |
| Raises, warns | A list of exception types, each linked where it resolves |
| Examples | Prose and doctest blocks, in the order they were written |
Admonitions (Note:, Warning:, Tip: …) |
An aside, in one of four flavours matching Starlight’s own |
| Deprecations | A badge on the heading and a caution aside carrying the explanation |
| Functions, classes, modules, type aliases | A list of cross-referenced names, as numpy-style See Also blocks produce |
We ignore section kinds we do not model, rather than guess at them. This means a future Griffe release can add a new kind without breaking a page.
Parameter tables list only the parameters the docstring documents. A parameter you leave out of the docstring still appears in the signature above. Types come from the annotation when the docstring gives none. They link exactly like the types in the signature; see Cross-references.
Admonition flavours
Section titled “Admonition flavours”Griffe records an admonition’s annotation (note, warning, danger, seealso, hint, …).
Each annotation maps onto one of four asides styled to match Starlight’s: note, tip, caution
and danger. An annotation we do not recognise renders as a note, and keeps its own title.
Deprecated: blocks are the exception. The google parser routes them through the admonition
machinery. This plugin turns them into the deprecation notice instead of an aside, so the
badge and the explanation stay together.
Doctests and examples
Section titled “Doctests and examples”An Examples: section arrives as a sequence of prose and transcript pieces. Prose renders as
Markdown. A >>> transcript arrives unfenced. This plugin fences it as python before
rendering. The site’s own highlighter then highlights it: Expressive Code under Starlight,
plain Shiki in a bare Astro project.
This plugin uses python rather than mkdocstrings’ pycon. The Shiki bundles these
processors use ship no Python-console grammar, and python highlights a transcript
correctly. A block that is already fenced in the docstring is left exactly as written, so you
can pick your own language:
def summarise(rows): """Summarise a table.
Examples: The plain transcript form, fenced as `python` for you:
>>> summarise([{"n": 1}]) 'n=1'
Or fence it yourself, in any language:
```console $ python -m mypkg summarise rows.json n=1 ``` """The llms.txt rendition of the same content fences transcripts as pycon instead. That
output is read by machines, not highlighted by Shiki.
Prose rendering
Section titled “Prose rendering”Docstring Markdown goes through the Markdown processor your site has configured, not one this package brings along. Your site’s Markdown settings (the theme, the plugins Starlight registers, a mermaid plugin you added, GFM tables, smart quotes) apply to docstring prose too. This means an API page reads like the rest of the site.
Two consequences:
- Rendering happens once per build, at
astro:config:done, after every integration has finished configuring the pipeline. The HTML lands in a sidecar file beside the cached dump, so no markdown engine runs while pages render. - A docstring that cannot be rendered costs that one string. The build logs a warning. The object keeps its signature, parameters and links, and the page still exists.
This plugin supports both Sätteri (the Astro 7 default) and the unified pipeline from
@astrojs/markdown-remark, because neither is a dependency here. It calls whatever
markdown.processor resolves to. This documentation site runs the default. The
examples/vanilla site in the repository pins unified(). CI exercises both.