Skip to main content

Autodox

Tool for generating documentation automatically from code annotations, types, and docstrings.

Status

Primary development is complete. Further development will be tracked in the issues. Historical changes can be found in the changelog.

Full API documentation generated by autodox can be found here.

Usage

Note that autodox imports the module being documented, so it must be installed in the same Python environment as the target module. If autodox is installed at the system or user level while the target module lives in a virtual environment, the autodox CLI will not be able to import it. Install autodox inside the target module's environment (e.g. activate the virtualenv and run pip install autodox there) before documenting it.

Installation

pip install autodox

Note that Protocols do not support __init__ methods before Python 3.11. To use __init__ method signatures for Protocols in Python 3.10, use the typing.Protocol backport from the 3rd-party typing_extensions package. Otherwise, the __init__ method signature will be overridden with an empty one named _no_init_or_replace_init and will be ignored by this tool.

Document a module from CLI

Use the following to document a module with default configuration:

autodox module_name [options] > target_file.md

By default, the output ends with a footer identifying the autodox and Python versions; pass --no-footer to omit it.

Run autodox --help for the full, up-to-date list. The output can be configured with the following options:

  • --exclude-name=name to exclude a specific part of the module by name (or pass a comma-separated list; repeatable)
  • --exclude-type=type to exclude any module parts of the given type (or pass a comma-separated list; repeatable)
  • --package=module_name to scope a relative import
  • --header-level=number to increase the hashtag count in headers by number
  • --function-format=format - can be one of 'header', 'paragraph', or 'list'
  • --method-format=format - can be one of 'header', 'paragraph', or 'list'
  • --value-format=format - can be one of 'header', 'paragraph', or 'list'
  • --line-length=number - number of chars per line in paragraphs and list items
  • --include-private to include things prefaced with _
  • --include-dunder to include things prefaced with __
  • --include-submodules to include submodules
  • --document-submodules to run the module documentation for submodules
  • --no-backtick-names to omit backticks around names (annotations, values, classes, modules, and aliases)
  • --no-backtick-types to omit backticks around annotation and value types
  • --no-backtick-signatures to omit backticks around function and method signatures
  • --no-backticks to disable all backticks at once, forcing each granular flag off
  • --no-clean-type-aliases to keep module qualifiers in type alias definitions (e.g. typing.Callable[...])
  • --verbose-defaults to render complex default values in full instead of abbreviating them to ...
  • --sort-default-dicts to sort dictionary defaults by rendered key instead of preserving insertion order
  • --sort-classes to sort classes by name instead of preserving module namespace order
  • --no-footer to omit the generated-by footer
  • --debug to increase the level of debug statements printed to stderr (starts at 0; levels 1-3 are available, and debug output does not contaminate redirected markdown)
  • -v, --version to print the version and exit

For experimentation and to learn how the options work, try running the following:

autodox autodox [options]

Programmatic access

The autodox package can also be used by importing and running the desired documentation function(s). The following are included.

  • dox_a_module(module: ModuleType, options: dict | None = None) -> str produces docs for a module
  • dox_a_value(value: Any, options: dict | None = None) -> str produces docs for a value
  • dox_a_function(function: Callable, options: dict | None = None) -> str produces docs for a function
  • dox_a_class(cls: type, options: dict | None = None) -> str produces docs for a class
  • dox_footer() -> str produces a markdown footer with the autodox and Python versions

The valid options for the dox_a_{thing} functions are described below. The dox_a_* functions do not append the footer automatically. Additionally, there is a system for setting up hooks that interact with the doc generation process to change the inputs or outputs, and that will be described below the options for the four dox_a_{thing} functions.

dox_a_module(module: ModuleType, options: dict | None = None) -> str

Produces docs for a module. Valid options are the following:

  • exclude_names: list[str] - names to exclude from docs
  • exclude_types: list[str] - types to exclude from docs
  • header_level: int - number of additional hashtags to add to headers
  • function_format: str - can be one of 'header', 'paragraph', or 'list'
  • method_format: str - can be one of 'header', 'paragraph', or 'list'
  • value_format: str - can be one of 'header', 'paragraph', or 'list'
  • include_private: bool - if True, includes things with names prefaced by _
  • include_dunder: bool - if True, includes things with names prefaced by __
  • include_submodules: bool - if True, notes will be made about any additional modules encountered when analyzing the specified module
  • document_submodules: bool - if True, dox_a_module will be called recursively on any additional modules encountered when analyzing the specified module
  • line_length: int - number of chars per line in paragraphs and list items
  • backtick_names: bool - if False, omits backticks from names (annotations, values, classes, modules, and aliases; defaults to True)
  • backtick_types: bool - if False, omits backticks from annotation and value types (defaults to True)
  • backtick_signatures: bool - if False, omits backticks from function and method signatures (defaults to True)
  • backticks: bool - if False, disables all backticks regardless of the granular options (defaults to True); setting it True does not re-enable a category disabled by a granular option
  • clean_type_aliases: bool - if False, keeps module qualifiers in rendered type alias definitions (defaults to True)
  • verbose_defaults: bool - if True, renders complex default values in full instead of abbreviating them to ... (defaults to False)
  • sort_default_dicts: bool - if True, sorts dictionary defaults by rendered key instead of preserving insertion order (defaults to False)
  • sort_classes: bool - if True, sorts classes by name instead of preserving module namespace order; alias entries sort by their binding name (defaults to False)

Module-level type aliases (for example Handler = Callable[[Message], Message]) are rendered in the Values section as Handler = Callable[[Message], Message] rather than by their private runtime class name. PEP 585 builtin generics, PEP 604 unions, typing aliases, PEP 695 type aliases, and typing.NewType are supported. typing.Optional and typing.Union are rendered as PEP 604 unions, and typing.List, typing.Dict, typing.Set, typing.FrozenSet, typing.Tuple, and typing.Type are rendered as their builtin generic equivalents on every supported Python version, e.g. Optional[List[int]] becomes list[int] | None. Unions place None last, and runtime forward references render in quotes, e.g. Optional['Node'] becomes 'Node' | None. By default, typing., builtins., collections.abc., and the documented module's own qualifier are stripped from the rendered definition; string literals inside a definition are left untouched. NewType values render as Name = NewType('Name', Supertype).

When the same class or function is bound to more than one name in a module (e.g. UsageError = DependencyError), dox_a_module documents the target once and emits an alias entry (### \UsageError = DependencyError`) for each additional binding. Alias detection is automatic; no configuration is required, and a class-body method alias such as bar = foois handled the same way. An alias is only detected when the target is bound under itsnamein the same namespace: aliases of builtins, inherited methods, renamed imports, and name-mangled targets are documented under theirnameinstead. Withsort_classes`, alias entries sort alongside other classes by their binding name.

dox_a_value(value: Any, options: dict | None = None) -> str

Produces docs for a value. Valid options are the following:

  • header_level: int - number of additional hashtags to add to headers
  • format: str - format can be one of 'header', 'paragraph', or 'list'
  • name: str - overrides the name used in the docs (the module binding name)
  • line_length: int - number of chars per line in paragraphs and list items
  • backtick_names: bool - if False, omits backticks from the value name (defaults to True)
  • backtick_types: bool - if False, omits backticks from the value type (defaults to True)
  • backticks: bool - if False, disables all backticks (defaults to True; see dox_a_module for how it interacts with the granular options)
  • clean_type_aliases: bool - if False, keeps module qualifiers in rendered type alias definitions (defaults to True)
  • module_name: str - module qualifier to strip from type alias definitions (usually set automatically by dox_a_module)

Runtime type aliases and NewType values are rendered as name = definition; other values keep the name: type form.

dox_a_function(function: Callable, options: dict | None = None) -> str

Produces docs for a function. Valid options are the following:

  • header_level: int - number of additional hashtags to add to headers
  • format: str - format can be one of 'header', 'paragraph', or 'list'
  • prepend: str - text prepended to the signature (used for decorators)
  • line_length: int - number of chars per line in paragraphs and list items
  • backtick_signatures: bool - if False, omits backticks from the signature (defaults to True)
  • backticks: bool - if False, disables all backticks (defaults to True; see dox_a_module for how it interacts with the granular options)
  • verbose_defaults: bool - if True, renders complex default values in full instead of abbreviating them to ... (defaults to False)
  • sort_default_dicts: bool - if True, sorts dictionary defaults by rendered key instead of preserving insertion order (defaults to False)

By default, callable defaults, object instances, nested containers, and containers with more than three items are rendered as .... Scalar and small container defaults keep their literal form; type aliases render as their definitions (PEP 695 type aliases as their names) using the same canonical PEP 604/builtin-generic form, and NewType values render as their names. typing.Any renders as Any on all supported Python versions. Bytes-like defaults are also elided when they exceed 40 bytes, including when nested inside a small container. With verbose_defaults, callables and callable instances render as Callable[..., ReturnType], non-callable object instances use a stable TypeName(...) placeholder, and containers are expanded recursively. Combined Flag defaults render as fully qualified member unions, such as Mode.READ | Mode.WRITE.

Dictionary defaults preserve insertion order by default. With sort_default_dicts, dictionary items are sorted recursively by their rendered key and value. Verbose output never includes memory addresses; enable sort_default_dicts as well when dictionary insertion order may vary between runs.

dox_a_class(cls: type, options: dict | None = None) -> str

Produces docs for a class. Valid options are the following:

  • exclude_names: list[str] - names to exclude from docs
  • header_level: int - number of additional hashtags to add to headers
  • include_private: bool - if True, includes things with names prefaced by '_'
  • include_dunder: bool - if True, includes things with names prefaced by '__'
  • method_format: str - can be one of 'header', 'paragraph', or 'list'
  • line_length: int - number of chars per line in paragraphs and list items
  • backtick_names: bool - if False, omits backticks from the class header and annotation names (defaults to True)
  • backtick_types: bool - if False, omits backticks from annotation types (defaults to True)
  • backtick_signatures: bool - if False, omits backticks from method signatures (defaults to True)
  • backticks: bool - if False, disables all backticks (defaults to True; see dox_a_module for how it interacts with the granular options)
  • verbose_defaults: bool - if True, renders complex default values in full instead of abbreviating them to ... (defaults to False)
  • sort_default_dicts: bool - if True, sorts method dictionary defaults by rendered key instead of preserving insertion order (defaults to False)

Enum subclasses also get a Members section immediately after the docstring. Members are listed in declaration order as NAME = value; aliases render as ALIAS = TARGET, and Flag/IntFlag composites render as NAME = A | B = value when all bits map to visible single-bit members. exclude_names, include_private, and include_dunder apply to member names. Complex values follow the same rendering rules as parameter defaults, so they are abbreviated to ... unless verbose_defaults is enabled.

Hooks

There are eleven events where custom functionality can be run, specified in the Event enum:

  • AFTER_HEADER
  • AFTER_PARAGRAPH
  • AFTER_LIST
  • BEFORE_VALUE
  • AFTER_VALUE
  • BEFORE_FUNCTION
  • AFTER_FUNCTION
  • BEFORE_CLASS
  • AFTER_CLASS
  • BEFORE_MODULE
  • AFTER_MODULE

Handlers for the BEFORE_ events can be set using the set_before_handler function. These handlers will receive the item to be documented and a dict containing any options passed into the dox_a_{thing} function, and they should return a tuple containing those two arguments after any modifications are made to them. Example:

from autodox import Event, set_before_handler
from typing import Callable


def handle_before_function(function: Callable, options: dict):
    # set an option
    options['header_level'] = 2
    return (function, options)

set_before_handler(Event.BEFORE_FUNCTION, handle_before_function)

Handlers for the AFTER_ events can be set using the set_after_handler function. These handlers will receive the str doc after the dox_a_{thing} function has completed executing, and they should return that document after any modifications are made. Example:

from autodox import Event, set_after_handler


def handle_after_function(doc: str):
    # do some string manipulation
    return doc + 'But really, why would you call this function anyway?\n\n'

set_after_handler(Event.AFTER_FUNCTION, handle_after_function)

Multiple handlers can be set for each event, and they will be executed in order, passing the output from the first as input to the second, etc. Example:

from autodox import Event, set_after_handler


# add 'hello world' to the end of each list item in two steps
def hello(doc: str):
    return doc + ' hello'

def world(doc: str):
    return doc + ' world'

set_after_handler(Event.AFTER_LIST, hello)
set_after_handler(Event.AFTER_LIST, world)

Testing

The test suite uses the standard library unittest module and covers the hook system and the generated documentation, including signature rendering, class annotations, protocols, and alias detection.

To run it, clone the repository and run the following:

# setup
python -m venv venv
source venv/bin/activate
pip install -e .

# then
python tests/test_hooks.py
python tests/test_doxing.py
# or
python -m unittest discover tests/

ISC License

Copyright (c) 2026 k98kurz

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyleft notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Metadata

Release files for autodox 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for autodox 0.2.0
File Size Uploaded Provenance
autodox-0.2.0.tar.gz 23.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for autodox 0.2.0
File Interpreter ABI Platform
autodox-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.8 kB

Release files / autodox-0.2.0.tar.gz

Download URL autodox-0.2.0.tar.gz
Size 23.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ac87fd60c74fae8383c1ccdb834bd8f8de185a647c9a55607a9b1a65270e65b5
BLAKE2b-256 checksum
How to use checksums
71d4122de3334198321e969703e7fbacbca2eb5acfa3faf386363d477471af02
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / autodox-0.2.0-py3-none-any.whl

Download URL autodox-0.2.0-py3-none-any.whl
Size 22.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d0202a3f602a0a05d095f7fec6601afc0bae571b38420af616c87dd3db0b2714
BLAKE2b-256 checksum
How to use checksums
862c9d05e09a164c7b3f46056339dc630274293a419dba299073274c5bdb0454
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for autodox 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page