from __future__ import annotations from pathlib import Path import yaml from .paths import presets_root import re def load_yaml(path: Path) -> dict: if not path.exists(): return {} return yaml.safe_load(path.read_text(encoding="utf-8")) or {} def deep_merge(a: dict, b: dict) -> dict: out = dict(a) for k, v in (b or {}).items(): if isinstance(v, dict) and isinstance(out.get(k), dict): out[k] = deep_merge(out[k], v) else: out[k] = v return out def load_customer_preset(repo_root: Path, customer_key: str) -> dict: key = customer_key.strip().lower() if not re.fullmatch(r"[a-z0-9_-]+", key): raise ValueError("Customer key must contain only letters, digits, _ or -") local = presets_root(repo_root) if (local / "customers" / f"{key}.yaml").is_file(): return load_yaml(local / "customers" / f"{key}.yaml") # Prefer per-customer file file_preset = repo_root / "presets" / "customers" / f"{key}.yaml" if file_preset.exists(): return load_yaml(file_preset) # Fallback to shared customers.yaml shared = load_yaml(repo_root / "presets" / "customers.yaml").get("customers", {}) return shared.get(key, {})