import os from functools import lru_cache from pathlib import Path from typing import Any import yaml from dotenv import load_dotenv load_dotenv() # Maps environment variable names to nested YAML key paths _ENV_OVERRIDES: dict[str, list[str]] = { "ZHIPUAI_API_KEY": ["zhipuai", "api_key"], "STORAGE_ACCESS_KEY": ["storage", "access_key"], "STORAGE_SECRET_KEY": ["storage", "secret_key"], "STORAGE_ENDPOINT": ["storage", "endpoint"], "BACKEND_CALLBACK_URL": ["backend", "callback_url"], "LOG_LEVEL": ["server", "log_level"], "MAX_VIDEO_SIZE_MB": ["video", "max_file_size_mb"], } _CONFIG_PATH = Path(__file__).parent.parent.parent / "config.yaml" def _set_nested(cfg: dict, keys: list[str], value: Any) -> None: for key in keys[:-1]: cfg = cfg.setdefault(key, {}) # Coerce numeric env vars try: value = int(value) except (TypeError, ValueError): pass cfg[keys[-1]] = value @lru_cache(maxsize=1) def get_config() -> dict: with open(_CONFIG_PATH, "r", encoding="utf-8") as f: cfg: dict = yaml.safe_load(f) for env_var, key_path in _ENV_OVERRIDES.items(): value = os.environ.get(env_var) if value is not None: _set_nested(cfg, key_path, value) return cfg