""" This module defines the NavSpec class, which represents the user's intent for documentation navigation as defined in a YAML specification (usually docforge.nav.yml). """ from pathlib import Path from typing import Dict, List, Optional import yaml class NavSpec: """ Parsed representation of the docforge navigation specification file. Attributes: home: Path to the home document (e.g., 'index.md'). groups: Mapping of group titles to lists of path patterns/globs. """ def __init__( self, home: Optional[str], groups: Dict[str, List[str]], ) -> None: """ Initialize a NavSpec. Args: home: The path to the home document. groups: A mapping of group names to lists of path patterns (globs). """ self.home = home self.groups = groups @classmethod def load(cls, path: Path) -> "NavSpec": """ Load a NavSpec from a YAML file. Args: path: The filesystem path to the YAML file. Returns: A NavSpec instance. Raises: FileNotFoundError: If the path does not exist. ValueError: If the file content is not a valid NavSpec mapping. """ if not path.exists(): raise FileNotFoundError(path) data = yaml.safe_load(path.read_text(encoding="utf-8")) if not isinstance(data, dict): raise ValueError("Nav spec must be a mapping") home = data.get("home") groups = data.get("groups", {}) if home is not None and not isinstance(home, str): raise ValueError("home must be a string") if not isinstance(groups, dict): raise ValueError("groups must be a mapping") for key, value in groups.items(): if not isinstance(key, str): raise ValueError("group names must be strings") if not isinstance(value, list) or not all( isinstance(v, str) for v in value ): raise ValueError(f"group '{key}' must be a list of strings") return cls(home=home, groups=groups) def all_patterns(self) -> List[str]: """ Get all path patterns referenced in the specification. Returns: A list of all patterns (home plus all groups). """ patterns: List[str] = [] if self.home: patterns.append(self.home) for items in self.groups.values(): patterns.extend(items) return patterns def load_nav_spec(path: Path) -> NavSpec: """ Utility function to load a NavSpec from a file. Args: path: Path to the navigation specification file. Returns: A loaded NavSpec instance. """ if not path.exists(): raise FileNotFoundError(path) data = yaml.safe_load(path.read_text(encoding="utf-8")) if not isinstance(data, dict): raise ValueError("Nav spec must be a YAML mapping") return NavSpec( home=data.get("home"), groups=data.get("groups", {}), )