"""Oracle 11.2 thick 连接。环境变量与 rpa_oms 相同。""" from __future__ import annotations import os from pathlib import Path DEAL_USER_NAME = "rpa-select" _client_ready = False _PROJECT_ROOT = Path(__file__).resolve().parent _OMS_ENV = _PROJECT_ROOT.parent / "rpa_oms" / ".env" class RepoUnavailable(Exception): def __init__(self, message: str = "数据库不可用"): self.message = message super().__init__(message) def load_runtime_env(paths: list[Path] | None = None) -> None: """先读选品 .env,空缺再补 rpa_oms/.env。不覆盖已有非空环境变量。""" env_paths = paths if paths is not None else [_PROJECT_ROOT / ".env", _OMS_ENV] for path in env_paths: _fill_env(path) def _fill_env(path: Path) -> None: if not path.is_file(): return for raw in path.read_text(encoding="utf-8").splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue key, _, value = line.partition("=") key = key.strip() value = value.strip() if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}: value = value[1:-1] if not key or not value: continue current = os.environ.get(key, "") if not current: os.environ[key] = value def oracle_dsn() -> tuple[str, str, str]: user = os.getenv("RPA_ORACLE_USER", "") password = os.getenv("RPA_ORACLE_PASSWORD", "") host = os.getenv("RPA_ORACLE_HOST", "") if not user or not password or not host: raise RepoUnavailable("未配置 RPA_ORACLE_HOST / RPA_ORACLE_USER / RPA_ORACLE_PASSWORD") port = os.getenv("RPA_ORACLE_PORT", "1521") service = os.getenv("RPA_ORACLE_SERVICE", "rpa") return user, password, f"{host}:{port}/{service}" def connect_from_env(): user, password, dsn = oracle_dsn() _ensure_client() import oracledb return oracledb.connect(user=user, password=password, dsn=dsn) def _ensure_client() -> None: global _client_ready if _client_ready: return import oracledb if os.getenv("RPA_ORACLE_THICK", "1") == "1": lib_dir = os.getenv("RPA_ORACLE_CLIENT_LIB", "") kwargs = {"lib_dir": lib_dir} if lib_dir else {} oracledb.init_oracle_client(**kwargs) _client_ready = True