***************************************************************** Writing documentation ***************************************************************** This page explains how to add to these docs. There are two kinds of content: #. **Prose pages** — hand-written guides like this one, in reStructuredText (``.rst``). #. **API reference** — generated automatically from the docstrings in the ``semi_cr`` source code. Building the docs locally ========================== Run the docs server from the repo root:: uv run docs This regenerates the API reference from docstrings, builds the HTML, serves it at http://127.0.0.1:8000, opens a browser tab, and rebuilds on every save. Press ``Ctrl-C`` to stop. The built HTML lands in ``docs/_build/html`` and is **not** committed to the repo (it is ``.gitignore``\ d). Rendered Jupyter notebooks additionally require the ``pandoc`` binary; without it the notebook pages are skipped locally but the surrounding prose still builds. Writing prose pages (reStructuredText) ====================================== Prose pages are ``.rst`` files under ``docs/``. Sphinx uses `reStructuredText `_, not Markdown. To make a new page appear, create the file and add it to a ``toctree`` (see :ref:`wiring-a-page` below). reST cheat sheet ---------------- **Headings** are text underlined (and optionally overlined) with punctuation. The character you use defines the level; be consistent within a file. A common order is ``*`` (with overline) for the title, then ``=``, ``-``, ``~``:: ***** Title ***** Section ======= Subsection ----------- .. important:: The underline must be **at least as long as the text**, or Sphinx emits a "Title underline too short" warning and may misparse the page. **Inline markup**:: *italic* **bold** ``literal / code`` **Lists** — blank line before the list, indentation for continuation:: - bullet one - bullet two #. auto-numbered #. auto-numbered **Code blocks** — a ``::`` at the end of a paragraph starts a literal block; the block must be indented:: Here is some Python:: x = greeter("world") print(x) Use ``.. code-block:: python`` when you want syntax highlighting for a specific language:: .. code-block:: python def f(x): return x + 1 **Links**:: `link text `_ external link :doc:`api/index` link to another page :ref:`wiring-a-page` link to a labelled target :func:`semi_cr.core.helpers.deprecated` link to an API object **Admonitions** draw attention to a note:: .. note:: Blank line, then indented body. .. warning:: Same shape: ``note``, ``warning``, ``important``, ``tip``, ... .. _wiring-a-page: Wiring a page into the site --------------------------- A page is invisible until it is listed in a ``toctree``. Add its filename (without ``.rst``) to the ``toctree`` in ``docs/index.rst``:: .. toctree:: :maxdepth: 2 api/index writing_docs example_notebooks/index changes/index Nested sections get their own ``index.rst`` with a local ``toctree`` — see ``docs/example_notebooks/index.rst`` for an example that globs its contents. Documenting code for the API reference ======================================= The API pages under :doc:`api/index` are generated, not written by hand. On every build the ``sphinx.ext.apidoc`` extension scans the source tree and ``autodoc`` imports each module and reads its **docstrings**. So "adding API docs" means writing good docstrings; nothing else is required. .. important:: Only the ``semi_cr.core`` subtree is included in the API reference. The ``apps``, ``setup``, ``research`` and ``portable`` subtrees are excluded because they run hardware connections / interactive prompts at import time, which ``autodoc`` cannot do during a build. If you move reusable, safely importable code into ``core``, it shows up automatically. See the ``apidoc_modules`` setting in ``docs/conf.py`` for the exclusion list. Docstring style --------------- This project uses **Google-style** docstrings (enforced by ruff's ``pydocstyle`` config) which Sphinx understands via the ``napoleon`` extension. A function docstring looks like this: .. code-block:: python def greeter(name: str, *, loud: bool = False) -> str: """Generate a greeting message. A longer description can go here, spanning multiple lines. Keep the one-line summary on the first line, then a blank line, then details. Args: name: The name of the person to greet. Types come from the annotation, so you don't need to repeat them here. loud: If ``True``, shout the greeting. Returns: The formatted greeting. Raises: ValueError: If ``name`` is empty. Example: >>> greeter("world") 'Hello, world' """ Classes follow the same shape. Because ``autoclass_content = "both"`` is set, both the class docstring and the ``__init__`` docstring are shown, so document constructor arguments in ``__init__``: .. code-block:: python class Chip: """A device under test. Attributes: name: Human-readable identifier for the chip. """ def __init__(self, name: str) -> None: """Initialise the chip. Args: name: Human-readable identifier for the chip. """ self.name = name Common sections recognised by napoleon: ``Args``, ``Returns``, ``Yields``, ``Raises``, ``Attributes``, ``Example``/``Examples``, ``Note``, ``Warning``. What gets picked up ------------------- * **Modules, classes, functions and methods** are documented from their docstrings automatically once the module lives under ``semi_cr.core``. * **Undocumented** members still appear (``undoc-members`` is on), just without descriptions — so a docstring is always an improvement. * **Private** names (leading underscore) are omitted, except dunder methods that carry a docstring. * A **new module or subpackage** under ``core`` is included on the next build; ``sphinx-apidoc`` rediscovers the tree each time, so you don't edit any ``.rst`` by hand. Avoiding docstring warnings --------------------------- ``autodoc`` re-parses docstrings as reST, so the reST rules above apply inside them. The two most common warnings: * *"Unexpected indentation"* — usually a continuation line under ``Args:`` that isn't indented consistently, or a code example not introduced with ``::``. * *"Title underline too short"* — a ``Returns``/``Args`` line written as a reST heading (underlined with ``---``) instead of the Google ``Returns:`` section label. Use the ``Section:`` form, not underlines, inside docstrings. Build with ``uv run docs`` and read the warnings it prints; each one names the file and line so you can fix it at the source.