Skip to content

Usage¤

This is the documentation for the LEGACY Python handler

To read the documentation for the NEW handler, go to the new handler documentation.

The tool used by the legacy Python handler to collect documentation from Python source code is pytkdocs. It stands for (Python) Take Docs, and is supposed to be a pun on MkDocs (Make Docs?).

Like every handler, the legacy Python handler accepts both global and local options.

Global-only options¤

Some options are global only, and go directly under the handler's name.

  • import: this option is used to import Sphinx-compatible objects inventories from other documentation sites. For example, you can import the standard library objects inventory like this:

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            import:
            - https://docs.python-requests.org/en/master/objects.inv
    

    When importing an inventory, you enable automatic cross-references to other documentation sites like the standard library docs or any third-party package docs. Typically, you want to import the inventories of your project's dependencies, at least those that are used in the public API.

    Note

    This global option is common to all handlers, however they might implement it differently (or not even implement it).

  • paths: this option is used to provide filesystem paths in which to search for Python modules. Non-absolute paths are computed as relative to MkDocs configuration file. Example:

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            paths: [src]  # search packages in the src folder
    

    More details at Finding modules.

  • setup_commands: this option is used to instruct pytkdocs, the tool responsible for collecting data from sources, to run Python statements before starting to collect data. It is declared as a list of strings:

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            setup_commands:
            - import os
            - import django
            - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_app.settings")
            - django.setup()
    

    The setup commands are executed only once, when the pytkdocs background process is started.

Global/local options¤

The other options can be used both globally and locally, under the options key. For example, globally:

mkdocs.yml
plugins:
- mkdocstrings:
    handlers:
      python:
        options:
          do_something: true

...and locally, overriding the global configuration:

docs/some_page.md
::: package.module.class
    options:
      do_something: false

These options affect how the documentation is collected from sources and renderered: headings, members, docstrings, etc.

Headings options:

  • heading_level (int): The initial heading level to use. Default: 2.
  • show_root_heading (bool): Show the heading of the object at the root of the documentation tree (i.e. the object referenced by the identifier after :::). Default: False.
  • show_root_toc_entry (bool): If the root heading is not shown, at least add a ToC entry for it. Default: True.
  • show_root_full_path (bool): Show the full Python path for the root object heading. Default: True.
  • show_root_members_full_path (bool): Show the full Python path of the root members. Default: False.
  • show_object_full_path (bool): Show the full Python path of every object. Default: False.
  • show_category_heading (bool): When grouped by categories, show a heading for each category. Default: False.

Members options:

  • members (list[str] | False | None): An explicit list of members to render. Default: None.
  • members_order (str): The members ordering to use. Options: alphabetical - order by the members names, source - order members as they appear in the source file. Default: "alphabetical".
  • filters (list[str] | None): A list of filters applied to filter objects based on their name. A filter starting with ! will exclude matching objects instead of including them. The members option takes precedence over filters (filters will still be applied recursively to lower members in the hierarchy). Default: ["!^_[^_]"].
  • group_by_category (bool): Group the object's children by categories: attributes, classes, functions, and modules. Default: True.

Docstrings options:

  • docstring_style (str): The docstring style to use: google, numpy, restructured-text, or None. Default: "google".
  • docstring_options (dict): The options for the docstring parser. See parsers under pytkdocs.parsers.docstrings.
  • show_if_no_docstring (bool): Show the object heading even if it has no docstring or children with docstrings. Default: False.

Signatures/annotations options:

  • show_signature (bool): Show methods and functions signatures. Default: True.
  • show_signature_annotations (bool): Show the type annotations in methods and functions signatures. Default: False.

Additional options:

  • show_bases (bool): Show the base classes of a class. Default: True.
  • show_source (bool): Show the source code of this object. Default: True.

Supported docstrings styles¤

Right now, pytkdocs supports the Google-style, Numpy-style and reStructuredText-style docstring formats. The style used by default is the Google-style. You can configure what style you want to use with the docstring_style and docstring_options options, both globally or per autodoc instruction.

Google-style¤

You can see examples of Google-style docstrings in Napoleon's documentation.

Sections¤

Docstrings sections are parsed by pytkdocs and rendered by mkdocstrings. Supported sections are:

  • Arguments (or Args, Parameters, Params)
  • Attributes
  • Examples (or Example)
  • Raises (or Raise, Except, Exceptions)
  • Returns (or Return)

Admonitions¤

Additionally, any section that is not recognized will be transformed into its admonition equivalent. For example:

"""
Note: You can disable this behavior with the `replace_admonitions` option.
    To prevent `pytkdocs` from converting sections to admonitions,
    use the `replace_admonitions`:

    ```md
    ::: my_package.my_module
        options:
          docstring_style: google  # this is the default
          docstring_options:
            replace_admonitions: no 
    ```

    So meta!
"""
"""
!!! note "You can disable this behavior with the `replace_admonitions` option."
    To prevent `pytkdocs` from converting sections to admonitions,
    use the `replace_admonitions`:

    ```md
    ::: my_package.my_module
        options:
          docstring_style: google  # this is the default
          docstring_options:
            replace_admonitions: no 
    ```

    So meta!
"""

You can disable this behavior with the replace_admonitions parser option

To prevent pytkdocs from converting sections to admonitions, use the replace_admonitions parser option:

::: my_package.my_module
    options:
      docstring_style: google  # this is the default
      docstring_options:
        replace_admonitions: no 

So meta!

As shown in the above example, this can be disabled with the replace_admonitions option of the Google-style parser:

::: my_package.my_module
    options:
      docstring_style: google  # this is the default
      docstring_options:
        replace_admonitions: no 

Annotations¤

Type annotations are read both in the code and in the docstrings.

Example with a function

Expand the source at the end to see the original code!

A short description of this function.

Parameters:

Name Type Description Default
param1 int

An integer?

required
param2 Optional[str]

A string? If you have a long description, you can split it on multiple lines. Just remember to indent those lines consistently.

Complex markup is supported in sections items.

I'm a code block!
None
Source code in snippets/function_annotations_google.py
def my_function(param1: int, param2: Optional[str] = None) -> str:
    """A short description of this function.

    Arguments:
        param1: An integer?
        param2: A string? If you have a long description,
            you can split it on multiple lines.
            Just remember to indent those lines consistently.

            Complex markup is supported in sections items.

                I'm a code block!
    """
    return f"{param2}{param1}"

Numpy-style¤

Extra dependency required

You'll need an extra dependency to parse Numpy-style docstrings:

pdm add -d --group docs 'pytkdocs[numpy-style]'
poetry add -D 'pytkdocs[numpy-style]'
pip install 'pytkdocs[numpy-style]'
# etc.

Note

As Numpy-style is partially supported by the underlying parser, you may experience problems in the building process if your docstring has a Methods section in the class docstring (see #366).

You can see examples of Numpy-style docstrings in numpydoc's documentation.

reStructuredText-style¤

Partial support

Only RST-style is supported, not the whole RST markup specification.

You can see examples of reStructuredText-style docstrings in Sphinx's documentation.

Sections¤

Docstrings directives are parsed by pytkdocs and rendered by mkdocstrings. Supported directives are:

  • param (or parameter, arg, argument, key, keyword)
  • type
  • raises (or raise, except, exception)
  • var (or ivar, cvar)
  • vartype
  • returns (or return1)
  • rtype

Details about how to use each directive can be found in the Sphinx domain documentation

Annotations¤

Type annotations are read both in the code and in the docstrings.

Example with a function

Expand the source at the end to see the original code!

A short description of this function.

Complex markup is supported in the main description section.

I'm a code block!

Parameters:

Name Type Description Default
param1 int

An integer?

required
param2 Optional[str]

A string? If you have a long description, you can split it on multiple lines.

None
Source code in snippets/function_annotations_rst.py
def my_function(param1: int, param2: Optional[str] = None) -> str:
    """A short description of this function.

    Complex markup is supported in the main description section.

        I'm a code block!

    :param param1: An integer?
    :param param2: A string? If you have a long description,
        you can split it on multiple lines.
    """
    return f"{param2}{param1}"

Finding modules¤

There are multiple ways to tell the handler where to find your packages/modules.

The recommended method is to use the paths option, as it's the only one that works with the -f option of MkDocs, allowing to build the documentation from any location on the file system. Indeed, the paths provided with the paths option are computed as relative to the configuration file (mkdocs.yml), so that the current working directory has no impact on the build process: you can build the docs from any location on your filesystem.

Using the paths option¤

This is the recommended method

  1. mkdocs.yml in root, package in root

    📁 root/
    ├──  mkdocs.yml
    └── 📁 package/
    

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            paths: [.]  # actually not needed, default
    
  2. mkdocs.yml in root, package in subfolder

    📁 root/
    ├──  mkdocs.yml
    └── 📁 src/
        └── 📁 package/
    

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            paths: [src]
    
  3. mkdocs.yml in subfolder, package in root

    📁 root/
    ├── 📁 docs/
    │   └──  mkdocs.yml
    └── 📁 package/
    

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            paths: [..]
    
  4. mkdocs.yml in subfolder, package in subfolder

    📁 root/
    ├── 📁 docs/
    │   └──  mkdocs.yml
    └── 📁 src/
        └── 📁 package/
    

    mkdocs.yml
    plugins:
    - mkdocstrings:
        handlers:
          python:
            paths: [../src]
    

Except for case 1, which is supported by default, we strongly recommend to set the path to your packages using this option, even if it works without it (for example because your project manager automatically adds src to PYTHONPATH), to make sure anyone can build your docs from any location on their filesystem.

Behind the scenes, the handler will actually insert the specified paths in front of sys.path.

Using the PYTHONPATH environment variable¤

This method has limitations

This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the paths method instead.

You can take advantage of the usual Python loading mechanisms. In Bash and other shells, you can run your command like this (note the prepended PYTHONPATH=...):

  1. mkdocs.yml in root, package in root

    📁 root/
    ├──  mkdocs.yml
    └── 📁 package/
    

    PYTHONPATH=. mkdocs build  # actually not needed, default
    
  2. mkdocs.yml in root, package in subfolder

    📁 root/
    ├──  mkdocs.yml
    └── 📁 src/
        └── 📁 package/
    

    PYTHONPATH=src mkdocs build
    
  3. mkdocs.yml in subfolder, package in root

    📁 root/
    ├── 📁 docs/
    │   └──  mkdocs.yml
    └── 📁 package/
    

    PYTHONPATH=. mkdocs build -f docs/mkdocs.yml
    
  4. mkdocs.yml in subfolder, package in subfolder

    📁 root/
    ├── 📁 docs/
    │   └──  mkdocs.yml
    └── 📁 src/
        └── 📁 package/
    

    PYTHONPATH=src mkdocs build -f docs/mkdocs.yml
    

Installing your package in the current Python environment¤

This method has limitations

This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the paths method instead.

Install your package in the current environment, and run MkDocs:

. venv/bin/activate
pip install -e .
mkdocs build
pdm install
pdm run mkdocs build
poetry install
poetry run mkdocs build

Using the setup commands¤

This method has limitations

This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the paths method instead.

You can use the setup commands to modify sys.path:

mkdocs.yml
plugins:
- mkdocstrings:
    handlers:
      python:
        setup_commands:
        - import sys
        - sys.path.append("src")
        # or sys.path.insert(0, "src")

Mocking libraries¤

You may want to generate documentation for a package while its dependencies are not available. The Python handler provides itself no builtin way to mock libraries, but you can use the setup_commands to mock them manually:

mkdocs.yml
plugins:
- mkdocstrings:
    handlers:
      python:
        setup_commands:
        - import sys
        - from unittest.mock import MagicMock as mock
        - sys.modules["lib1"] = mock()
        - sys.modules["lib2"] = mock()
        - sys.modules["lib2.module1"] = mock()
        - sys.modules["lib2.module1.moduleB"] = mock()
        # etc

Here are some CSS rules for the Material for MkDocs theme:

/* Indentation. */
div.doc-contents:not(.first) {
  padding-left: 25px;
  border-left: .05rem solid var(--md-typeset-table-color);
}

Here are some CSS rules for the built-in ReadTheDocs theme:

/* Indentation. */
div.doc-contents:not(.first) {
  padding-left: 25px;
  border-left: 4px solid rgba(230, 230, 230);
}