Skip to main content

sphinx-contrib-prefect

A Sphinx extension for documenting Prefect flows, their parameters, Pydantic models, and the tasks and subflows observed in a flow graph.

The extension resolves flows from importable entrypoints and renders them as normal Sphinx sections. The v0.1 design renders flow graphs with Prefect's own runtime Mermaid generation, so no Prefect server or network access is required for self-contained flows.

Status: v0.1 is ready for release. The package scaffold, the core prefect-flow and prefect-params directives, main-flow docstring markers, external RST and MyST Markdown descriptions, module scanning with prefect-flow-index, parameter tables, Pydantic model documentation, runtime Mermaid flow graphs with :show-dag: and prefect-dag, subflow/task sections with cross-references, the unified error, dependency-tracking, and parallel-safety policy, and the documentation, example, and release preparation are implemented. See the release checklist and CHANGELOG. PyPI publishing runs through a manually triggered, human-approved GitHub Actions workflow.

Project context

Read these before changing behavior or architecture:

Installation

pip install sphinx-contrib-prefect

For MyST Markdown external descriptions, install the markdown extra:

pip install "sphinx-contrib-prefect[markdown]"

The core package does not depend on MyST. Without the extra, .md and .markdown description files warn and are omitted (or fail the build under prefect_on_error = "error").

Quick start

Add the extension to conf.py:

extensions = [
    "sphinx.ext.autodoc",
    "sphinxcontrib.pydantic",
    "sphinxcontrib.mermaid",
    "sphinxcontrib.prefect",
]

Document a flow by its importable entrypoint in index.rst:

EDA pipeline
============

.. prefect-flow:: mypkg.flows.eda

Build the page with sphinx-build -b html . _build/html. The directive renders the flow's title, entrypoint, optional version, signature, reStructuredText description, parameter table, and Pydantic model documentation. Both mypkg.flows.eda and mypkg.flows:eda entrypoint forms are accepted.

Prefect reads parameter descriptions from Google-style Args: sections. Each row shows the parameter name, type, required/optional status, default, and description. Pydantic parameter models are rendered by sphinxcontrib-pydantic, including nested models and Field(description=...) text. Only importable module-level Pydantic v2 models can be documented; local, nested, dynamically generated, and Pydantic v1 models are omitted with a diagnostic. Use prefect-params to render the flow's metadata fields, parameter table, and model sections without the description:

.. prefect-params:: mypkg.flows.eda

Use an external RST file when the description outgrows the docstring:

.. prefect-flow:: mypkg.flows.eda
   :description-from: descriptions/eda.rst

The path is resolved relative to the Sphinx source directory (the directory containing conf.py). .rst files are parsed as reStructuredText. With the markdown extra installed, .md and .markdown files are parsed as MyST Markdown, so headings, lists, code blocks, links, and inline markup work. Docstrings always remain reStructuredText; Markdown applies only to external files. See the usage guide for the format rules.

Docstrings may also carry a main-flow marker (@mainflow, YAML frontmatter, or :mainflow:); marker syntax is stripped from the rendered description. Markers drive flow selection in prefect-flow-index.

Configure one or more scanned modules in conf.py:

prefect_modules = ["mypkg.flows"]
prefect_main_flows = ["mypkg.flows.eda"]

Then render every selected main flow on the current page:

.. prefect-flow-index::

The index imports each configured module and renders one prefect-flow-style section per flow that has a true marker or an entry in prefect_main_flows. Flows are ordered by module list order and then attribute order; explicit flows outside prefect_modules follow in configuration order. Module scanning imports user code, so import-time side effects may run during the build. :show-dag: and :no-dag: apply to every generated section.

Directive reference

Directive Arguments Options Renders
prefect-flow Flow entrypoint (module.qualname or module:qualname) :show-dag:, :no-dag:, :description-from: Title, entrypoint, version, signature, description, parameter table, models, optional graph, subflow/task sections, and body content
prefect-params Flow entrypoint — Entrypoint, version, signature, parameter table, and model sections
prefect-dag Flow entrypoint — Runtime graph plus the observed subflow/task/unknown-node sections
prefect-flow-index — :show-dag:, :no-dag: One prefect-flow-style section per selected main flow

Configuration

All values are registered with rebuild type env.

Name Type Default Purpose
prefect_modules list[str] [] Modules scanned by prefect-flow-index
prefect_main_flows list[str] [] Entrypoints selected as main flows regardless of markers
prefect_dag_enabled bool False Enable runtime graph generation for prefect-flow
prefect_dag_sample_args dict[str, dict[str, object]] {} Sample arguments keyed by flow entrypoint
prefect_on_error str "warn" "warn" continues with a warning; "error" fails the build

Main-flow markers

A flow becomes a main flow in prefect-flow-index when its docstring uses any of these forms:

@flow
def eda(seed: int = 1):
    """Run the EDA build.

    @mainflow
    """
@flow
def eda(seed: int = 1):
    """---
    mainflow: true
    ---
    Run the EDA build.
    """
@flow
def eda(seed: int = 1):
    """Run the EDA build.

    :mainflow:
    """
  • @mainflow is a literal standalone docstring line, not a Python decorator.
  • YAML frontmatter is parsed only at the start of the docstring; mainflow: false does not select the flow.
  • :mainflow: and :mainflow: true select the flow; :mainflow: false does not.
  • A true marker wins over a false marker and emits a conflict warning.
  • Explicit selection with prefect_main_flows or a prefect-flow directive overrides markers.
  • All marker syntax is stripped from the rendered description.
  • Malformed YAML or an invalid marker value follows prefect_on_error.

The example project demonstrates all three forms.

Runtime flow graphs

Flow graphs come from Prefect's runtime visualization. Generating one executes the flow body, so it is opt-in and may perform I/O, read credentials, or write files. Enable it for one directive:

.. prefect-flow:: mypkg.flows.eda
   :show-dag:

Or enable it globally, with sample arguments for required parameters:

prefect_dag_enabled = False
prefect_dag_sample_args = {
    "mypkg.flows.eda": {"seed": 42},
}

:no-dag: suppresses a globally enabled graph. prefect-dag always opts in and renders the graph without the flow description or parameter table:

.. prefect-dag:: mypkg.flows.eda

The graph styles the main flow, subflows, tasks, and unknown nodes, and adds a legend. Missing sample arguments, unsupported .submit() / .map() calls, missing Prefect run context, and execution failures follow prefect_on_error and omit the graph.

Limitations and safety:

  • One execution path. Only the branches taken with the configured sample arguments appear. Change the sample arguments to document a different path.
  • Subflows are leaves. A subflow's internal tasks are not expanded and no recursive graph is generated. Add a separate directive for its internals.
  • Deployment calls are invisible. Flows started with arun_deployment() or run_deployment() are not tracked; document them with explicit directives.
  • Asynchronous task calls are unsupported. .submit(), .map(), and .apply_async() raise Prefect's VisualizationUnsupportedError, so the graph is omitted.
  • The flow body executes. Enabling a graph is an explicit decision to run user code that may perform I/O, read credentials, or write files. There is no sandbox.
  • Sample arguments are passed as-is. Prefect calls the flow function with the configured values without validating them against the flow's Pydantic parameter model. When a parameter is a model, construct the model instance in conf.py; a plain dictionary is not coerced.

Graph nodes that match module-level Flow and Task objects also get Subflows and Tasks sections with their description, signature, parameter table, and Pydantic models. Their names link to stable prefect-flow-<entrypoint> and prefect-task-<entrypoint> anchors from a short list in each section; the Mermaid source itself stays unlinked. Names that match no object, or more than one object, are listed under Unknown nodes without a link. Subflows are documented as leaves: their internal tasks are not expanded and no recursive graph is generated.

The text/man builders render Mermaid's [graph] placeholder, and LaTeX/PDF output needs the mmdc binary. See the usage guide for enablement, sample arguments, failure behavior, and limitations.

Errors, rebuilds, and parallelism

Recoverable failures warn and omit the affected part of the page by default. Set prefect_on_error = "error" to fail the build instead. Every diagnostic names the directive's path:line and, where available, the flow, task, module, or description file involved; the complete list is in the usage guide's failure-modes table.

Flow and task source files and external description files are registered with env.note_dependency(), so editing them rebuilds the page in Sphinx incremental mode. The extension declares parallel_read_safe = False because runtime DAG generation executes user code, and parallel_write_safe = True. v0.1 has no custom DAG cache and no subprocess isolation.

Documentation and example

The extension's own documentation lives under docs/ and builds with -W (warnings are errors):

uv sync --extra markdown
uv run sphinx-build -W -b html docs docs/_build/html

The example project exercises every directive, all three main-flow marker forms, scalar and nested Pydantic parameters, a runtime graph, subflows, tasks, an index page, and a standalone flow page. Its conf.py contains a working prefect_dag_sample_args entry:

uv run sphinx-build -W -b html examples/demo examples/demo/_build/html

CI builds both projects with -W, inspects the wheel and sdist, and installs the built wheel into a clean virtual environment before rebuilding the example. Every CI run also uploads the generated example HTML as the downloadable example-html artifact, so the rendered pages can be inspected without a local build. The Publish to PyPI workflow is started manually from a v* tag, reruns those checks, and then waits for approval in the protected pypi GitHub environment before publishing. See the release checklist for the one-time environment and PyPI trusted-publisher setup.

Development

Prerequisites

  • Python 3.12 or 3.13
  • uv

Clone and set up

git clone git@github.com:szerming/sphinx-prefect.git
cd sphinx-prefect
uv sync --all-extras

--all-extras installs the optional MyST Markdown dependency as well as the development tools.

Run checks

uv run ruff format --check .
uv run ruff check .
uv run pytest

Run uv run ruff format . to apply formatting. Tests use sphinx.testing.fixtures; integration test roots live under tests/roots/. See the coding guide for the architecture, test layout, and the full definition of done.

License

MIT. See LICENSE.

Metadata

Release files for sphinx-contrib-prefect 0.1.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 sphinx-contrib-prefect 0.1.0
File Size Uploaded Provenance
sphinx_contrib_prefect-0.1.0.tar.gz 204.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sphinx-contrib-prefect 0.1.0
File Interpreter ABI Platform
sphinx_contrib_prefect-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 235.7 kB

Release files / sphinx_contrib_prefect-0.1.0.tar.gz

Download URL sphinx_contrib_prefect-0.1.0.tar.gz
Size 204.6 kB
Tags Source
SHA-256 checksum
How to use checksums
2e5d13b0d5ceb4d8cdbb03230b784cd65466bddc6398aefaa8aceca11bddd50f
BLAKE2b-256 checksum
How to use checksums
b988d0b14252692156c69f8f4eeb1607269e6b10bc6acfc6276e2fd20b3a3816
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / sphinx_contrib_prefect-0.1.0-py3-none-any.whl

Download URL sphinx_contrib_prefect-0.1.0-py3-none-any.whl
Size 31.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b17ccd69fdb16f4780b702472cc8827da2a6a21ce0cb449c60c39df539c866d
BLAKE2b-256 checksum
How to use checksums
f1bf5a1e359c6047e197e89d7eda5bfc3e78d00eab0d8d54782358264cd540e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for sphinx-contrib-prefect 0.1.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sphinx_contrib_prefect-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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