""" config/loader.py — загрузка сервисов и глобальные конфигурационные переменные. Поддержка нескольких стендов: Переменная POLYGON_STANDS задаёт список стендов в формате: имя:путь,имя:путь,... Например: POLYGON_STANDS=stand1:services/stand1,stand2:services/stand2,stand3:services/stand3 По умолчанию — один стенд "default" из папки services/. Переменные модуля: VERSION — str, версия полигона STANDS — {stand_id: {"SERVICES": ..., "OPS_INDEX": ...}} DELAY — float, задержка операции DEFAULT_STAND — str, ID стенда по умолчанию """ import os import yaml _YAML_EXTS = (".yaml", ".yml") _DEFAULT_SERVICES_DIR = "services" def _load_one(services_dir): """Загружает YAML из одной директории → (services, ops_index).""" if not os.path.isdir(services_dir): raise FileNotFoundError(f"Services directory not found: {services_dir}") services = {} ops_index = {} for fname in sorted(os.listdir(services_dir)): if not fname.lower().endswith(_YAML_EXTS): continue path = os.path.join(services_dir, fname) with open(path, "r", encoding="utf-8") as f: cfg = yaml.safe_load(f) if not cfg: continue svc_id = cfg["service_id"] services[svc_id] = cfg for op in cfg.get("operations", []): ops_index[op["svcOperationId"]] = cfg return services, ops_index def _parse_stands(raw): """Парсит POLYGON_STANDS → {stand_id: services_dir}.""" stands = {} for pair in raw.split(","): pair = pair.strip() if ":" not in pair: continue name, path = pair.split(":", 1) stands[name.strip()] = path.strip() return stands # ── Загрузка ── _raw = os.getenv("POLYGON_STANDS", "") if _raw: _stand_dirs = _parse_stands(_raw) else: _stand_dirs = {"default": _DEFAULT_SERVICES_DIR} STANDS = {} for _sid, _sdir in _stand_dirs.items(): _svc, _ops = _load_one(_sdir) STANDS[_sid] = {"SERVICES": _svc, "OPS_INDEX": _ops} DEFAULT_STAND = next(iter(STANDS.keys())) # Для обратной совместимости (код который не использует g.stand_id) _DF = STANDS[DEFAULT_STAND] SERVICES = _DF["SERVICES"] OPS_INDEX = _DF["OPS_INDEX"] DELAY = float(os.getenv("MOCK_OP_DELAY", "0.1")) VERSION = "0.5.2" def get_services(stand_id): """SERVICES для конкретного стенда.""" return STANDS[stand_id]["SERVICES"] def get_ops_index(stand_id): """OPS_INDEX для конкретного стенда.""" return STANDS[stand_id]["OPS_INDEX"] def list_stands(): """Список ID всех стендов.""" return list(STANDS.keys())