# ----------------------------------------------------------------------------- # Description: Build-time mxpic_router runtime dependency validation helpers. # Inside functions: ensure_router_path, require_router_stack # Developer : Qin Yue @ 2026 # Organization : OptiHK Limited # ----------------------------------------------------------------------------- import importlib import os import sys from dataclasses import dataclass, field from typing import List @dataclass class RouterStackStatus: """Summary of the router stack checks completed for a build action.""" ok: bool router_root: str checked: List[str] = field(default_factory=list) class RouterStackUnavailable(RuntimeError): """Raised when a build action needs the external router stack but it is absent.""" pass def ensure_router_path() -> str: """Add the sibling mxpic_router checkout to import resolution when present.""" router_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "mxpic_router")) if os.path.isdir(router_root) and router_root not in sys.path: sys.path.insert(0, router_root) return router_root def require_router_stack(require_gdstk: bool = False) -> RouterStackStatus: """Validate the runtime stack required for build-time router actions.""" router_root = ensure_router_path() checked = [] missing = [] try: importlib.import_module("mxpic_router") checked.append("mxpic_router") except Exception as exc: missing.append(f"mxpic_router: {exc}") try: importlib.import_module("nazca") checked.append("nazca") except Exception as exc: missing.append(f"nazca: {exc}") if require_gdstk: try: importlib.import_module("gdstk") checked.append("gdstk") except Exception as exc: missing.append(f"gdstk: {exc}") try: router_builder = importlib.import_module("mxpic_router.builder") route_factory = getattr(router_builder, "_import_route_backend") route_backend = route_factory() checked.append(getattr(route_backend, "backend_name", "route backend")) except Exception as exc: missing.append(f"route backend: {exc}") if missing: details = "; ".join(missing) raise RouterStackUnavailable( "Required mxpic_router runtime stack is unavailable. " "Build actions require mxpic_router, Nazca, and either mxpic_forge Route " f"or the Nazca Interconnect fallback. gdstk is also required for SVG preview generation. Details: {details}" ) return RouterStackStatus(ok=True, router_root=router_root, checked=checked)