docs (naas_abi_cli.cli.docs)
What it is
CLI and helper utilities to:
- Scan a Python source tree for
.pyfiles (optionally including tests) - Determine which corresponding Markdown reference docs are missing or outdated
- Optionally regenerate stale docs in parallel using
DocumentationAgent
Public API
Data types
-
RegenerationReason = Literal["missing", "outdated"]
Reason a doc file should be regenerated. -
@dataclass DocSyncItem
Represents a doc sync action:source_file: Path— Python source filetarget_file: Path— expected/generated Markdown filereason: RegenerationReason—"missing"or"outdated"
File discovery and staleness
-
iter_python_files(source_root: Path, include_tests: bool = False) -> list[Path]
Recursively lists Python files undersource_root, skipping:- directories:
.git,.venv,venv,__pycache__,.mypy_cache,.pytest_cache,node_modules __init__.py- test files unless
include_tests=True(test_*.pyor*_test.py)
- directories:
-
target_markdown_path(source_file: Path, source_root: Path, output_root: Path) -> Path
Maps a source file to its expected Markdown path underoutput_root, preserving relative path and changing suffix to.md. -
needs_regeneration(source_file: Path, target_file: Path) -> tuple[bool, RegenerationReason | None]
Determines whether regeneration is needed:"missing"iftarget_filedoes not exist"outdated"iftarget_filemtime is older thansource_filemtime- otherwise returns
(False, None)
-
collect_docs_to_regenerate(source_root: Path, output_root: Path, include_tests: bool = False) -> list[DocSyncItem]
Produces a list ofDocSyncItemfor all missing/outdated docs.
API key resolution
resolve_openai_api_key() -> str | None
ResolvesOPENAI_API_KEYby:- Checking environment variable
OPENAI_API_KEY - Falling back to reading
OPENAI_API_KEYfrom a local.envfile (supportsexport KEY=..., comments, and quoted values)
If found in.env, it also setsos.environ["OPENAI_API_KEY"].
- Checking environment variable
Documentation generation
generate_documentation_for_items(stale_docs: list[DocSyncItem], model: str, workers: int = 10) -> int
Generates docs for eachDocSyncItemusingDocumentationAgent(model=model).generate_and_write(...).- Runs sequentially if effective worker count is 1; otherwise uses
ThreadPoolExecutor. - Raises
ValueErrorifworkers < 1. - Raises
RuntimeErrorif one or more files fail (includes up to 10 error lines). - Returns number of successfully generated files.
- Runs sequentially if effective worker count is 1; otherwise uses
CLI
-
docs()(Click group:docs)
“Documentation tooling for ABI projects.” -
sync_docs(...)(Click command:docs sync)
Detects stale docs; optionally generates them.Options:
--source(dir, defaultlibs/naas-abi-core/naas_abi_core)--output(dir, defaultdocs/reference)--include-tests--fail-on-stale(exit non-zero if stale docs detected and not generating)--generate(generate/update stale docs)--model(defaultgpt-5.2)--workers(min 1, default 10)
Configuration/Dependencies
- Depends on
clickfor CLI. - Depends on
naas_abi_cli.docs_builder.DocumentationAgentfor generation. --generaterequiresOPENAI_API_KEY:- either exported in the environment, or
- present in a local
.envfile asOPENAI_API_KEY=...(optionallyexport ...and/or quoted).
Usage
CLI: check for stale docs
python -m naas_abi_cli.cli.docs docs sync --source libs/naas-abi-core/naas_abi_core --output docs/referenceCLI: generate stale docs
export OPENAI_API_KEY="your-key"
python -m naas_abi_cli.cli.docs docs sync --generate --model gpt-5.2 --workers 10Python: list stale docs and generate
from pathlib import Path
from naas_abi_cli.cli.docs import (
collect_docs_to_regenerate,
generate_documentation_for_items,
resolve_openai_api_key,
)
stale = collect_docs_to_regenerate(
source_root=Path("libs/naas-abi-core/naas_abi_core"),
output_root=Path("docs/reference"),
)
if stale and resolve_openai_api_key():
generate_documentation_for_items(stale_docs=stale, model="gpt-5.2", workers=4)Caveats
- Test file detection is name-based only (
test_*.pyor*_test.py). - Staleness is based solely on filesystem modification times (mtime).
- On parallel generation, failures are aggregated and raised as a single
RuntimeError(only first 10 errors included).