4. Directives

Waterloo directives insert generated documentation into a Sphinx document or change the build-time context used by later directives. They are ordinary reST directives with one argument and no directive body.

The extension provides three directive families:

  • Docstring rendering directives

  • State-changing directives

  • Callable signature directives

4.1. Docstring Rendering Directives

The docstring rendering directives are:

  • .. wtrl_autodoc_module:: <module-identifier>

  • .. wtrl_autodoc_class:: <class-identifier>

  • .. wtrl_autodoc_function:: <function-identifier>

  • .. wtrl_autodoc_method:: <method-identifier>

and the special recursive directive:

  • .. wtrl_autodoc_class_full:: <class-identifier>

Each directive resolves its argument to a Python object, reads that object’s Waterloo docstring, validates it, and renders it as Docutils nodes. Resolution uses the current Python interpreter, the configured wtrl_basedirs, and the current module/class state described below.

The identifier may be plain, partially qualified, or fully qualified. Fully qualified identifiers are explicit and work independently of the current state:

.. wtrl_autodoc_class:: sdv.doc.waterloo.docitem_helper.tracer

Plain identifiers become practical once a current module or class has been pushed:

.. wtrl_push_current_module:: sdv.doc.waterloo.docitem_helper

.. wtrl_autodoc_class:: tracer

.. wtrl_pop_current_module:: sdv.doc.waterloo.docitem_helper

The directive .. wtrl_autodoc_class_full:: starts with the class itself and then renders documentable member classes and methods recursively. It is useful for compact reference pages, while .. wtrl_autodoc_class:: is better when the surrounding document should control the order and grouping of members manually.

The extension module reference demonstrates the effect of these directives. Theme-specific showcase builds are available for:

4.2. State-Changing Directives

The state-changing directives are:

  • .. wtrl_push_current_module:: <module-identifier>

  • .. wtrl_pop_current_module:: <module-identifier>

  • .. wtrl_push_current_class:: <class-identifier>

  • .. wtrl_pop_current_class:: <class-identifier>

  • .. wtrl_push_current_scope:: <scope-symbol>

  • .. wtrl_pop_current_scope:: <scope-symbol>

These directives maintain three independent stacks: current module, current class, and current scope. A push directive adds a value to the corresponding stack. A pop directive removes the top value and requires the expected value as its argument. This explicit pop argument is intentional: it turns accidental nesting mistakes into visible diagnostics.

Depending on the configuration, state changes are rendered as small admonitions and/or logged during the Sphinx build. See Configuration for the corresponding switches.

4.2.1. Module And Class Stack

The module and class stacks reduce repetition in long sequences of rendering directives. Instead of writing fully qualified names for every class:

.. wtrl_autodoc_class:: sdv.doc.waterloo.docitem_helper.cls0

.. wtrl_autodoc_class:: sdv.doc.waterloo.docitem_helper.cls1

...

.. wtrl_autodoc_class:: sdv.doc.waterloo.docitem_helper.clsN

you can push the module once and document the classes by their local names:

.. wtrl_push_current_module:: sdv.doc.waterloo.docitem_helper

.. wtrl_autodoc_class:: cls0

.. wtrl_autodoc_class:: cls1

...

.. wtrl_autodoc_class:: clsN

.. wtrl_pop_current_module:: sdv.doc.waterloo.docitem_helper

In the rendered document, the module state change looks like this:

Waterloo module context

Classes and functions below this point implicitly belong to package/module sdv.doc.waterloo.docitem_helper.

and is closed as follows:

Waterloo module context

Default module qualifier sdv.doc.waterloo.docitem_helper ends here. New default: doc_errors.

The class stack works in the same way and is mainly useful for methods and nested classes. Instead of writing fully qualified method identifiers:

.. wtrl_autodoc_method:: sdv.doc.waterloo.docitem_helper.tracer.meth0

.. wtrl_autodoc_method:: sdv.doc.waterloo.docitem_helper.tracer.meth1

...

.. wtrl_autodoc_method:: sdv.doc.waterloo.docitem_helper.tracer.methN

you can push the module and class once:

.. wtrl_push_current_module:: sdv.doc.waterloo.docitem_helper

.. wtrl_push_current_class:: tracer

.. wtrl_autodoc_method:: meth0

.. wtrl_autodoc_method:: meth1

...

.. wtrl_autodoc_method:: methN

.. wtrl_pop_current_class:: tracer

.. wtrl_pop_current_module:: sdv.doc.waterloo.docitem_helper

The corresponding state changes are rendered as follows:

Waterloo module context

Classes and functions below this point implicitly belong to package/module sdv.doc.waterloo.docitem_helper.

Waterloo class context

Methods below this point implicitly belong to class tracer.

and are closed as follows:

Waterloo class context

Default class qualifier tracer ends here. No default class active.

Waterloo module context

Default module qualifier sdv.doc.waterloo.docitem_helper ends here. New default: doc_errors.

4.2.2. Scope Stack

The scope stack controls which docstrings are visible in the generated document. Waterloo docstrings may declare a scope, and a Sphinx document can select the target audience by pushing a scope value.

The current scope order is:

core > extension > public

Choosing public renders only public documentation:

.. wtrl_push_current_scope:: public

Choosing extension also includes extension-level documentation:

.. wtrl_push_current_scope:: extension

Choosing core renders the most complete view, including core, extension, and public documentation:

.. wtrl_push_current_scope:: core

The following state change is rendered into this documentation for demonstration purposes:

Waterloo scope context

Scope below this point is set to extension.

Waterloo scope context

Scope qualifier extension ends here. New current scope: public.

In practice, you will often set the scope near the beginning of a reference page and leave it unchanged afterwards.

4.3. Callable Signature Directives

The callable signature directives render a Python signature without rendering the full Waterloo docstring:

  • .. wtrl_function_signature:: <function-identifier>

  • .. wtrl_function_signature_block:: <function-identifier>

  • .. wtrl_method_signature:: <method-identifier>

  • .. wtrl_method_signature_block:: <method-identifier>

Use the inline variants when the signature is short enough to fit naturally into running text. Use the block variants for longer signatures or when the signature should visually introduce a following explanation.

Waterloo module context

Classes and functions below this point implicitly belong to package/module sphinxcontrib.waterloo_docstrings.

For demonstration and testing, this document renders the function resolve_qualified_name from the extension package. The inline directive is written as:

.. wtrl_function_signature:: extension.resolve_qualified_name

and renders as:

resolve_qualified_name(ctx: context | None, qname: str) -> tuple[object, str, str, list[str]]

The block form is written as:

.. wtrl_function_signature_block:: extension.resolve_qualified_name

and renders as:

sphinxcontrib.waterloo_docstrings.extension.resolve_qualified_name(
ctx: context | None
qname: str
) -> tuple[object, str, str, list[str]]

Waterloo module context

Default module qualifier sphinxcontrib.waterloo_docstrings ends here. New default: doc_errors.

Method signatures work analogously. The following example renders a method in the tracer class from sdv.doc.waterloo.docitem_helper:

.. wtrl_method_signature:: sdv.doc.waterloo.docitem_helper.tracer.build_json

which renders as:

build_json(severity: Severity, schema_version: str | None = None, waterloo_version: str | None = None, id_prefix: str | None = None, include_debug: bool = True) -> dict[str, Any]

The block representation is written as:

.. wtrl_method_signature_block:: sdv.doc.waterloo.docitem_helper.tracer.build_json

and renders as:

sdv.doc.waterloo.docitem_helper.tracer.build_json(
severity: Severity
schema_version: str | None = None
waterloo_version: str | None = None
id_prefix: str | None = None
include_debug: bool = True
) -> dict[str, Any]