Option C Tools
Loading...
Searching...
No Matches
oct.docs.oct_docs Namespace Reference

Functions

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 _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)
Path setup_sphinx (Path root)
int run_sphinx_build (Path docs_dir, dict config)
int run_docs_sphinx (Path root)
bool _check_doxygen_installed ()
Path|None _find_doxyfile (Path root)
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)
int run_docs_clean (Path root, *, bool dry_run=False)
int run_docs_all (Path root)

Variables

str _TEMPLATES_DIR = Path(__file__).parent.parent / "templates" / "sphinx"
str _AUTO_MARKER_RST = ".. Auto-generated by oct docs --sphinx"
str _AUTO_MARKER_MD = "<!-- Auto-generated by oct docs --sphinx -->"
list _REQUIRED_PACKAGES
dict _DOCS_EXCLUDE_DIRS
list _PRIORITY_DOCS
int _MAX_PACKAGE_DEPTH = 10
int _STALE_DOXYFILE_MAX_AGE_SECONDS = 24 * 60 * 60
list _DOCS_CLEAN_DIRS = ["html", "doctrees", "_api", "doxygen_output"]
list _DOCS_CLEAN_FILES = ["index.rst", "dependencies.rst"]

Detailed Description

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 ``conf.py`` if already present.
- ``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.deps.oct_deps (dependency graph generation)
- oct.core.exclusions (directory exclusion lists)

Function Documentation

◆ _check_doxygen_installed()

bool oct.docs.oct_docs._check_doxygen_installed ( )
protected
Check if doxygen is on PATH via shutil.which().

Definition at line 677 of file oct_docs.py.

Here is the caller graph for this function:

◆ _check_sphinx_deps()

list[str] oct.docs.oct_docs._check_sphinx_deps ( )
protected
Check which Sphinx dependencies are missing.

Definition at line 122 of file oct_docs.py.

Here is the caller graph for this function:

◆ _create_patched_doxyfile()

Path oct.docs.oct_docs._create_patched_doxyfile ( Path doxyfile_path,
Path root )
protected
Create a temporary copy of the Doxyfile with INPUT patched to actual root.

The existing Doxyfiles have hardcoded stale paths.  This creates a temp
copy with the correct INPUT path.  Does NOT modify the original.

Returns the path to the temp Doxyfile.

Definition at line 690 of file oct_docs.py.

Here is the caller graph for this function:

◆ _discover_markdown()

list[str] oct.docs.oct_docs._discover_markdown ( Path docs_dir)
protected
Discover markdown files in the docs directory, recursing into
subdirectories that are not in :data:`_DOCS_EXCLUDE_DIRS`.

Returns a sorted list of file identifiers relative to ``docs_dir`` and
stripped of the ``.md`` extension. For files in the docs/ root these
identifiers are bare stems (e.g. ``"ARCHITECTURE"``); for files in
subdirectories they are POSIX-form relative paths
(e.g. ``"option_c_specs/00_Master_Option_C_Specs_Intro_V3_4"``).
Sphinx-MyST consumes both forms directly in the toctree.

Definition at line 196 of file oct_docs.py.

Here is the caller graph for this function:

◆ _find_doxyfile()

Path | None oct.docs.oct_docs._find_doxyfile ( Path root)
protected
Locate docs/doxygen_work_dir/Doxyfile if it exists.

Definition at line 682 of file oct_docs.py.

Here is the caller graph for this function:

◆ _find_packages()

list[tuple[str, Path]] oct.docs.oct_docs._find_packages ( Path root,
dict config )
protected
Discover Python packages to document.

Walks the project tree recursively, stopping at each package (a
directory containing ``__init__.py``) rather than descending into
its subpackages — Sphinx autodoc handles subpackages automatically.
Respects ``LINTER_EXCLUDE_DIRS`` and ``WILDCARD_EXCLUDE_DIRS`` via
:func:`_should_skip_dir`.

Bounded by :data:`_MAX_PACKAGE_DEPTH` to prevent pathological walks
on misconfigured projects (OI-426).

Returns list of ``(package_name, package_path)`` tuples.

Definition at line 275 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _generate_api_rst()

bool oct.docs.oct_docs._generate_api_rst ( Path root,
Path docs_dir,
dict config )
protected
Generate per-module API documentation using sphinx-apidoc.

Uses sphinx-apidoc to create comprehensive .rst files for every
module, class, and function — similar to Doxygen's EXTRACT_ALL output.

Returns True if at least one package was documented.

Definition at line 321 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _generate_deps_rst()

bool oct.docs.oct_docs._generate_deps_rst ( Path root,
Path docs_dir )
protected
Generate dependencies.rst with a Mermaid dependency graph.

Returns True if the graph has edges.

Definition at line 387 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _is_auto_generated()

bool oct.docs.oct_docs._is_auto_generated ( Path path,
str marker )
protected
Return True if *path* is absent or was written by ``oct docs``.

OI-518: used as a write-safety guard around regeneration of
``docs/README.md``, ``docs/index.rst``, ``docs/dependencies.rst``,
and ``docs/_api/modules.rst``. A user-authored file (no marker) is
left untouched and a warning is emitted instead.

Definition at line 72 of file oct_docs.py.

Here is the caller graph for this function:

◆ _load_docs_config()

dict oct.docs.oct_docs._load_docs_config ( Path root)
protected
Load docs configuration from .octrc.json with defaults (Appendix H).

Definition at line 170 of file oct_docs.py.

Here is the caller graph for this function:

◆ _load_project_info()

dict oct.docs.oct_docs._load_project_info ( Path root)
protected
Load project name, version, and author from pyproject.toml or defaults.

Definition at line 139 of file oct_docs.py.

Here is the caller graph for this function:

◆ _order_markdown()

list[str] oct.docs.oct_docs._order_markdown ( list[str] stems)
protected
Order markdown identifiers with priority docs first, then alphabetical.

Identifiers may be bare stems (root-level docs) or
``subdir/.../stem`` paths (subdirectory docs). Priority matching
compares against the basename so ``_PRIORITY_DOCS`` entries can stay
leaf-name-based even as files move into subdirectories.

Definition at line 220 of file oct_docs.py.

Here is the caller graph for this function:

◆ _should_skip_dir()

bool oct.docs.oct_docs._should_skip_dir ( Path path,
Path root )
protected
Check if a directory should be excluded from module discovery.

Definition at line 253 of file oct_docs.py.

Here is the caller graph for this function:

◆ _sweep_stale_doxyfiles()

int oct.docs.oct_docs._sweep_stale_doxyfiles ( int max_age_seconds = _STALE_DOXYFILE_MAX_AGE_SECONDS)
protected
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 729 of file oct_docs.py.

Here is the caller graph for this function:

◆ _write_index_rst()

None oct.docs.oct_docs._write_index_rst ( Path docs_dir,
str project_name,
list[str] md_stems,
bool has_api,
bool has_deps )
protected
Write a populated index.rst with discovered content.

Definition at line 438 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_docs_all()

int oct.docs.oct_docs.run_docs_all ( Path root)
Run both Sphinx and Doxygen pipelines.

Returns 0 if both succeed, 1 if either fails.

Definition at line 879 of file oct_docs.py.

Here is the call graph for this function:

◆ run_docs_clean()

int oct.docs.oct_docs.run_docs_clean ( Path root,
* ,
bool dry_run = False )
Remove generated documentation artifacts from docs/.

Cleans: html/, doctrees/, _api/, doxygen_output/,
        index.rst, dependencies.rst

Preserves: _sphinx/ (user conf.py), _static/, _templates/,
           user-authored .md files, doxygen_work_dir/Doxyfile

Returns 0 always.

Definition at line 833 of file oct_docs.py.

◆ run_docs_doxygen()

int oct.docs.oct_docs.run_docs_doxygen ( Path root)
Full oct docs --doxygen pipeline.

1. Check doxygen is installed (shutil.which)
2. Find existing Doxyfile in docs/doxygen_work_dir/
3. Create patched temp copy with correct INPUT
4. Run doxygen on the temp Doxyfile
5. Clean up temp Doxyfile
6. Report output location (docs/doxygen_output/)

Returns exit code: 0 on success, 1 on failure.

Definition at line 761 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_docs_sphinx()

int oct.docs.oct_docs.run_docs_sphinx ( Path root)
Full oct docs --sphinx pipeline.

1. Check dependencies
2. Set up Sphinx config (one-time)
3. Load .octrc.json docs configuration
4. Discover markdown files
5. Generate API reference (autodoc)
6. Generate dependency graph
7. Write populated index.rst
8. Run sphinx-build

Returns exit code.

Definition at line 600 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_sphinx_build()

int oct.docs.oct_docs.run_sphinx_build ( Path docs_dir,
dict config )
Run sphinx-build to generate HTML output.

Returns exit code: 0 on success, 1 on failure.

Definition at line 563 of file oct_docs.py.

Here is the caller graph for this function:

◆ setup_sphinx()

Path oct.docs.oct_docs.setup_sphinx ( Path root)
Set up Sphinx configuration in the project's docs/ directory.

Uses docs/ as the Sphinx source directory directly — markdown files
already present in docs/ are included without copying.

Sphinx config files (conf.py, Makefile, make.bat) live in docs/_sphinx/
to keep the docs/ root clean.  The ``-c`` flag in ``run_sphinx_build``
points Sphinx at this configuration directory.

Returns the path to the docs directory.

Definition at line 500 of file oct_docs.py.

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ _AUTO_MARKER_MD

str oct.docs.oct_docs._AUTO_MARKER_MD = "<!-- Auto-generated by oct docs --sphinx -->"
protected

Definition at line 69 of file oct_docs.py.

◆ _AUTO_MARKER_RST

str oct.docs.oct_docs._AUTO_MARKER_RST = ".. Auto-generated by oct docs --sphinx"
protected

Definition at line 68 of file oct_docs.py.

◆ _DOCS_CLEAN_DIRS

list oct.docs.oct_docs._DOCS_CLEAN_DIRS = ["html", "doctrees", "_api", "doxygen_output"]
protected

Definition at line 827 of file oct_docs.py.

◆ _DOCS_CLEAN_FILES

list oct.docs.oct_docs._DOCS_CLEAN_FILES = ["index.rst", "dependencies.rst"]
protected

Definition at line 830 of file oct_docs.py.

◆ _DOCS_EXCLUDE_DIRS

dict oct.docs.oct_docs._DOCS_EXCLUDE_DIRS
protected
Initial value:
1= {"old", "code_reviews", "sphinx_docs", "_build",
2 "_static", "_templates", "_autosummary", "_sphinx",
3 "_api", "html", "doctrees", "doxygen_output",
4 "doxygen_work_dir"}

Definition at line 98 of file oct_docs.py.

◆ _MAX_PACKAGE_DEPTH

int oct.docs.oct_docs._MAX_PACKAGE_DEPTH = 10
protected

Definition at line 272 of file oct_docs.py.

◆ _PRIORITY_DOCS

list oct.docs.oct_docs._PRIORITY_DOCS
protected
Initial value:
1= [
2 "README",
3 "00_Master_Option_C_Specs_Intro_",
4 "01_Master_Option_C_Specs_Core_",
5 "02_Master_Option_C_Specs_Tooling_",
6 "03_Master_Option_C_Specs_Diagnostics_",
7 "04_Master_Option_C_Specs_AI_Protocol_",
8 "05_Master_Option_C_Specs_Changelog_",
9 "ARCHITECTURE",
10 "REFERENCE",
11 "ROADMAP",
12]

Definition at line 106 of file oct_docs.py.

◆ _REQUIRED_PACKAGES

list oct.docs.oct_docs._REQUIRED_PACKAGES
protected
Initial value:
1= [
2 "sphinx",
3 "sphinx_book_theme",
4 "myst_parser",
5 "sphinxcontrib.mermaid",
6 "sphinx_copybutton",
7]

Definition at line 89 of file oct_docs.py.

◆ _STALE_DOXYFILE_MAX_AGE_SECONDS

int oct.docs.oct_docs._STALE_DOXYFILE_MAX_AGE_SECONDS = 24 * 60 * 60
protected

Definition at line 726 of file oct_docs.py.

◆ _TEMPLATES_DIR

str oct.docs.oct_docs._TEMPLATES_DIR = Path(__file__).parent.parent / "templates" / "sphinx"
protected

Definition at line 62 of file oct_docs.py.