Files
doc-forge/docforge/nav/resolver.py
Vishesh 'ironeagle' Bangotra 582b6809a0 docs: bring docforge docstrings and wiki to GSDFC standard
- fix GSDFC spec contradictions in __init__ docstring (parenthesized types, fenced-block rule) and sync generated README
- rewrite docstrings across loaders, models, nav, servers, renderers, cli; sync .pyi stubs
- add pydoclint (google style) gate to dev extras and pyproject config
- fix mcp nav resources doc:// -> docs://
- refresh docs/lib and docs/mcp, drop stale docforge/ duplicate group
- update wiki pages and add GSDFC + MCP guides under 05_development
2026-09-12 13:12:51 +05:30

151 lines
4.2 KiB
Python

"""
Navigation resolution utilities.
This module resolves a ``NavSpec`` against the filesystem by expanding glob
patterns and validating that referenced documentation files exist.
---
Notes:
- Glob resolution is recursive and returns paths in sorted order.
- Unmatched patterns raise ``FileNotFoundError`` to fail fast on typos.
---
"""
import glob
from collections.abc import Iterable
from pathlib import Path
from docforge.nav.spec import NavSpec
class ResolvedNav:
"""
Resolved navigation structure.
A ``ResolvedNav`` represents navigation data after glob patterns have been
expanded and paths validated against the filesystem.
Attributes:
home: Relative path to the documentation home page.
groups: Mapping of navigation group titles to lists of resolved
documentation file paths.
"""
def __init__(
self,
home: str | None,
groups: dict[str, list[Path]],
docs_root: Path | None = None,
) -> None:
"""
Initialize a ResolvedNav instance.
Args:
home (str | None):
Relative path to the home page within the documentation root.
groups (dict[str, list[Path]]):
Mapping of group titles to resolved documentation file paths.
docs_root (Path | None):
Root directory of the documentation source files.
"""
self.home = home
self.groups = groups
self._docs_root = docs_root
def all_files(self) -> Iterable[Path]:
"""
Iterate over all files referenced by the navigation structure.
Yields:
Path:
A documentation file referenced by the navigation, including
the home page when defined.
Raises:
RuntimeError: If the home page is defined but the documentation
root is not available for resolution.
"""
if self.home:
if self._docs_root is None:
raise RuntimeError("docs_root is required to resolve home path")
yield self._docs_root / self.home
for paths in self.groups.values():
yield from paths
def resolve_nav(
spec: NavSpec,
docs_root: Path,
) -> ResolvedNav:
"""
Resolve a navigation specification against the filesystem.
The function expands glob patterns defined in a ``NavSpec`` and verifies
that referenced documentation files exist within the documentation root.
Args:
spec (NavSpec):
Navigation specification describing documentation layout.
docs_root (Path):
Root directory containing documentation Markdown files.
Returns:
ResolvedNav:
A `ResolvedNav` instance containing validated navigation paths.
Raises:
FileNotFoundError: If the documentation root does not exist or a
navigation pattern does not match any files.
"""
if not docs_root.exists():
raise FileNotFoundError(docs_root)
def resolve_pattern(pattern: str) -> list[Path]:
"""
Resolve a glob pattern relative to the documentation root.
Args:
pattern (str):
Glob pattern used to match documentation files.
Returns:
list[Path]:
A sorted list of matching `Path` objects.
Raises:
FileNotFoundError: If the pattern does not match any files.
"""
full = docs_root / pattern
matches = sorted(Path(p) for p in glob.glob(str(full), recursive=True))
if not matches:
raise FileNotFoundError(pattern)
return matches
# Resolve home page
home: str | None = None
if spec.home:
home_path = docs_root / spec.home
if not home_path.exists():
raise FileNotFoundError(spec.home)
home = spec.home
# Resolve navigation groups
resolved_groups: dict[str, list[Path]] = {}
for group, patterns in spec.groups.items():
files: list[Path] = []
for pattern in patterns:
files.extend(resolve_pattern(pattern))
resolved_groups[group] = files
return ResolvedNav(
home=home,
groups=resolved_groups,
docs_root=docs_root,
)