Advanced Usage
The following topics may be relevant when working on real-world documentation projects, which often demand a greater level of customization.
A TOC for every class
It is also possible to use autoclasstoc
in auto-generated API
documentation, i.e. where all of the classes in your project are documented
without you having to explicitly write an autoclass
directive for
each one. The way to do this is to use the sphinx.ext.autosummary
extension with a
custom Jinja template for classes, as detailed below:
Configure the
sphinx.ext.autosummary
extension to automatically generate stub files each time the documentation is built:autosummary_generate = True
Alternatively, you could generate stub files yourself by running the
autogen
command when necessary (after completing steps 2 and 3 below). I find this less convenient, but it might be better if you intend to edit the stub files by hand:$ sphinx-autogen -t _templates path/to/doc/with/autosummary.rst
Add an
autosummary
directive with the:toctree:
and:recursive:
options to your documentation. Anywhere will work, butindex.rst
is a common choice:.. autosummary:: :toctree: path/to/directory/for/autogenerated/files :recursive: mоdulе.tо.dосumеnt
Provide a custom Jinja template for formatting class stub files. The purpose of this template is to specify that
autoclasstoc
should be used for each class:{{ fullname | escape | underline}} .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} :members: :undoc-members: :special-members: :private-members: :inherited-members: :show-inheritance: .. autoclasstoc::
Note that the name of the
_templates
directory depends on the value of thetemplates_path
setting inconf.py
.
Custom sections
By default, autoclasstoc
divides the TOC into sections based whether
or not attributes are methods, and whether or not they are public. This is a
reasonable default, but for many projects it may make sense to add custom
sections specific to the idioms of that project. Fortunately, this is easy to
configure. The basic steps are:
Define new
autoclasstoc.Section
subclasses.Reference the subclasses either in
conf.py
or in the documentation itself.
This approach is very powerful, because the Section
class controls all
aspects of defining and formatting the TOC sections, and its subclasses can
overwrite any of that behavior. Below are some specific examples showing how
custom sections can be configured:
Based on name
Categorizing attributes based on their names is convenient, because it doesn’t
require making any changes or annotations to the code itself. For this
example, we’ll make a custom “Event Handlers” section that will consist of
methods that begin with the prefix “on_”, e.g. on_mouse_down()
or
on_key_up()
.
The first step is to define a new Section
subclass with the following
attributes:
key
: used to include or exclude the section from class TOCs.title
: how the section will be labeled in the documentation.predicate()
: which attributes to include in the section.
from autoclasstoc import Section, is_method
class EventHandlers(Section):
key = 'event-handlers'
title = "Event Handlers:"
def predicate(self, name, attr, meta):
return is_method(name, attr) and name.startswith('on_')
We also have to redefine the “Public Methods” section, so that it doesn’t include the event handlers (as it otherwise would):
from autoclasstoc import PublicMethods
class RemainingPublicMethods(PublicMethods):
exclude_section = EventHandlers
Finally, we need to specify that our new sections should be used by default (and what order they should go in):
autoclasstoc_sections = [
'event-handlers',
'public-methods',
'private-methods',
]
Based on pattern
Excluding attributes from a section based on their name is a common desire. To
make this easier, Section
classes have a
exclude_pattern
attribute that filters any
matching attributes out of the section. To demonstrate how this works,
we’ll make a custom “Public Methods” section that will consist of public
methods but excluding all “dunders” methods, e.g. __init__()
.
The first step is to define a new PublicSection
subclass with the following
attributes:
key
: used to include or exclude the section from class TOCs.exclude_pattern
: used for regex matching of the name for exclusion
from autoclasstoc import PublicSection, is_method
class PublicMethodsWithoutDunders(PublicSection):
key = 'public-methods-without-dunders'
exclude_pattern = '__'
autoclasstoc_sections = [
'public-methods-without-dunders',
'private-methods',
]
No more is necessary because the PublicSection
(and all other Section
subclasses) check for possible exclude_pattern
. Note here, that
exclude_pattern
can also be a list of strings.
This class we just created (PublicMethodsWithoutDunders
) is already within
autoclasstoc
. It can be used with the key
public-methods-without-dunders
in the autoclasstoc_sections
variable.
Based on decorator
A more explicit way to categorize methods is to use a decorator to label methods that belong to a particular section. This approach only is only applicable to methods and inner classes (because data attributes cannot be decorated), but is easy to implement. For this example, we’ll make a section for “Read Only” methods that are identified by a decorator:
The first step is to write a decorator to label read-only methods:
def read_only(f):
f.__readonly__ = True
return f
class MyClass:
@read_only
def do_nothing(self):
pass
Next, we have to define Section
subclasses that are aware of the decorator:
from autoclasstoc import Section
class ReadOnlySection(Section):
key = 'read-only'
title = "Read-Only Methods:"
def predicate(self, name, attr, meta):
return getattr(attr, '__readonly__', False)
class ReadWriteSection(Section):
key = 'read-write'
title = "Read/Write Methods:"
def predicate(self, name, attr, meta):
return not getattr(attr, '__readonly__', False)
autoclasstoc_sections = [
'read-only',
'read-write',
]
Note that this example removes the distinction between private and public methods, so both the “Read-Only” and “Read/Write” sections will contain public and private methods.
Based on :meta:
fields
With sphinx.ext.autodoc
, it’s possible to describe how an object should be
documented by including :meta:
fields in that object’s
docstring. autoclasstoc
automatically parses these fields and
provides them as an argument to predicate()
, so
they can be easily used to categorize attributes. As in the previous example,
we’ll make a custom section for read-only methods. The snippet below shows how
such a method might be identified using a meta field:
class MyClass:
def do_nothing(self):
"""
This method doesn't do anything.
:meta read-only:
"""
pass
These meta fields are parsed into a dictionary such that :meta key: value
would give {'key': 'value'}
. This dictionary is provided to the
predicate()
method via the meta argument:
from autoclasstoc import Section
class ReadOnlySection(Section):
key = 'read-only'
title = "Read-Only Methods:"
def predicate(self, name, attr, meta):
return 'read-only' in meta
class ReadWriteSection(Section):
key = 'read-write'
title = "Read/Write Methods:"
def predicate(self, name, attr, meta):
return 'read-only' not in meta
autoclasstoc_sections = [
'read-only',
'read-write',
]
Custom CSS
All of the HTML elements generated by autoclasstoc
are contained in
a <div>
with class autoclasstoc
. This can be used to select and style
the elements in the class TOC. Note that the plugin includes some default
rules to control the spacing around the <details>
elements that contain
TOCs for inherited attributes.