"""配置加载器 —— 读取 TOML 文件并注入 os.environ。 加载顺序(后覆盖前): 1. app.toml — 基础配置 2. app.{APP_ENV}.toml — 环境差异 3. app.ai.toml — AI 专用(最高 TOML 优先级) 4. 已有环境变量 — 不覆盖(最高优先级) """ from __future__ import annotations import os import sys from pathlib import Path _ROOT = Path(__file__).resolve().parents[2] def _find_project_root() -> Path: """查找项目根目录(包含 app.toml 的目录)。""" return _ROOT def _load_toml(path: Path) -> dict: """读取 TOML 文件并展平 [SECTION].KEY → SECTION_KEY。""" try: import tomllib except ImportError: import tomli as tomllib with open(path, "rb") as fh: data = tomllib.load(fh) flat: dict[str, str] = {} for section, values in data.items(): if not isinstance(values, dict): continue for key, val in values.items(): env_key = f"{section.upper()}_{key.upper()}" if isinstance(val, list): flat[env_key] = ",".join(str(v) for v in val) elif isinstance(val, bool): flat[env_key] = str(val).lower() elif val is not None: flat[env_key] = str(val) return flat def load_config() -> None: """加载所有 TOML 配置到 os.environ(不覆盖已有环境变量)。""" root = _find_project_root() env = os.getenv("APP_ENV", "development") toml_files = [ root / "app.toml", root / f"app.{env}.toml", root / "app.ai.toml", ] for toml_path in toml_files: if not toml_path.exists(): continue for key, value in _load_toml(toml_path).items(): os.environ.setdefault(key, value) # 确保项目根在 sys.path 中 if str(root) not in sys.path: sys.path.insert(0, str(root))