# ----------------------------------------------------------------------------- # Description: Technology manifest loading and fallback helpers for routing layers and cross-section defaults. # Inside functions: technology_manifest_path, read_technology_manifest # Developer : Qin Yue @ 2026 # Organization : OptiHK Limited # ----------------------------------------------------------------------------- import os import yaml class TechnologyManifestError(Exception): """Exception raised when a technology manifest cannot be found or parsed.""" pass def technology_manifest_path(pdks_root: str, foundry: str, technology: str) -> str: """Build the expected path to a foundry/technology manifest YAML file.""" base = os.path.abspath(pdks_root) path = os.path.abspath(os.path.join(base, foundry, technology, "technology.yml")) # Keep user-provided foundry/technology names from escaping the configured # PDK root. if not path.startswith(base + os.sep): raise TechnologyManifestError("Invalid technology path") return path def read_technology_manifest(pdks_root: str, foundry: str, technology: str) -> dict: """Load and validate the active technology manifest for the frontend.""" path = technology_manifest_path(pdks_root, foundry, technology) if not os.path.exists(path): raise TechnologyManifestError("technology manifest not generated; run mxpic_forge technology export workflow") with open(path, "r", encoding="utf-8") as file: manifest = yaml.safe_load(file) or {} # The frontend route editor depends on both xsection definitions and global # defaults being present before it can safely style or build links. if not isinstance(manifest.get("xsections"), dict): raise TechnologyManifestError("technology manifest is missing xsections") if not isinstance(manifest.get("defaults"), dict): raise TechnologyManifestError("technology manifest is missing defaults") return manifest