Fumerov0.3.0

Generating

Run fumero over a module, and control what reaches the page

Fumero reads a module the way Python imports one, so it needs a module it can import:

uv init --lib example
cd example
uv add fumero --dev

Give src/example/__init__.py something to document:

src/example/__init__.py
def connect(host):
    """Open a connection to `host`."""


def _retry(host):
    """Try again after a failed attempt."""

Then run fumero over it:

fumero generate example --output content/docs/api
wrote 1 pages to content/docs/api

The result is content/docs/api/example.mdx, documenting connect with its signature and its description.

What reaches the page

_retry is absent by design. Fumero documents the public surface of a module: a name starting with an underscore is private, and a module defining __all__ is taken at its word, so anything it does not export is left out.

src/example/__init__.py
__all__ = ["connect"]


def connect(host): ...


def disconnect(host): ...  # public by name, but unexported, so undocumented

Public members are documented in place. Modules and classes each get a page, while functions and attributes are rendered on the page of whatever holds them, under an anchor named after them.

Naming the module

The argument is an import path rather than a path on disk, because fumero imports what it documents. The module has to be installed in the environment fumero runs in An unknown name is reported rather than silently producing an empty page:

fumero generate exmaple
error: could not load 'exmaple'. Is it importable in this environment?

A package is a module that happens to hold other modules, so both are documented the same way. example documents the whole tree; example.core documents that subtree alone, which is the way to publish parts of one package separately.

Compiled modules

A module written in C has no source to read, so fumero imports it and reads what the interpreter holds instead. A compiled function carries no signature, and the reference comes out with nothing taking any parameters:

def connect() -> Connection

Such a package usually ships .pyi stubs beside the binary, and those carry the signatures in full. --no-inspect reads the stubs rather than importing anything:

fumero generate example --no-inspect
def connect(host: str, timeout: float = 5.0) -> Connection

An extension package often writes each signature into the docstring as well, to make up for what the binary lost, which is why an inspected module can repeat its signatures as prose below them. Reading the stubs removes that too.

Inspecting a module runs it

Reading source does not execute anything, so documenting a package written in Python runs none of it. Inspecting is the exception: a module with no source is imported, and importing it runs its module-level code with whatever the interpreter can reach. That is the same trust you extend by installing the package, but it is worth knowing before pointing fumero at something you have not read. --no-inspect removes it.

Where the pages go

--output is the directory the tree is written into. --base-url is the URL that directory is served at, which fumero needs in order to build the links between pages. Set it whenever the reference is not served from the site root:

fumero generate example --output content/docs/api --base-url /docs/api

--clean removes the module's previous output before writing, so a renamed or deleted symbol leaves no orphan page. --with-meta writes the meta.json files that order the Fumadocs sidebar, listing submodules before classes instead of leaving both in alphabetical order.

fumero generate example --output content/docs/api --base-url /docs/api --clean --with-meta

Options that do not change between runs belong in the configuration table.

Fumero reports the references it could not resolve and continues:

warning: item link `Connection.clos` in content/docs/api/example.mdx matched no documented item
wrote 1 pages to content/docs/api

The run succeeds, since the pages are otherwise correct. An unresolved reference is rendered as plain code rather than as a link to a page that does not exist. See linking items for what resolves.

On this page