git_brcal/src/brecal_api_client/config.py

75 lines
2.3 KiB
Python

from __future__ import annotations
import json
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Mapping, Optional, Union
from .exceptions import ClientConfigurationError
ConfigPath = Union[str, Path]
DEFAULT_BASE_URL_FALLBACK = "https://brecaldevel.bsmd-emswe.eu"
CONFIG_FILENAME = "client.json"
def _default_config_path() -> Path:
xdg = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
return (xdg / "brecal" / CONFIG_FILENAME).expanduser()
@dataclass(frozen=True)
class ClientConfig:
base_url: str
environment: Optional[str] = None
@classmethod
def from_mapping(cls, data: Mapping[str, Any]) -> "ClientConfig":
environment = data.get("environment")
base_url = data.get("base_url")
endpoints = data.get("endpoints")
if isinstance(endpoints, Mapping):
if environment and environment in endpoints:
base_url = endpoints[environment]
elif not base_url and endpoints:
# Pick the first entry as a last resort
_, base_url = next(iter(endpoints.items()))
if not base_url:
raise ClientConfigurationError(
"Client configuration requires either 'base_url' or an "
"'endpoints' mapping."
)
return cls(
base_url=str(base_url).rstrip("/"),
environment=str(environment) if environment else None,
)
@classmethod
def load(cls, path: Optional[ConfigPath] = None) -> "ClientConfig":
file_path = Path(path) if path else _default_config_path()
data = json.loads(file_path.read_text(encoding="utf-8"))
return cls.from_mapping(data)
def get_default_base_url(path: Optional[ConfigPath] = None) -> str:
"""Resolve the default base URL using env vars or ~/.config/brecal/client.json."""
env_override = os.getenv("BRECAL_BASE_URL")
if env_override:
return env_override.rstrip("/")
try:
config = ClientConfig.load(path=path)
return config.base_url
except FileNotFoundError:
return DEFAULT_BASE_URL_FALLBACK
except ClientConfigurationError:
raise
except Exception as exc:
raise ClientConfigurationError(
f"Failed to load BreCal client configuration: {exc}"
) from exc