|
| bool | _is_auto_generated (Path path, str marker) |
| list[str] | _check_sphinx_deps () |
| dict | _load_project_info (Path root) |
| dict | _load_docs_config (Path root) |
| list[str] | _discover_markdown (Path docs_dir) |
| list[str] | _order_markdown (list[str] stems) |
| bool | _should_skip_dir (Path path, Path root) |
| list[tuple[str, Path]] | _find_packages (Path root, dict config) |
| bool | _generate_api_rst (Path root, Path docs_dir, dict config) |
| bool | _render_dot_svg (str dot_src, Path target) |
| bool | _generate_deps_rst (Path root, Path docs_dir) |
| None | _write_index_rst (Path docs_dir, str project_name, list[str] md_stems, bool has_api, bool has_deps, *, bool include_root_readme=False) |
| Path | setup_sphinx (Path root) |
| int | run_sphinx_build (Path docs_dir, dict config) |
| int | run_docs_sphinx (Path root, *, bool no_workspace=False) |
| bool | _check_doxygen_installed () |
| Path|None | _find_doxyfile (Path root) |
| str|None | _doxygen_setting (str content, str key) |
| Path | _doxygen_html_output_dir (Path doxyfile_path) |
| None | _clear_doxygen_pages (Path doxyfile_path, Path root) |
| int | _prune_unreferenced_graphs (Path html_dir) |
| Path | _create_patched_doxyfile (Path doxyfile_path, Path root) |
| int | _sweep_stale_doxyfiles (int max_age_seconds=_STALE_DOXYFILE_MAX_AGE_SECONDS) |
| int | run_docs_doxygen (Path root, *, bool no_workspace=False) |
| int | run_docs_clean (Path root, *, bool dry_run=False, bool no_workspace=False) |
| int | run_docs_all (Path root, *, bool no_workspace=False) |
Purpose
-------
Provide documentation generation pipelines for Option C projects:
``oct docs --sphinx``, ``oct docs --doxygen``, ``oct docs --all``, and ``oct docs --clean``.
Responsibilities
----------------
- Set up Sphinx configuration in the project's ``docs/`` directory (if not already present).
- Discover markdown documentation files already in ``docs/``.
- Generate API reference pages from Python module docstrings via autodoc.
- Generate dependency graph pages via ``oct deps``.
- Populate ``index.rst`` with all discovered content.
- Run ``sphinx-build`` to generate HTML output.
- Check for required Sphinx dependencies and emit a clear error if missing.
- Run Doxygen with a patched Doxyfile (correcting stale INPUT paths).
- Clean generated documentation artifacts while preserving user-authored files.
Diagnostics
-----------
Domain: OCT-DOCS
Levels:
L2 - lifecycle
L3 - semantic details
L4 - deep tracing
Contracts
---------
- Must not overwrite existing ``oct/docs/_sphinx/conf.py`` if already present.
- ``oct/docs/_sphinx/index.rst`` is regenerated on every build (auto-generated content).
- Must exit 1 with a helpful message if Sphinx dependencies are not installed.
- Template files are bundled in ``oct/templates/sphinx/``.
- Doxygen runs on a temporary copy of the Doxyfile; the original is never modified.
- ``--clean`` preserves ``_sphinx/``, ``_static/``, ``_templates/``, ``doxygen_work_dir/``, and user-authored markdown files.
Dependencies
------------
- oct.core.exclusions (directory exclusion lists)
- oct.core.diagnostics (_dbg structured logger)
- oct.tools.fs_remove (remove_tree_or_warn - removes generated output, warning on a tree that refuses to go)
- oct.core.option_c_dir (lazy; resolve_octrc - finds the octrc that holds the docs settings)
- oct.deps.import_graph (lazy; build_import_graph and its renderers - the dependencies page)
- oct.docs.doxyfile_init (lazy; DOXYFILE_REL - where a project's Doxyfile lives)
- oct.docs.typedoc (lazy; has_typedoc, run_docs_typedoc - the TypeDoc step of --all)
- oct.docs.workspace_docs (lazy; is_workspace_root, run_workspace_docs - the workspace fan-out)
- sphinx.ext.apidoc (lazy; main - writes the per-module API pages)
- tomli (lazy; reads pyproject.toml on Python 3.10, where tomllib is absent)
| None oct.docs.oct_docs._clear_doxygen_pages |
( |
Path | doxyfile_path, |
|
|
Path | root ) |
|
protected |
Delete the previous run's pages but keep the graph cache.
Doxygen regenerates every page it still has an input for, but it
never deletes the page for an input it no longer sees. Excluding a
file therefore leaves its generated page on disk indefinitely: the
navigation stops linking it, yet it keeps being copied into the
published site and keeps answering at its old URL. Clearing the pages
first is what makes the output mean "what the current configuration
produces".
The graphs are deliberately NOT cleared. Doxygen keys every dot graph
on an md5 of its source and skips ``dot`` when the rendered file
already matches, and that cache is most of the build: oc_pricing
rebuilds in 0.8 s with 0 dot invocations when the cache is present
and in 79 s with 304 when it is not (measured 2026-09-27). The
2026-09-26 version of this function removed the whole directory and
so threw the cache away on every build - oct's 3,185 graphs were
being re-rendered from scratch each time. Graphs whose page no
longer exists are pruned after the run by
:func:`_prune_unreferenced_graphs`, which is what keeps the original
orphan problem solved.
Two guards, because this deletes inside a directory whose location
comes from a config file: the target must resolve inside *root*, and
it must look like Doxygen's own output. Anything else is left alone
with a warning - a stale page is a much smaller problem than a
deleted source tree.
Failure is never fatal. Whatever cannot be removed is reported, and
the build still runs.
Definition at line 886 of file oct_docs.py.
| bool oct.docs.oct_docs._generate_deps_rst |
( |
Path | root, |
|
|
Path | docs_dir ) |
|
protected |
Generate the ``dependencies`` page: the subproject's dependency overview.
Two levels on one page (plan A, docs/DOCS_OVERVIEW_CHARTS_PLAN_2026-09-27.md):
a package-level Mermaid chart a person can read in one look, and the
full module-level graph rendered by Graphviz to a zoomable SVG. Both are
derived from the ``import`` statements, not the ``Dependencies``
docstring declarations that ``oct deps`` reports, because a structural
picture that can drift from the code is worse than none.
Returns True when a page was written (the graph has at least one edge),
so the caller can add it to the toctree.
Definition at line 448 of file oct_docs.py.
| dict oct.docs.oct_docs._load_docs_config |
( |
Path | root | ) |
|
|
protected |
Load docs configuration from the project's octrc with defaults (Appendix H).
Resolved through :func:`oct.core.option_c_dir.resolve_octrc`, which prefers
``.option_c/octrc.json`` and falls back to the legacy ``<root>/.octrc.json``.
This function used to hardcode the legacy path, so on a MIGRATED project --
which has no root ``.octrc.json`` -- the whole ``docs`` block was silently
ignored and the defaults below were always used. ``oct`` itself is migrated,
so its own configured ``autodoc_modules`` was being dropped: discovery fell
back to walking the tree, which picked up the stale ``build/lib/oct`` copy
alongside the real package and ran ``sphinx-apidoc`` over both.
Definition at line 187 of file oct_docs.py.
| int oct.docs.oct_docs._prune_unreferenced_graphs |
( |
Path | html_dir | ) |
|
|
protected |
Remove graph files no page in *html_dir* embeds; return the count.
The complement of :func:`_clear_doxygen_pages`: pages are always
rebuilt fresh, so after a run the set of ``.svg`` files the pages
reference is exactly the set of live graphs. Everything else in the
dot cache belongs to a function or class Doxygen no longer sees and
is removed - the rendered ``.svg``, the ``_org.svg`` original that
``INTERACTIVE_SVG`` keeps beside it, and the ``.map`` and ``.md5``
that would otherwise keep it "cached" forever.
Doxygen's own non-graph SVGs (``doxygen.svg``, the legend and the
theme's icons) are referenced from the pages like any graph and so
survive this on the same rule, with no special-casing.
Definition at line 966 of file oct_docs.py.
Remove orphaned ``oct-doxyfile-*.Doxyfile`` temp files.
The ``finally`` block in :func:`run_docs_doxygen` cleans up on normal
exit, exceptions, and ``FileNotFoundError`` - but it is skipped on
``SIGKILL``, power loss, or OOM-kill. Without this sweep the system
temp directory would slowly accumulate orphaned Doxyfiles (OI-423).
Best-effort: any OS error (per-file or directory-wide) is silently
swallowed so that a failed sweep never blocks a legitimate doxygen
build.
Returns the number of files removed.
Definition at line 1046 of file oct_docs.py.
| int oct.docs.oct_docs.run_docs_clean |
( |
Path | root, |
|
|
* | , |
|
|
bool | dry_run = False, |
|
|
bool | no_workspace = False ) |
Remove generated documentation artifacts from docs/.
Cleans: html/, doctrees/, _api/, doxygen_output/, typedoc/,
index.rst, dependencies.rst
Preserves: _sphinx/ (user conf.py), _static/, _templates/,
user-authored .md files, doxygen_work_dir/Doxyfile
Returns 0 when the artifacts are gone (or when there were none, or under
*dry_run*), and 1 when one or more could not be removed - the count it
prints is of directories verified absent afterwards, never of removal
calls made, so a refused delete cannot report as a clean.
Workspace mode (FS-WS-DOCS): from a workspace root, dispatches to
:func:`oct.docs.workspace_docs.run_workspace_docs` with
``mode="clean"`` (Phase F implementation). ``--no-workspace`` falls
back to single-project clean.
Definition at line 1168 of file oct_docs.py.