Python API documentation generation¶
This theme includes an optional extension that generates Python API documentation pages.
A separate page is generated for each documented entity.
Top-level module-level entities are organized into groups, specified by the
:group:
field within the docstring. Thepython-apigen-group
directive is used to insert a summary of a group into an existing page.The summary of a group shows an abbreviated signature and an abbreviated description for each entity in the group; the name portion of the signature is a link to the separate page for that entity.
Class members are also organized into groups, also using the
:group:
field within their docstrings. Class members without a group are assigned to a default group based on their name. The summaries for each class member group are included on the page that documents the class.There is special support for pybind11-defined overloaded functions. Each overload is documented as a separate function; each overload is identified by the
:overload:
field specified within its docstring.
Usage¶
To use this extension, add "sphinx_immaterial.apidoc.python.apigen"
to
the list of extensions in conf.py
and define the
python_apigen_modules
configuration option.
For example:
extensions = [
# other extensions...
"sphinx_immaterial.apidoc.python.apigen",
]
python_apigen_modules = {
"my_module": "api",
}
This configuration is sufficient to generate a documentation page for every
top-level member of the specified modules. To generate a listing of those
top-level members and add the generated documentation pages to the global table
of contents, the python-apigen-group
directive may be used.
Tip
This extension works well with the toc_title_is_page_title
configuration option.
Groups¶
Each documented module member and class member is assigned to a member group. The group is either explicitly specified or determined automatically.
The group may be specified explicitly using the :group:
field within the
docstring:
def foo(x: int) -> int:
"""Does something or other.
:param x: The parameter.
:group: My group
When using the sphinx.ext.napoleon
extension, the group can also be
specified using the Group:
section:
def foo(x: int) -> int:
"""Does something or other.
Args:
x: The parameter.
Group:
My group
If the group is not specified explicitly, it is determined automatically based
on the python_apigen_default_groups
option.
Member order¶
For each each member there is also assigned an associated integer order
value that determines the order in which members are listed: members are listed
in ascending order by their associated order
value, and ties are broken
according to the python_apigen_order_tiebreaker
option.
Similarly to the group name, the order value may be specified explicitly using
the :order:
field within the docstring:
def foo(x: int) -> int:
"""Does something or other.
:param x: The parameter.
:group: My group
:order: 1
When using the sphinx.ext.napoleon
extension, the group can also be
specified using the Order:
section:
def foo(x: int) -> int:
"""Does something or other.
Args:
x: The parameter.
Group:
My group
Order:
1
If the order value is not specified explicitly, it is determined automatically
based on the python_apigen_default_order
option.
The order associated with a member determines both:
the relative order in which the member is listed within its associated group;
for class members, the order of the per-group sections for which an explicit section is not already listed in the class docstring (the order value associated with a group is the minimum of the order values of all of its members).
rST Directives¶
- .. python-apigen-group:: group-name¶
Generates a summary of all top-level members that are in the specified group, and also inserts a table-of-contents entry for each member at the current document position.
Before matching the specified group name to the group name of every top-level member, all the group names are normalized by converting each letter to lowercase and converting spaces to
-
.- :notoc:¶
By default, this directive also adds the pages corresponding to the members of the specified group to the global table of contents as children of the current page/section. Specifying this flag disables that behavior.
The group namespace for module-level members is global: if module
a
defines a memberfoo
in groupMy group
and moduleb
defines a memberbar
that is also inMy group
, then the following example would insert a summary of botha.foo
andb.bar
:.. python-apigen-group:: Some other group :notoc:
- class tensorstore_demo.VeryLongClassNameForTestingOutWordWrapping[source]
This is a class with a very long name.
- class tensorstore_demo.Foo[source]
This is a class defined in the
tensorstore_demo._tensorstore
module but should appear to be defined in thetensorstore_demo
module.
- class tensorstore_demo.FooSubclass(Foo)[source]
This is a subclass of
Foo
.
Note
This directive only includes top-level module members (for the modules specified by
python_apigen_modules
). Class members are also organized into groups, but these groups are per-class and are listed (along with their members) on the documentation page for the class.
- .. python-apigen-entity-summary:: entity-name¶
Generates a summary of a single Python entity.
The
entity-name
should be specified asmodule_name.ClassName.member
ormodule_name.ClassName.member(overload)
.- :notoc:¶
By default, this directive also adds the page corresponding to the specified Python entity to the global table of contents as a child of the current page/section. Specifying this flag disables that behavior.
.. python-apigen-entity-summary:: tensorstore_demo.IndexDomain.__init__(json) :notoc:
- tensorstore_demo.IndexDomain(*, json: Any)
Constructs an index domain from its JSON representation.
Sections defined within docstrings¶
When using this extension, docstrings can define sections, including nested
sections, using the usual reStructedText section syntax
. The
mapping between punctuation characters and heading levels is local to the
individual docstring. Therefore, it is not necessary (though still recommended)
to use a consistent order of punctuation characters across different docstrings.
In addition to providing a way to organize any explanatory content, for classes, sections can also correspond to member groups, as described below.
Class member groups¶
Within the documentation page for a given class, after its normal docstring content, a summary is added for each documented member, with a separate section per group.
For each group, if the class docstring defines a section with a title equal to the group name (or an id equal to the normalized group name), the member summaries are added to the end of the existing section. Otherwise, a new section for the group is added to the end of the class documentation.
New sections are added in the order of first ocurrence of the group within the order defined for the members.
For example, consider the following class definition:
class Foo:
"""This is some class.
Constructors
------------
This class defines the following constructors.
Operations
----------
This class supports the following operations.
"""
def __init__(self):
"""Constructs the class.
:group: Constructors
"""
def foo(self):
"""Performs the foo operation.
:group: Operations
"""
def bar(self):
"""Performs the bar operation.
:group: Operations
"""
def size(self) -> int:
"""Returns the size.
:group: Accessors
:order: 2
"""
def __setitem__(self, i: int, value: int) -> None:
"""Set the element at the given position.
:group: Indexing
:order: 3
"""
def __getitem__(self, i: int) -> int:
"""Returns the element at the given position.
:group: Indexing
:order: 1
"""
The __init__
method will be documented within the existing Constructors
section, the foo
and bar
methods will be documented within the existing
Operations
section. After the Operations
section, a new Indexing
section will be added that lists the __getitem__
and __setitem__
members, and then a new Accessors
section will be added that lists the
size
method.
Configuration¶
-
python_apigen_modules : dict[str, str] =
{}
¶ Maps module names to the output path prefix relative to the source directory.
All entities defined by the specified modules are documented.
For example, with the following added to
conf.py
:python_apigen_modules = { "my_module": "my_api/", "my_other_module": "other_api/my_other_module.", }
The following generated documents will be used (depending on the value of
python_apigen_case_insensitive_filesystem
):Python object
Overload
Document (case-sensitive)
Document (case-insensitive)
my_module.foo
my_api/foo
my_api/foo-2c26b46b
my_module.Foo
my_api/Foo
my_api/Foo-1cbec737
my_module.Foo.method
my_api/Foo.method
my_api/Foo.method-14e51ffc
my_module.Foo.__init__
json
my_api/Foo.__init__-json
my_api/Foo.__init__-json-3916c576
my_module.Foo.__init__
values
my_api/Foo.__init__-values
my_api/Foo.__init__-values-e6f37aec
my_module.Bar
my_api/Bar
my_api/Bar-95d64cac
my_other_module.Baz
other_api/my_other_module.Baz
other_api/my_other_module.Baz-e8f1251a
Note
The specified path prefix for each module is treated as a prefix, not a directory. It should normally end in either
"/"
or some other delimiter like"."
If you want the generated document name to include the module name, choose a prefix of the form"api_directory/module_name."
. If you want the generated document name to exclude the module name, choose a prefix of the form"api_directory/"
.Warning
Because Sphinx is not designed to process files outside the source tree, these files are actually written to the source tree, and are regenerated automatically at the start of the build. These files should not be checked into your source repository. (When using git, you may wish to add a suitable pattern to a
.gitignore
file.)The generated files start with a special comment to indicate that they were generated by this extension. Stale files from previous build invocations are deleted automatically. If there is an existing non-generated file with the same name as a to-be-generated file, the existing file will not be overwritten and the build will fail (showing an error message).
-
python_apigen_default_groups : list[tuple[str, str]] =
[('.*', 'Public members'), ('class:.*', 'Classes')]
¶ list
of(pattern, group)
pairs, wherepattern
is a regular expression matching strings of the form"<objtype>:<fully_qualified_member_name>"
(e.g."method:module_name.ClassName.member"
) andgroup
is the group name to assign.The group name for a given member is determined by the last matching pattern. If no pattern matches, the group is
Public members
.python_apigen_default_groups = [ ("class:.*", "Classes"), (r".*\.__(init|new)__", "Constructors"), (r".*\.__(str|repr)__", "String representation"), ]
-
python_apigen_default_order : list[tuple[str, int]] =
[]
¶ list
of(pattern, order)
pairs, wherepattern
is a regular expression matching strings of the form"<objtype>:<fully_qualified_member_name>"
(e.g."method:module_name.ClassName.member"
) andorder
is theint
order to assign.The order value for a given member is determined by the last matching pattern. If no pattern matches, the order value is 0.
python_apigen_default_order = [ ("class:.*", -10), (r".*\.__(init|new)__", -5), (r".*\.__(str|repr)__", 5), ]
-
python_apigen_order_tiebreaker : 'definition_order' | 'alphabetical' =
'definition_order'
¶ Specifies the relative order of members that have the same associated
order
value."definition_order"
Top-level members are sorted first by the order their containing module is listed in
python_apigen_modules
and then by the order in which they are defined.Class members are sorted by the order in which they are defined. Inherited members are listed after direct members, according to the method resolution order.
"alphabetical"
All members are sorted alphabetically, first using case-insensitive comparison and then breaking ties with case-sensitive comparison.
python_apigen_order_tiebreaker = "alphabetical"
-
python_apigen_case_insensitive_filesystem : None | bool =
None
¶ This extension results in an output file for each documented Python object based on its fully-qualified name. Python names are case-sensitive, meaning both
foo
andFoo
can be defined within the same scope, but some filesystems are case insensitive (e.g. on Windows and macOS), which creates the potential for a conflict.By default (if
python_apigen_case_insensitive_filesystem
isNone
), this extension detects automatically if the filesystem is case-insensitive, but detection is skipped if the option is set to an explicit value ofTrue
orFalse
:python_apigen_case_insensitive_filesystem = True
If the filesystem is either detected or specified to be case-insensitive, case conflicts are avoided by including a hash in the document name.
-
python_apigen_rst_prolog : str =
''
¶ A string of reStructuredText that will be included at the beginning of every docstring.
This may be used to set the rST directive default-role,
highlight
language, ordefault-literal-role
.Note
The prior default role, default literal role, and default highlight langauge are automatically restored after processing the
python_apigen_rst_epilog
. Therefore, it is not necessary to manually add anything topython_apigen_rst_epilog
to restore the prior roles or highlight language.rst_prolog = """ .. role python(code) :language: python :class: highlight """ python_apigen_rst_prolog = """ .. default-role:: py:obj .. default-literal-role:: python .. highlight:: python """
-
python_apigen_rst_epilog : str =
''
¶ A string of reStructuredText that will be included at the end of every docstring.
This option is supported for symmetry with
python_apigen_rst_prolog
, but in most cases is not needed because any changes to the default role, default literal role, and default highlight language due topython_apigen_rst_prolog
are undone automatically.
Subscript methods¶
Subscript methods are attributes defined on an object that support subscript syntax. For example:
arr.vindex[1, 2:5, [1, 2, 3]]
These subscript methods can be implemented as follows:
class MyArray:
class _Vindex:
def __init__(self, arr: MyArray):
self.arr = arr
def __getitem__(self, sel: Selection):
# Do something with `self.arr` and `sel`.
return result
@property
def vindex(self) -> MyArray._Vindex:
return MyArray._Vindex(self)
Based on the python_apigen_subscript_method_types
option, this
extension can recognize this pattern and display vindex
as:
vindex[sel: Selection]
rather than as a normal property.
-
python_apigen_subscript_method_types : re.Pattern =
'.*\\._[^.]*'
¶ Regular expression pattern that matches the return type annotations of properties that define subscript methods.
Return type annotations can be specified either as real annotations or in the textual signature specified as the first line of the docstring.
The default value matches any name beginning with an underscore, e.g.
_Vindex
in the example above.
-
python_apigen_show_base_classes : bool =
True
¶ Display the list of base classes when documenting classes.
Unlike the built-in
sphinx.ext.autodoc
module, base classes are shown using the normal Python syntax in a parenthesized list after the class name.The list of base classes displayed for each class can be customized by adding a listener to the
autodoc-process-bases
event. This is useful for excluding base classes that are not intended to be part of the public API.Note
The built-in
object
type is never included as a base class.