Doc generators » Python docs

A mod­ern, mo­bile-friendly Sphinx-alike Py­thon doc­u­ment­a­tion gen­er­at­or with a first-class search func­tion­al­ity and an abil­ity to provide Py­thon stubs for IDE auto­com­ple­tion and type check­ing. Gen­er­ated by in­spect­ing Py­thon mod­ules and us­ing either em­bed­ded doc­strings or ex­tern­al reST files to pop­u­late the doc­u­ment­a­tion.

One of the design goals is provid­ing a sim­il­ar user ex­per­i­ence to the Doxy­gen doc­u­ment­a­tion theme.

Ba­sic us­age

The base is con­tained in a single Py­thon script and re­lated style/tem­plate files, for ad­vanced fea­tures such as math ren­der­ing it’ll make use of in­tern­als of some m.css plu­gins. Clone the m.css Git­Hub re­pos­it­ory and look in­to the documentation/ dir­ect­ory:

git clone https://github.com/mosra/m.css
cd m.css/documentation

The script re­quires Py­thon 3.6 and de­pends on Jin­ja2 for tem­plat­ing and doc­utils for reST markup ren­der­ing. You can in­stall the de­pend­en­cies via pip or your dis­tri­bu­tion pack­age man­ager, in most cases you’ll prob­ably have them already in­stalled:

# You may need sudo here
pip3 install docutils jinja2

Next, you need a con­fig­ur­a­tion file which tells the script what mod­ules to in­spect, how to name the pro­ject and where to put the out­put. In this ex­ample, we’ll gen­er­ate doc­u­ment­a­tion for the Py­thon built­in math mod­ule:

PROJECT_TITLE = "Python math"
INPUT_MODULES = ['math']

Now, run the script and pass path to the con­fig­ur­a­tion file to it:

./python.py path/to/conf.py

This will gen­er­ate an output/ dir­ect­ory next to the conf.py file and fill it with the gen­er­ated out­put. Open index.html to see the res­ult.

Fea­tures

  • Theme tailored from scratch for Py­thon-spe­cif­ic lan­guage fea­tures
  • Uses code in­spec­tion to query mod­ules, classes, data, func­tions and their sig­na­tures, does not rely on er­ror-prone source code pars­ing
  • Does not force the doc­u­ment­a­tion writer to ex­pli­citly list all sym­bols in or­der to have them doc­u­mented
  • Can use both in-code doc­strings and ex­tern­al reST files to de­scribe the APIs, giv­ing the user a con­trol over the code size vs doc­u­ment­a­tion verb­os­ity tradeoff
  • Opt-in spe­cial­ized be­ha­vi­or for un­der­stand­ing nat­ive bind­ings writ­ten with py­bind11 and Py­thon code us­ing at­trs
  • Abil­ity to gen­er­ate light­weight Py­thon stubs for IDE auto­com­ple­tion and type check­ing that ex­actly matches the doc­u­ment­a­tion, both for pure Py­thon and nat­ive bind­ings.

Con­fig­ur­a­tion

To­geth­er with the above PROJECT_TITLE and INPUT_MODULES vari­ables men­tioned above, the con­fig­ur­a­tion file sup­ports the fol­low­ing vari­ables. The op­tions are sim­il­ar to the Doxy­gen con­fig, but free of the Doxy­gen-spe­cif­ic nam­ing and con­straints.

Vari­able De­scrip­tion
PROJECT_TITLE: str Pro­ject title. Rendered in top navbar, page title and fine print. If not set, "My Python Project" is used.
PROJECT_SUBTITLE: str Pro­ject sub­title. If set, ap­pen­ded in a thin­ner font to PROJECT_TITLE.
PROJECT_LOGO: str URL of an im­age to use as a log in the top navbar. De­fault is none.
MAIN_PROJECT_URL: str If set and PROJECT_SUBTITLE is also set, then PROJECT_TITLE in the top navbar will link to this URL and PROJECT_SUBTITLE to the doc­u­ment­a­tion main page, sim­il­arly as shown here.
INPUT: str Base in­put dir­ect­ory. If not set, con­fig file base dir is used. Re­l­at­ive paths are re­l­at­ive to con­fig file base dir.
OUTPUT: Optional[str] Where to save the HTML out­put. Re­l­at­ive paths are re­l­at­ive to INPUT. If not set, output/ is used, if set to None, no HTML out­put is gen­er­ated.
OUTPUT_STUBS: Optional[str] Where to save gen­er­ated Py­thon stubs. See Stub gen­er­a­tion for more in­form­a­tion. Re­l­at­ive paths are re­l­at­ive to INPUT. If set to None, no stubs are gen­er­ated, de­fault is None.
INPUT_MODULES: List[Any] List of mod­ules to gen­er­ate the docs from. Val­ues can be either strings or mod­ule ob­jects. See Mod­ule in­spec­tion for more in­form­a­tion.
INPUT_PAGES: List[str] List of reST files for stan­dalone pages. See Pages for more in­form­a­tion.
THEME_COLOR: str Col­or for <meta name="theme-color" />, cor­res­pond­ing to the CSS style. If empty, no <meta> tag is rendered. See Theme se­lec­tion for more in­form­a­tion.
FAVICON: str Favicon URL, used to pop­u­late <link rel="icon" />. If empty, no <link> tag is rendered. Re­l­at­ive paths are searched re­l­at­ive to INPUT and to the python.py script dir as a fall­back. See Theme se­lec­tion for more in­form­a­tion.
STYLESHEETS: List[str] List of CSS files to in­clude. Re­l­at­ive paths are searched re­l­at­ive to INPUT and to the python.py script dir as a fall­back. See Theme se­lec­tion for more in­form­a­tion.
HTML_HEADER: str HTML code to put at the end of the <head> ele­ment. Use­ful for link­ing ar­bit­rary JavaS­cript code or, for ex­ample, adding <link> CSS stylesheets with ad­di­tion­al prop­er­ties and IDs that are oth­er­wise not pos­sible with just STYLESHEETS.
EXTRA_FILES: List[str] List of ex­tra files to copy (for ex­ample ad­di­tion­al CSS files that are @imported from the primary one). Re­l­at­ive paths are searched re­l­at­ive to INPUT and to the python.py script dir as a fall­back.
LINKS_NAVBAR1: List[Any] Left navbar column links. See Navbar links for more in­form­a­tion.
LINKS_NAVBAR2: List[Any] Right navbar column links. See Navbar links for more in­form­a­tion.
PAGE_HEADER: str reST markup to put at the top of every page. If not set, noth­ing is ad­ded any­where. The {url} place­hold­er is re­placed with cur­rent file URL.
FINE_PRINT: str reST markup to put in­to the foot­er. If not set, a de­fault gen­er­ic text is used. If empty, no foot­er is rendered at all.
FORMATTED_METADATA: List[str] Which metadata fields should be format­ted in doc­u­ment­a­tion pages. By de­fault only the summary field is.
PLUGINS: List[str] List of plu­gins to use. See Plu­gins for more in­form­a­tion.
PLUGIN_PATHS: List[str] Ad­di­tion­al plu­gin search paths. Re­l­at­ive paths are re­l­at­ive to INPUT.
CLASS_INDEX_EXPAND_LEVELS How many levels of the class in­dex tree to ex­pand. 0 means only the top-level sym­bols are shown. If not set, 1 is used.
CLASS_INDEX_EXPAND_INNER Wheth­er to ex­pand in­ner classes in the class in­dex. If not set, False is used.
NAME_MAPPING: Dict[str, str] Ad­di­tion­al name map­ping in ad­di­tion to what’s figured out from the __all__ mem­bers
PYBIND11_COMPATIBILITY: bool En­able some ad­di­tion­al tricks for bet­ter com­pat­ib­il­ity with py­bind11. If not set, False is used. See py­bind11 com­pat­ib­il­ity for more in­form­a­tion.
ATTRS_COMPATIBILITY: bool En­able some ad­di­tion­al tricks for bet­ter com­pat­ib­il­ity with at­trs. If not set, False is used. See at­trs com­pat­ib­il­ity for more in­form­a­tion.
SEARCH_DISABLED: bool Dis­able search func­tion­al­ity. If this op­tion is set, no search data is com­piled and the rendered HTML does not con­tain search-re­lated UI or sup­port. If not set, False is used.
SEARCH_DOWNLOAD_BINARY Down­load search data as a bin­ary to save band­width and ini­tial pro­cessing time. If not set, False is used. See Search op­tions for more in­form­a­tion.
SEARCH_FILENAME_PREFIX: str Search data fi­le­name pre­fix. Use­ful to pre­vent file con­flicts if both C++ and Py­thon doc­u­ment­a­tion shares the same dir­ect­ory. If not set, searchdata is used.
SEARCH_RESULT_ID_BYTES: int Search data pack­ing op­tion. A value of 2, 3 or 4 is al­lowed. If not set, 2 is used. See Search op­tions for more in­form­a­tion.
SEARCH_FILE_OFFSET_BYTES: int Search data pack­ing op­tion. A value of 3 or 4 is al­lowed. If not set, 3 is used. See Search op­tions for more in­form­a­tion.
SEARCH_NAME_SIZE_BYTES: int Search data pack­ing op­tion. A value of 1 or 2 is al­lowed. If not set, 1 is used. See Search op­tions for more in­form­a­tion.
SEARCH_HELP: str reST markup to dis­play as help text on empty search popup. If not set, a de­fault mes­sage is used. Has ef­fect only if SEARCH_DISABLED is not True.
SEARCH_BASE_URL: str Base URL for OpenSearch-based search en­gine sug­ges­tions for web browsers. See Search op­tions for more in­form­a­tion. Has ef­fect only if SEARCH_DISABLED is not True.
SEARCH_EXTERNAL_URL: str URL for ex­tern­al search. The {query} place­hold­er is re­placed with ur­len­coded search string. If not set, no ex­tern­al search is offered. See Search op­tions for more in­form­a­tion. Has ef­fect only if SEARCH_DISABLED is not True.
DOCUTILS_SETTINGS: Dict[Any] Ad­di­tion­al doc­utils set­tings. Key/value pairs as de­scribed in the docs.
URL_FORMATTER: Callable Func­tion for cre­at­ing fi­le­names and URLs for mod­ules, classes, pages and in­dex pages. See Cus­tom URL format­ters for more in­form­a­tion.
ID_FORMATTER: Callable Func­tion for cre­at­ing link an­chors for mod­ule and class mem­bers. See Cus­tom URL format­ters for more in­form­a­tion.
STUB_EXTENSION: str Ex­ten­sion to use for gen­er­ated Py­thon stub files. If not set, .pyi is used. See Stub gen­er­a­tion for more in­form­a­tion.
STUB_HEADER: str Com­ment block or ar­bit­rary oth­er code to put at the top gen­er­ated Py­thon stub files. If not set, a de­fault gen­er­ic text is used. If empty, no head­er is present in the files at all. See Stub gen­er­a­tion for more in­form­a­tion.

Theme se­lec­tion

By de­fault, the dark m.css theme to­geth­er with doc­u­ment­a­tion-theme-spe­cif­ic ad­di­tions is used, which cor­res­ponds to the fol­low­ing con­fig­ur­a­tion:

STYLESHEETS = [
    'https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600',
    '../css/m-dark+documentation.compiled.css']
THEME_COLOR = '#22272e'
FAVICON = 'favicon-dark.png'

If you have a site already us­ing the m-dark.compiled.css file, there’s an­oth­er file called m-dark.documentation.compiled.css, which con­tains just the doc­u­ment­a­tion-theme-spe­cif­ic ad­di­tions so you can re­use the already cached m-dark.compiled.css file from your main site:

STYLESHEETS = [
    'https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600',
    '../css/m-dark.compiled.css',
    '../css/m-dark.documentation.compiled.css']
THEME_COLOR = '#22272e'
FAVICON = 'favicon-dark.png'

If you prefer the light m.css theme in­stead, use the fol­low­ing con­fig­ur­a­tion (and, sim­il­arly, you can use m-light.compiled.css to­geth­er with m-light.documentation.compiled-css in place of m-light+documentation.compiled.css:

STYLESHEETS = [
    'https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700,700i%7CSource+Code+Pro:400,400i,600',
    '../css/m-light+documentation.compiled.css']
THEME_COLOR = '#cb4b16'
FAVICON = 'favicon-light.png'

See the CSS files sec­tion be­low for more in­form­a­tion about cus­tom­iz­ing the CSS files.

Search op­tions

Sym­bol search is im­ple­men­ted us­ing JavaS­cript Typed Ar­rays and does not need any serv­er-side func­tion­al­ity to per­form well — the cli­ent auto­mat­ic­ally down­loads a tightly packed bin­ary con­tain­ing search data and per­forms search dir­ectly on it.

How­ever, due to re­stric­tions of Chro­mi­um-based browsers, it’s not pos­sible to down­load data us­ing XMLHttpRequest when served from a loc­al file-sys­tem. Be­cause of that, the search de­faults to pro­du­cing a Base85-en­coded rep­res­ent­a­tion of the search bin­ary and load­ing that asyn­chron­ously as a plain JavaS­cript file. This res­ults in the search data be­ing 25% lar­ger, but since this is for serving from a loc­al filesys­tem, it’s not con­sidered a prob­lem. If your docs are ac­cessed through a serv­er (or you don’t need Chrome sup­port), set the SEARCH_DOWNLOAD_BINARY op­tion to True. The search data are by de­fault fetched from the cur­rent dir­ect­ory on the web­serv­er, if you want to sup­ply a dif­fer­ent loc­a­tion, set it to a string and provide a cus­tom URL format­ter.

The site can provide search en­gine metadata us­ing the OpenSearch spe­cific­a­tion. On sup­por­ted browsers this means you can add the search field to search en­gines and search dir­ectly from the ad­dress bar. To en­able search en­gine metadata, point SEARCH_BASE_URL to base URL of your doc­u­ment­a­tion, for ex­ample:

SEARCH_BASE_URL = 'https://doc.magnum.graphics/magnum/'

In gen­er­al, even without the above set­ting, ap­pend­ing ?q={query}#search to the URL will dir­ectly open the search popup with res­ults for {query}.

If SEARCH_EXTERNAL_URL is spe­cified, full-text search us­ing an ex­tern­al search en­gine is offered if noth­ing is found for giv­en string or if the user has JavaS­cript dis­abled. It’s re­com­men­ded to re­strict the search to a par­tic­u­lar do­main or add ad­di­tion­al keywords to the search query to fil­ter out ir­rel­ev­ant res­ults. Ex­ample, us­ing Google search en­gine and re­strict­ing the search to a sub­do­main:

SEARCH_EXTERNAL_URL = 'https://google.com/search?q=site:doc.magnum.graphics+{query}'

The search bin­ary is im­pli­citly made with the tight­est pack­ing pos­sible for smal­lest down­load sizes. On large pro­jects with tens of thou­sands of sym­bols it may how­ever hap­pen that the data won’t fit and doc gen­er­a­tion fails with an ex­cep­tion such as the fol­low­ing, sug­gest­ing you to in­crease the packed type sizes:

Over­flowEr­ror: Trie res­ult ID too large to store in 16 bits, set SEARCH_RES­ULT_ID_­BYTES = 3 in your conf.py.

The rel­ev­ant con­fig­ur­a­tion is SEARCH_RESULT_ID_BYTES, SEARCH_FILE_OFFSET_BYTES and SEARCH_NAME_SIZE_BYTES. Simply up­date your conf.py with sug­ges­ted val­ues and re­start the gen­er­at­or. Due to the way the search data get pro­cessed dur­ing seri­al­iz­a­tion it’s un­for­tu­nately not feas­ible to es­tim­ate the pack­ing sizes be­fore­hand.

Cus­tom URL format­ters

The URL_FORMATTER op­tion al­lows you to con­trol how all fi­le­names and gen­er­ated URLs look like. It takes an entry type and a “path” as a list of strings (so for ex­ample my.module.Class is rep­res­en­ted as ['my', 'module', 'Class']), re­turn­ing a tuple of a fi­le­name and an URL. Those can be the same, but also dif­fer­ent (for ex­ample a file get­ting saved in­to my/module/Class/index.html but the ac­tu­al URL be­ing https://docs.my.module/Class/). The de­fault im­ple­ment­a­tion looks like this, pro­du­cing both fi­le­names and URLs in the form of my.module.Class.html:

def default_url_formatter(type: EntryType, path: List[str]) -> Tuple[str, str]:
    if type == EntryType.STATIC:
        url = os.path.basename(path[0])

        # Encode version information into the search driver
        if url == 'search.js':
            url = 'search-v{}.js'.format(searchdata_format_version)

        return url, url

    url = '.'.join(path) + '.html'
    assert '/' not in url
    return url, url

The type is an enum, if you don’t want to fiddle with im­ports, com­pare type.name against a string, which is one of 'PAGE', 'MODULE', 'CLASS', 'SPECIAL' or 'STATIC'. The 'SPECIAL' is for in­dex pages and in that case the path has al­ways just one item, one of 'pages', 'modules' or 'classes'. The 'STATIC' is for stat­ic data such as im­ages or CSS files and the path is ab­so­lute in­put fi­le­name in­clud­ing the ex­ten­sion and ex­cept for search data (which are gen­er­ated on-the-fly) it al­ways ex­ists. If the stat­ic path is an URL, the URL format­ter is not called.

The ID_FORMATTER handles format­ting of an­chors on a page. Again it takes an entry type (which in this case is al­ways one of 'ENUM', 'ENUM_VALUE', 'FUNCTION', 'PROPERTY', 'DATA' or, in case of py­bind11 code, 'OVERLOADED_FUNCTION'. The second para­met­er is again a path, be­ing al­ways just one item ex­cept for 'ENUM_VALUE' (in which case it’s enum name and value name to­geth­er) and for 'OVERLOADED_FUNCTION', in which case it con­tains also a llist of ar­gu­ment types. The de­fault im­ple­ment­a­tion simply re­turns the the path con­cat­en­ated with dashes:

def default_id_formatter(type: EntryType, path: List[str]) -> str:
    return '-'.join(path)

Mod­ule in­spec­tion

By de­fault, if a mod­ule con­tains the __all__ at­trib­ute, all names lis­ted there are ex­posed in the doc­u­ment­a­tion. Oth­er­wise, all mod­ule (and class) mem­bers are ex­trac­ted us­ing inspect.getmembers(), skip­ping names imported from else­where and un­doc­u­mented un­der­scored names. Ad­di­tion­ally, class data mem­bers with type an­nota­tions (but with no val­ues) are pulled out from __annotations__, al­low­ing you to ex­pose (and doc­u­ment) also fields that might oth­er­wise only be pop­u­lated from __init__():

class MyClass:
    a_float: float
    string_value: str

De­tect­ing if a mod­ule is a sub­mod­ule of the cur­rent pack­age or if it’s imported from else­where is tricky, the script thus in­cludes only sub­mod­ules that have their __package__ prop­erty the same or one level be­low the par­ent pack­age. If a mod­ule’s __package__ is empty, it’s as­sumed to be a plain mod­ule (in­stead of a pack­age) and since those can’t have sub­mod­ules, all found sub­mod­ules in it are ig­nored.

Doc­u­ment­a­tion-only over­rides

While the in­spec­tion and auto­de­tec­tion fol­lows the struc­ture of the ori­gin­al code, it might not be al­ways de­sir­able to show it ex­actly that way in the docs. For­tu­nately, thanks to Py­thon’s dy­nam­ic nature, a lot can be done by mon­key-patch­ing dur­ing doc gen­er­a­tion.

In case the auto­de­tec­tion in­cludes more than you want or, con­versely, you need to in­clude names that would oth­er­wise be ex­cluded (such as un­der­scored names), you can tem­por­ar­ily over­ride the __all__ at­trib­ute when gen­er­at­ing the docs. For ex­ample, the fol­low­ing will list just the pow() and log() func­tions from the math mod­ule, ig­nor­ing the rest:

import math
math.__all__ = ['pow', 'log']

INPUT_MODULES = [math]

In oth­er cases, es­pe­cially when nat­ive mod­ules are in­volved, the in­spec­ted name loc­a­tions might not be what you want. By put­ting the names in­to __all__ you tell the script it should map the in­spec­ted loc­a­tion to the one provided. Note you should also hide the ori­gin­al loc­a­tion from the script to avoid du­plic­ate defin­i­tions (un­less it’s un­der­scored, in which case it’ll get ig­nored auto­mat­ic­ally).

# module math

from _native_math import fast_sin as sin
from _native_math import fast_cos as cos
__all__ = ['sin', 'cos']

Ad­di­tion­ally, for map­ping types of ex­tern­al lib­rar­ies where the auto­de­tec­tion from __all__ can’t be per­formed, you can use the NAME_MAPPING op­tion:

NAME_MAPPING = {
    'fastmath._native.Vector3': 'fastmath.Vector3',
    'fastmath._native.Quaternion': 'fastmath.Quaternion',
    # or, equivalently, if the mapping is the same for all members:
    'fastmath._native': 'fastmath'
}

Doc­strings

By de­fault, the first para­graph of a mod­ule-level, class-level and func­tion-level doc­string is used as a doc sum­mary, copied as-is to the out­put without format­ting it in any way. What fol­lows is put (again without format­ting) para­graph-by-para­graph in­to de­tailed docs.

"""Module summary

First paragraph of module detailed docs."""

class Foo:
    """Class summary"""

    def bar(self):
        """Function summary"""

Us­ing just doc­strings, how­ever, comes with a few lim­it­a­tions:

  • Class and mod­ule-level vari­ables can’t have a doc­string at­tached due to how Py­thon works
  • Be­cause not every Py­thon API can be doc­u­mented us­ing doc­strings, the out­put con­tains everything, in­clud­ing un­doc­u­mented names
  • In­stance vari­ables ad­ded in­side __init__() are not ex­trac­ted, as this would re­quire pars­ing Py­thon code dir­ectly (which is what Sphinx has to do to sup­port these). You can work around this by adding an­not­ated “de­clar­a­tions” to the class as shown above, how­ever no doc­strings can be spe­cified for those either.

To over­come the lim­it­a­tions, ex­tern­ally-sup­plied doc­u­ment­a­tion provides means to doc­u­ment names that can’t have a doc­string at­tached, and to­geth­er with the m.sphinx plu­gin ex­pand­ing format­ting cap­ab­il­it­ies bey­ond plain text.

Func­tion and vari­able an­nota­tions

The script uses inspect.signature() to query func­tion para­met­er / re­turn type an­nota­tions to­geth­er with de­fault val­ues and dis­plays them in the out­put. Sim­il­ar is for mod­ule and class vari­ables, ex­trac­ted from the __annotations__ prop­erty. If a vari­able type im­ple­ments __repr__(), a repr() of it is prin­ted as the value, oth­er­wise the value is omit­ted.

from typing import Tuple, List

def foo(a: str, be_nice: bool = True) -> Tuple[int, str]:
    pass

SETTINGS: List[Tuple[str, bool]] = []

For bet­ter read­ab­il­ity, if the func­tion sig­na­ture con­tains type an­nota­tions or a de­fault value, the ar­gu­ments are prin­ted each on one line. Oth­er­wise, to avoid wast­ing ver­tic­al space, the ar­gu­ments are lis­ted on a single line.

Sim­il­arly to how the built­in help() in Py­thon 3.7 star­ted an­not­at­ing bound­ar­ies between po­s­i­tion-only, po­s­i­tion-or-keyword and keyword-only ar­gu­ments with / and *, the same is done here — it’s es­pe­cially help­ful for nat­ive func­tions, where you can for ex­ample call math.sin(0.3) but not math.sin(x=0.3), be­cause the x ar­gu­ment is po­s­i­tion­al-only. Cur­rently, po­s­i­tion­al-only ar­gu­ments are pos­sible only with nat­ive func­tions, PEP570 adds them for pure Py­thon func­tions as well.

In some cases, es­pe­cially when doc­u­ment­ing nat­ive func­tions, the sig­na­ture can’t be ex­trac­ted and the func­tion sig­na­ture shows just an el­lip­sis () in­stead of the ac­tu­al ar­gu­ment list.

Class meth­ods, stat­ic meth­ods, dun­der meth­ods, prop­er­ties

Meth­ods dec­or­ated with @classmethod are put in­to a “Class meth­ods” sec­tion, @staticmethods in­to a “Stat­ic meth­ods” sec­tion. Double-un­der­scored meth­ods ex­pli­citly im­ple­men­ted in the class are put in­to a “Spe­cial meth­ods” sec­tion, oth­er­wise they’re ig­nored — by de­fault, Py­thon adds a large col­lec­tion of dun­der meth­ods to each class and the only way to know if the meth­od is user-provided or im­pli­cit is by check­ing the doc­string.

class MyClass:
    @classmethod
    def a_classmethod(cls):
        """A class method"""

    @staticmethod
    def a_staticmethod():
        """A static method"""

    def __init__(self, foo, bar):
        """A constructor"""

Prop­er­ties ad­ded to classes either us­ing the @property dec­or­at­or or cre­ated with the property() built­in are ad­ded to the “Prop­er­ties” sec­tion. Each prop­erty is an­not­ated with get set del if it has a get­ter, a set­ter and a deleter or with get and oth­er vari­ants if it has just some. The doc­string and type an­nota­tion is ex­trac­ted from the prop­erty get­ter.

from typing import Tuple

class MyClass:
    @property
    def a_read_write_property(self) -> Tuple[int, int]:
        """A read-write tuple property"""

    @a_read_write_property.setter
    def a_read_write_property(self, a):
        # Docstring and type annotation taken from the getter, no need to
        # have it repeated here too
        pass

Doc­u­ment­ing enum val­ues

Py­thon sup­plies an im­pli­cit doc­strings for enums de­rived from enum.Enum and enum val­ues im­pli­citly in­her­it the doc­string of the enum class. If either is de­tec­ted to be the case, doc­string of the enum or the value is ig­nored. While it’s pos­sible to doc­u­ment enum classes the usu­al way, there’s a non-ob­vi­ous way to doc­u­ment enum val­ues as well.

import enum

class MyEnum(enum.Enum):
    """My enum"""

    ZERO = 0
    TWO = 3
    CONSISTENCY = -73

MyEnum.ZERO.__doc__ = "Zero value"
MyEnum.TWO.__doc__ = "Three, but named TWO for compatibility"

The doc­u­ment­a­tion out­put for enums in­cludes enum value val­ues and the class it was de­rived from, so it’s pos­sible to know wheth­er it’s an enum or a flag.

In­clud­ing un­der­scored names in the out­put

By de­fault, names start­ing with an un­der­score (ex­cept for __dunder__ meth­ods) are treated as private and not lis­ted in the out­put. One way to ex­pose them is to list them in __all__, how­ever that works for mod­ule con­tent only. For ex­pos­ing gen­er­al un­der­scored names, you either need to provide a doc­string or ex­tern­al doc­u­ment­a­tion con­tent (and in case of plain data, ex­tern­al doc­u­ment­a­tion con­tent is the only op­tion).

Note that at the point where mod­ules and classes are crawled for mem­bers, doc­strings are not parsed yet — so e.g. a data doc­u­ment­a­tion via a :data: op­tion of the .. py:class:: m.sphinx dir­ect­ive won’t be vis­ible to the ini­tial crawl and thus the data will stay hid­den.

Some­times, how­ever, you’ll want the in­verse — keep­ing an un­der­scored name hid­den, even though it has a doc­string. Solu­tion is to re­move the doc­string while gen­er­at­ing the docs, dir­ectly in the conf.py file dur­ing mod­ule im­port:

import mymodule
mymodule._private_thing.__doc__ = None

INPUT_MODULES = [mymodule]

Pages

In ad­di­tion to doc­u­ment­a­tion gen­er­ated by in­spect­ing par­tic­u­lar mod­ule, it’s pos­sible to add ded­ic­ated doc­u­ment­a­tion pages. Con­tent is writ­ten in reST (see Writ­ing reST con­tent for a short in­tro­duc­tion) and taken from files spe­cified in INPUT_PAGES. Fi­le­names are in­ter­preted re­l­at­ive to con­fig­ur­a­tion file path, out­put fi­le­name is in­put base­name with ex­ten­sion re­placed to .html. In par­tic­u­lar, con­tent of a index.rst file is used for the doc­u­ment­a­tion main page. Ex­ample:

INPUT_PAGES = ['pages/index.rst']
My Python library
=================

:summary: Welcome on the main page!

This is a documentation of the mypythonlib module. You can use it like
this:

.. code:: py

    import mypythonlib
    mypythonlib.foo()

Apart from :summary:, the page can have any num­ber of metadata, with all of them ex­posed as prop­er­ties of page in the out­put tem­plates. Fields lis­ted in FORMATTED_METADATA (the :summary: is among them) are ex­pec­ted to be format­ted as reST and ex­posed as HTML, oth­er­wise as a plain text.

All ref­er­enced im­ages are ex­pec­ted to have either an ab­so­lute URL or be re­l­at­ive to INPUT, the ones with re­l­at­ive paths are then copied dir­ectly to OUTPUT with the lead­ing dirs stripped from the path.

Plu­gins

The reST con­tent is not lim­ited to just the built­in func­tion­al­ity and it’s pos­sible to ex­tend it via plu­gins either from m.css it­self or 3rd party ones. See doc­u­ment­a­tion of each plu­gin to see its us­age; the m.htmls­an­ity plu­gin is used un­con­di­tion­ally while all oth­ers are op­tion­al. For ex­ample, en­abling the com­mon m.css plu­gins might look like this:

PLUGINS = ['m.code', 'm.components', 'm.dox']

Ex­tern­al doc­u­ment­a­tion con­tent

Be­cause it’s of­ten not feas­ible to have the whole doc­u­ment­a­tion stored in Py­thon doc­strings, the gen­er­at­or al­lows you to sup­ply doc­u­ment­a­tion from ex­tern­al files. Sim­il­arly to pages, the INPUT_DOCS set­ting is a list of reST files that con­tain doc­u­ment­a­tion for par­tic­u­lar names us­ing cus­tom dir­ect­ives. A set of cus­tom dir­ect­ives is provided by the m.sphinx plu­gin — see its doc­u­ment­a­tion for de­tailed de­scrip­tion of all fea­tures. Be­low is a simple ex­ample of us­ing it to doc­u­ment a class:

PLUGINS = ['m.sphinx']
INPUT_DOCS = ['docs.rst']
.. py:class:: mymodule.sub.Class
    :summary: A pretty class

    This class is *pretty*.

py­bind11 com­pat­ib­il­ity

C++ bind­ings gen­er­ated us­ing py­bind11 do not have all in­form­a­tion ac­cess­ible through in­tro­spec­tion and thus the script has to do a few py­bind11-spe­cif­ic work­arounds to gen­er­ate ex­pec­ted out­put. This be­ha­vi­or is not en­abled by de­fault as it might have un­wanted con­sequences in pure Py­thon code, en­able it us­ing the PYBIND11_COMPATIBILITY op­tion.

Func­tion sig­na­tures, prop­erty an­nota­tions

For reas­ons ex­plained in py­bind/py­bind11#990, py­bind11 is not able to provide func­tion sig­na­tures through in­tro­spec­tion and thus the script falls back to pars­ing ar­gu­ment names, type an­nota­tions and de­fault val­ues from the doc­string in­stead. By de­fault, un­less py::arg() is used, func­tion ar­gu­ments are po­s­i­tion­al-only (shown as arg0, arg1, …) and marked as such in the out­put.

Sim­il­arly, prop­erty types are ex­trac­ted from get­ter doc­strings.

Un­like Py­thon, py­bind11 has a built­in sup­port for over­loaded func­tions — de­pend­ing on types passed to a func­tion, it dis­patches to a par­tic­u­lar C++ over­load. The over­loads are ex­pan­ded in the out­put as well, mean­ing you can see one func­tion men­tioned more than once with dif­fer­ent sig­na­tures.

Be­cause stat­ic meth­ods in py­bind11 are not dec­or­ated with @staticmethod, they are de­tec­ted based on pres­ence of self as the first para­met­er — if it’s there, it’s an in­stance meth­od, oth­er­wise it’s a stat­ic meth­od.

Enums

Enums in py­bind11 are not de­rived from enum.Enum, but rather are plain classes. The only re­li­able way to de­tect a py­bind11 enum is by look­ing for a __members__ mem­ber, which is a dict provid­ing string names and their cor­res­pond­ing val­ues. With py­bind 2.2, it’s only pos­sible to doc­u­ment the enum class it­self, not the val­ues.

at­trs com­pat­ib­il­ity

If a code­base is us­ing the at­trs pack­age and the ATTRS_COMPATIBILITY op­tion is en­abled, the script is able to ex­tract the (oth­er­wise in­ac­cess­ible by nor­mal means) in­form­a­tion about at­trib­utes defined us­ing attr.ib() or via the @attr.s(auto_attribs=True) dec­or­at­or. Note that at­trib­utes of classes us­ing @attr.s(slots=True) are vis­ible even without the com­pat­ib­il­ity en­abled.

In all cases, there’s no pos­sib­il­ity of adding in-source doc­strings for any of these and you need to sup­ply the doc­u­ment­a­tion with the .. py:property:: dir­ect­ive as de­scribed in Ex­tern­al doc­u­ment­a­tion con­tent.

Ad­di­tion­ally, vari­ous dun­der meth­ods that say just “Auto­mat­ic­ally cre­ated by at­trs.” in their doc­string are im­pli­citly hid­den from the out­put if this op­tion is en­abled. In or­der to show them again, over­ride the doc­string to some­thing mean­ing­ful.

Stub gen­er­a­tion

By de­fault, the tool pro­duces just a HTML doc­u­ment­a­tion. In many cases, and es­pe­cially when nat­ive bind­ings are in­volved, it’s use­ful to provide so-called stubs for the IDE in or­der for it to provide use­ful auto­com­ple­tion and per­form type check­ing. An­oth­er use case is when the amount of code in the ac­tu­al im­ple­ment­a­tion is too large for the IDE to handle.

Stubs can be op­ted in by spe­cify­ing a path where to gen­er­ate them in OUTPUT_STUBS. They can be gen­er­ated either to­geth­er with the HTML out­put, or alone, if OUTPUT is set to None in­stead. A com­mon setup in that case is to cre­ate a second file, named conf-stubs.py, that in­her­its everything from conf.py but en­ables only the stub out­put:

# Inherit everything from conf.py
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
from conf import *

OUTPUT = None
OUTPUT_STUBS = 'stubs/'

Now, when you run the script, the out­put dir­ect­ory will con­tain *.pyi files that you can sup­ply to your IDE.

./python.py path/to/conf-stubs.py

Com­mand-line op­tions

./python.py [-h] [--templates TEMPLATES] [--debug] conf

Ar­gu­ments:

  • conf — con­fig­ur­a­tion file

Op­tions:

  • -h, --help — show this help mes­sage and exit
  • --templates TEMPLATES — tem­plate dir­ect­ory. De­faults to the templates/python/ sub­dir­ect­ory if not set.
  • --debug — verb­ose log­ging out­put. Use­ful for de­bug­ging.

Im­ple­ment­ing cus­tom plu­gins

Third-party plu­gins can be loaded from paths spe­cified in PLUGIN_PATHS. Cus­tom plu­gins need to im­ple­ment a re­gis­tra­tion func­tion named register_mcss(). It gets passed the fol­low­ing named ar­gu­ments and the plu­gin might or might not use them.

Keyword ar­gu­ment Con­tent
mcss_settings Dict con­tain­ing all m.css set­tings
jinja_environment Jin­ja2 en­vir­on­ment. Use­ful for adding new fil­ters etc.
module_doc_contents Mod­ule doc­u­ment­a­tion con­tents
class_doc_contents Class doc­u­ment­a­tion con­tents
enum_doc_contents Enum doc­u­ment­a­tion con­tents
enum_value_doc_contents Enum doc­u­ment­a­tion con­tents
function_doc_contents Func­tion doc­u­ment­a­tion con­tents
property_doc_contents Prop­erty doc­u­ment­a­tion con­tents
data_doc_contents Data doc­u­ment­a­tion con­tents
hooks_post_crawl Hooks to call after the ini­tial name crawl
hooks_pre_scope Hooks to call on scope enter
hooks_post_scope Hooks to call on scope exit
hooks_docstring Hooks to call when pars­ing a doc­string
hooks_pre_page Hooks to call be­fore each page gets rendered
hooks_post_run Hooks to call at the very end of the script run

The module_doc_contents, class_doc_contents, enum_doc_contents, enum_value_doc_contents, function_doc_contents, property_doc_contents and data_doc_contents vari­ables are Dict[str, Dict[str, str]], where the first level is a name and second level are key/value pairs of the ac­tu­al HTML doc­u­ment­a­tion con­tent. Plu­gins that parse ex­tra doc­u­ment­a­tion in­puts (such as m.sphinx) are sup­posed to add to the dict, which is then used to fill the ac­tu­al doc­u­ment­a­tion con­tents. The fol­low­ing cor­res­ponds to the doc­u­ment­a­tion source shown in the Ex­tern­al doc­u­ment­a­tion con­tent sec­tion be­low. Note that the dict can already have ex­ist­ing entries ad­ded from else­where, so it’s im­port­ant to avoid fully over­writ­ing it:

docs = class_doc_contents.setdefault('mymodule.sub.Class', {})
docs['summary'] = "A pretty class"
docs['details'] = "This class is *pretty*."

The hooks_post_crawl, hooks_docstring, hooks_pre_page and hooks_post_run vari­ables are lists of func­tions. Plu­gins that need to do some­thing at spe­cif­ic points of the ex­e­cu­tion are sup­posed to add func­tions to the list.

The hooks_post_crawl is called once gath­er­ing of all names is done. It gets passed the fol­low­ing ar­gu­ments:

Keyword ar­gu­ment Con­tent
name_map

Map with all gathered mod­ule, class, enum, func­tion, prop­erty, data and page metadata. Plu­gins are al­lowed to read from it (for ex­ample to seri­al­ize them to a file for search­ing or link­ing from oth­er pro­jects) as well as write to it (for ex­ample to al­low link­ing to names from ex­tern­al pro­jects). Key is a name, value has at the fol­low­ing prop­er­ties:

Prop­erty De­scrip­tion
type Entry type. Same as the enum passed to cus­tom URL format­ters.
object Ob­ject which the entry doc­u­ments. This prop­erty be­ing None means this entry is ex­tern­al 1; if not present at all there’s filename in­stead.
filename File this entry doc­u­ments. Present only for EntryType.PAGE or EntryType.SPECIAL.
path Path. Equi­val­ent to key.split('.').
url URL to the entry doc­u­ment­a­tion, format­ted with cus­tom URL format­ters.
css_classes List of CSS classes to add to the <a> tag. In­tern­al entries usu­ally have ['m-doc'] while ex­tern­al have ['m-doc-external'].
1.
^ As this dis­tin­guishes between in­tern­al and ex­tern­al entries, new entries ad­ded by the plu­gin need to have object set to None so the script as well as oth­er plu­gins can cor­rectly dis­tin­guish them.

The hooks_pre_scope and hooks_post_scope get called be­fore en­ter­ing and after leav­ing a name scope (page, mod­ule, class, enum, enum value, func­tion, prop­erty or data), and are meant mainly to aid with con­text-sens­it­ive link­ing. Those scopes can be nes­ted and can be called suc­cess­ively for the same scope — for ex­ample, when ren­der­ing mod­ule docs, hooks_pre_scope gets called first for the mod­ule scope, but then an­oth­er hooks_pre_scope gets called when ren­der­ing a sum­mary for ref­er­ence to an in­ner class. Then, hooks_post_scope gets called in re­verse or­der. The plu­gins are ex­pec­ted to im­ple­ment a stack-like data struc­ture for main­tain­ing in­form­a­tion about cur­rent scope. Both of those func­tions get passed the fol­low­ing ar­gu­ments:

Keyword ar­gu­ment Con­tent
type Type of the scope that’s be­ing entered or ex­ited. Same as the enum passed to cus­tom URL format­ters.
path Path of the mod­ule / class / func­tion / enum / enum value / data scope that’s be­ing entered or ex­ited. A list of names, '.'.join(path) is equi­val­ent to the fully qual­i­fied name.
param_names In case of func­tions, list of para­met­er names. This ar­gu­ment is not present oth­er­wise.

Hooks lis­ted in hooks_docstring are called when doc­strings are parsed, and al­ways pre­ceded by a cor­res­pond­ing hooks_pre_scope call. The first lis­ted hook gets the raw doc­string only pro­cessed by inspect.cleandoc() and each fol­low­ing gets the out­put of the pre­vi­ous. When a hook re­turns an empty string, hooks later in the list are not called. String re­turned by the last hook is pro­cessed, if any, the same way as if no hooks would be present — it gets par­ti­tioned in­to sum­mary and con­tent and those put to the out­put as-is, each para­graph wrapped in <p> tags. The hooks are free to do any­thing with the doc­string — ex­tract­ing metadata from it and re­turn­ing it as-is, transpil­ing it from one markup lan­guage to an­oth­er, or fully con­sum­ing it, pop­u­lat­ing the *_doc_contents vari­ables men­tioned above and re­turn­ing noth­ing back. Each hook gets passed the fol­low­ing ar­gu­ments:

Keyword ar­gu­ment Con­tent
type Name type. Same as the enum passed to cus­tom URL format­ters.
path Path of the mod­ule / class / func­tion / enum / enum value / data con­tain­ing the doc­string. A list of names, '.'.join(path) is equi­val­ent to the fully qual­i­fied name.
signature Sig­na­ture of a func­tion, for dis­tin­guish­ing between par­tic­u­lar over­loads. In a form of (param1: type1, param2: type2).
doc Doc­string con­tent. Al­ways non-empty — once a hook re­turns noth­ing back, no fur­ther hooks are called.

The hooks_pre_page is called be­fore each page of out­put gets rendered. Can be used for ex­ample for re­set­ting some in­tern­al counter for page-wide unique ele­ment IDs. The hooks_post_run is called after the whole run is done, use­ful for ex­ample to seri­al­ize cached in­tern­al state. Cur­rently, those two func­tions get no ar­gu­ments passed.

Re­gis­tra­tion func­tion for a plu­gin that needs to query the OUTPUT set­ting might look like this — the re­main­ing keyword ar­gu­ments will col­lapse in­to the **kwargs para­met­er. See code of vari­ous m.css plu­gins for ac­tu­al ex­amples. The be­low ex­ample shows re­gis­tra­tion of a hy­po­thet­ic HTML val­id­at­or plu­gin — it saves the out­put path from set­tings and re­gisters a post-run hook that val­id­ates everything in giv­en out­put dir­ect­ory.

output_dir = None



def _validate_output():
    validate_all_html_files(output_dir)

def register_mcss(mcss_settings, hooks_post_run, **kwargs):
    global output_dir
    output_dir = mcss_settings['OUTPUT']
    hooks_post_run += [_validate_output]

Cus­tom­iz­ing the tem­plate

The rest of the doc­u­ment­a­tion ex­plains how to cus­tom­ize the built­in tem­plate to bet­ter suit your needs. Each doc­u­ment­a­tion file is gen­er­ated from one of the tem­plate files that are bundled with the script. How­ever, it’s pos­sible to provide your own Jin­ja2 tem­plate files for cus­tom­ized ex­per­i­ence as well as modi­fy the CSS styl­ing.

CSS files

By de­fault, com­piled CSS files are used to re­duce amount of HT­TP re­quests and band­width needed for view­ing the doc­u­ment­a­tion. How­ever, for easi­er cus­tom­iz­a­tion and de­bug­ging it’s bet­ter to use the un­pro­cessed stylesheets. The STYLESHEETS op­tion lists all files that go to the <link rel="stylesheet" /> in the res­ult­ing HTML markup, while EXTRA_FILES list the in­dir­ectly ref­er­enced files that need to be copied to the out­put as well. Be­low is an ex­ample con­fig­ur­a­tion cor­res­pond­ing to the dark theme:

STYLESHEETS = [
    'https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600',
    '../css/m-dark.css',
    '../css/m-documentation.css']
EXTRA_FILES = [
    '../css/m-grid.css',
    '../css/m-components.css',
    '../css/pygments-dark.css',
    '../css/pygments-console.css']
THEME_COLOR = '#22272e'

After mak­ing de­sired changes to the source files, it’s pos­sible to post­pro­cess them back to the com­piled ver­sion us­ing the postprocess.py util­ity as ex­plained in the CSS themes doc­u­ment­a­tion. In case of the dark theme, the m-dark+documentation.compiled.css and m-dark.documentation.compiled.css files are pro­duced like this:

cd css
./postprocess.py m-dark.css m-documentation.css -o m-dark+documentation.compiled.css
./postprocess.py m-dark.css m-documentation.css --no-import -o m-dark.documentation.compiled.css

Out­put tem­plates

Each out­put file is rendered with one of these tem­plates:

Fi­le­name Use
module.html Mod­ule doc­u­ment­a­tion
class.html Class doc­u­ment­a­tion
page.html Ex­pli­cit doc­u­ment­a­tion pages, in­clud­ing the main page

Each tem­plate gets passed all con­fig­ur­a­tion val­ues from the Con­fig­ur­a­tion table as-is, to­geth­er with a URL vari­able with URL of giv­en out­put file. In ad­di­tion to built­in Jin­ja2 fil­ters, the format_url fil­ter re­turns either a path format­ted ac­cord­ing to cus­tom URL format­ters, if the path is re­l­at­ive; or a full URL, if the ar­gu­ment is an ab­so­lute URL. It’s use­ful in cases like this:

{% for css in HTML_EXTRA_STYLESHEET %}
<link rel="stylesheet" href="{{ css|format_url|e }}" />
{% endfor %}

The ac­tu­al page con­tents are provided in a page ob­ject, which has the fol­low­ing prop­er­ties. All ex­posed data are meant to be passed dir­ectly to the HTML markup without any ad­di­tion­al es­cap­ing.

Prop­erty De­scrip­tion
page.summary Doc sum­mary
page.filename File name 4
page.url File URL 4
page.breadcrumb List of (title, URL) tuples for bread­crumb nav­ig­a­tion.
page.content De­tailed doc­u­ment­a­tion, if any

Each mod­ule page, rendered with module.html, has the fol­low­ing ad­di­tion­al prop­er­ties:

Prop­erty De­scrip­tion
page.prefix_wbr Fully-qual­i­fied sym­bol pre­fix for giv­en com­pound with trail­ing . with <wbr/> tag after every ..
page.dependencies List of (prefix, module) tuples with mod­ule de­pend­en­cies. To match re­l­at­ive type names, it’s either import module if prefix is empty, from prefix import * if module is empty or from prefix import module if both are non-empty.
page.modules List of in­ner mod­ules. See Mod­ule prop­er­ties for de­tails.
page.classes List of classes. See Class prop­er­ties for de­tails.
page.enums List of enums. See Enum prop­er­ties for de­tails.
page.functions List of mod­ule-level func­tions. See Func­tion prop­er­ties for de­tails.
page.data List of mod­ule-level data. See Data prop­er­ties for de­tails.
page.has_enum_details If there is at least one enum with full de­scrip­tion block 3
page.has_function_details If there is at least one func­tion (or meth­od, in case of classes) with full de­scrip­tion block 3
page.has_data_details If there is at least one data with full de­scrip­tion block 3

Each class page, rendered with class.html, has the fol­low­ing ad­di­tion­al prop­er­ties:

Prop­erty De­scrip­tion
page.classmethods List of class meth­ods (an­not­ated with @classmethod). See Func­tion prop­er­ties for de­tails.
page.staticmethods List of stat­ic meth­ods (an­not­ated with @staticmethod). See Func­tion prop­er­ties for de­tails.
page.methods List of meth­ods. See Func­tion prop­er­ties for de­tails.
page.dunder_methods List of double-un­der­scored spe­cial func­tions. See Func­tion prop­er­ties for de­tails.
page.properties List of prop­er­ties. See Prop­erty prop­er­ties for de­tails.
page.has_property_details If there is at least one prop­erty with full de­scrip­tion block 3
page.has_members If the class con­tains at least one mem­ber or is com­pletely empty

Ex­pli­cit doc­u­ment­a­tion pages rendered with class.html have ad­di­tion­al prop­er­ties taken from in­put metadata. If giv­en metadata is lis­ted in FORMATTED_METADATA, it’s rendered in­to HTML, oth­er­wise it’s ex­posed as plain text.

Mod­ule prop­er­ties

Prop­erty De­scrip­tion
module.url URL of de­tailed mod­ule doc­u­ment­a­tion
module.name Mod­ule name
module.summary Doc sum­mary

Class prop­er­ties

Prop­erty De­scrip­tion
class_.url URL of de­tailed class doc­u­ment­a­tion
class_.name Class name
class_.summary Doc sum­mary

Enum prop­er­ties

Prop­erty De­scrip­tion
enum.name Enum name
enum.id Enum ID 5
enum.summary Doc sum­mary
enum.content De­tailed doc­u­ment­a­tion, if any
enum.base Fully qual­i­fied name of a base class from which the enum is de­rived. Set to None if no base class in­form­a­tion is avail­able.
enum.base_relative Like enum.base, but re­l­at­ive, i.e. with a com­mon pre­fix of the base class and con­tain­ing mod­ule / class omit­ted
enum.base_link Like enum.base_relative, but with cross-linked types
enum.values List of enum val­ues
enum.has_details If there is enough con­tent for the full de­scrip­tion block. 3
enum.has_value_details If the enum val­ues have de­scrip­tion. Im­pies enum.has_details.

Every item of enum.values has the fol­low­ing prop­er­ties:

Prop­erty De­scrip­tion
value.name Value name
value.id Value ID 5
value.value Value value. Set to None if no value is avail­able.
value.content Value doc­u­ment­a­tion, if any

Func­tion prop­er­ties

Prop­erty De­scrip­tion
function.name Func­tion name
function.id Func­tion ID 5
function.summary Doc sum­mary
function.content De­tailed doc­u­ment­a­tion, if any
function.type Fully qual­i­fied func­tion re­turn type an­nota­tion 2
function.type_quoted Like function.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with parts quoted if type in­spec­tion failed to match the an­nota­tion to an ac­tu­al name
function.type_link Like function.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with cross-linked types
function.params List of func­tion para­met­ers. See be­low for de­tails.
function.exceptions List of ex­cep­tions raised by this func­tion. See be­low for de­tails.
function.has_complex_params Set to True if the para­met­er list should be wrapped on sev­er­al lines for bet­ter read­ab­il­ity (for ex­ample when it con­tains type an­nota­tions or de­fault ar­gu­ments). Set to False when wrap­ping on mul­tiple lines would only oc­cupy too much ver­tic­al space.
function.has_param_details If the func­tion para­met­ers are doc­u­mented
function.return_value Re­turn value doc­u­ment­a­tion. Can be empty.
function.has_details If there is enough con­tent for the full de­scrip­tion block 3
function.is_method Set to True if the func­tion is a class meth­od, False if it’s stan­dalone.
function.is_classmethod Set to True if the func­tion is an­not­ated with @classmethod, False oth­er­wise.
function.is_staticmethod Set to True if the func­tion is an­not­ated with @staticmethod, False oth­er­wise.
function.is_overloaded Set to True if the func­tion has mul­tiple over­loads with the same name, False oth­er­wise.

The function.params is a list of func­tion para­met­ers and their de­scrip­tion. Each item has the fol­low­ing prop­er­ties:

Prop­erty De­scrip­tion
param.name Para­met­er name
param.type Fully qual­i­fied para­met­er type an­nota­tion 2
param.type_quoted Like param.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with parts quoted if type in­spec­tion failed to match the an­nota­tion to an ac­tu­al name
param.type_link Like param.type_relative, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with cross-linked types
param.default De­fault para­met­er value, if any. If param.type is an enum, is a fully-qual­i­fied enum value.
param.default_relative Like param.default, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted if param.type is an enum
param.default_link Like param.default_relative, but with cross-linked types
param.kind Para­met­er kind, a string equi­val­ent to one of the in­spect.Para­met­er.kind val­ues
param.content De­tailed doc­u­ment­a­tion, if any

In some cases (for ex­ample in case of nat­ive APIs), the para­met­ers can’t be in­tro­spec­ted. In that case, the para­met­er list is a single entry with name set to None and the rest be­ing None as well. It’s then up to the tem­plate what it does. For ex­ample the built­in Py­thon help() shows ... (which isn’t val­id syn­tax), if you need a val­id syn­tax you can also use *args in­stead.

The function.exceptions is a list of ex­cep­tions types and de­scrip­tions. Each item has the fol­low­ing prop­er­ties:

Prop­erty De­scrip­tion
exception.type Fully qual­i­fied ex­cep­tion type
exception.type_relative Like exception.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted
exception.type_link Like exception.type_relative, but with a cross-linked type
exception.content De­tailed doc­u­ment­a­tion

Prop­erty prop­er­ties

Prop­erty De­scrip­tion
property.name Prop­erty name
property.id Prop­erty ID 5
property.type Fully qual­i­fied prop­erty get­ter re­turn type an­nota­tion 2
property.type_quoted Like property.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with parts quoted if type in­spec­tion failed to match the an­nota­tion to an ac­tu­al name
property.type_link Like property.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with cross-linked types
property.summary Doc sum­mary
property.content De­tailed doc­u­ment­a­tion, if any
property.exceptions List of ex­cep­tions raised when ac­cess­ing this prop­erty. Same as function.exceptions de­scribed in func­tion prop­er­ties.
property.is_gettable If the prop­erty is get­table
property.is_settable If the prop­erty is set­table
property.is_deletable If the prop­erty is de­letable with del
property.has_details If there is enough con­tent for the full de­scrip­tion block 3

Data prop­er­ties

Prop­erty De­scrip­tion
data.name Data name
data.id Data ID 5
data.type Fully qual­i­fied data type an­nota­tion 2
data.type_quoted Like data.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with parts quoted if type in­spec­tion failed to match the an­nota­tion to an ac­tu­al name
data.type_link Like data.type, but re­l­at­ive, i.e. with a com­mon pre­fix of the type and con­tain­ing mod­ule / class omit­ted, and with cross-linked types
data.summary Doc sum­mary
data.content De­tailed doc­u­ment­a­tion, if any
data.value Data value rep­res­ent­a­tion
data.has_details If there is enough con­tent for the full de­scrip­tion block 3

In­dex page tem­plates

The fol­low­ing in­dex pages are provided, show­ing a ex­pand­able tree of the con­tents:

Fi­le­name Use
classes.html Class list­ing
modules.html Mod­ule list­ing
pages.html Page list­ing

Each tem­plate is passed all con­fig­ur­a­tion val­ues from the Con­fig­ur­a­tion table as-is, to­geth­er with an URL, as above. The nav­ig­a­tion tree is provided in an index ob­ject, which has the fol­low­ing prop­er­ties:

Prop­erty De­scrip­tion
index.classes List of all mod­ules + classes
index.pages List of all pages

The form of each list entry is the same:

Prop­erty De­scrip­tion
i.kind Entry kind (one of 'module', 'class' or 'page')
i.name Name
i.url URL of the file with de­tailed doc­u­ment­a­tion
i.summary Doc sum­mary
i.has_nestable_children If the list has nestable chil­dren (i.e., dirs or namespaces)
i.children Re­curs­ive list of child entries

Mod­ule/class list is ordered in a way that all mod­ules are be­fore all classes.


2.
^ a b c d i.type is ex­trac­ted out of func­tion para­met­er type, func­tion re­turn type, prop­erty type and data type an­nota­tion. If the types aren’t an­not­ated, the an­nota­tion is empty.
3.
^ a b c d e f g h page.has_*_details and i.has_details are True if there is de­tailed de­scrip­tion, func­tion para­met­er doc­u­ment­a­tion or doc­u­men­ted enum value list­ing that makes it worth to render the full de­scrip­tion block. If False, the mem­ber should be in­cluded only in the sum­mary list­ing on top of the page to avoid un­ne­ces­sary re­pe­ti­tion.
4.
^ a b page.filename and page.url is gen­er­ated by an URL format­ter, see Cus­tom URL format­ters for more in­form­a­tion
5.
^ a b c d e i.id is an ID used for link­ing to giv­en entry on a page. Gen­er­ated by an an­chor format­ter, see Cus­tom URL format­ters for more in­form­a­tion.