"""Load global config.""" import os from pathlib import Path from typing import Union from dotenv import load_dotenv from yaml import load from jarvis_core.util import Singleton try: from yaml import CLoader as Loader except ImportError: from yaml import Loader DEFAULT_YAML_PATH = Path("config.yaml") DEFAULT_ENV_PATH = Path(".env") class Config(Singleton): REQUIRED = [] OPTIONAL = {} ENV_REQUIRED = [] ENV_OPTIONAL = {} @classmethod def _process_env(cls, **kwargs) -> dict: """Process environment variables into standard arguments""" @classmethod def from_env(cls, filepath: Union[Path, str] = DEFAULT_ENV_PATH) -> "Config": """Loag the environment config.""" if inst := cls.__dict__.get("inst"): return inst load_dotenv(filepath) data = {} for item in cls.ENV_REQUIRED: data[item] = os.environ.get(item, None) for item, default in cls.ENV_OPTIONAL.items(): data[item] = os.environ.get(item, default) data = cls._process_env(**data) return cls(**data) @classmethod def from_yaml(cls, filepath: Union[Path, str] = DEFAULT_YAML_PATH) -> "Config": """Load the yaml config file.""" if inst := cls.__dict__.get("inst"): return inst if isinstance(filepath, str): filepath = Path(filepath) with filepath.open() as f: raw = f.read() y = load(raw, Loader=Loader) return cls(**y) @classmethod def load(cls) -> "Config": if DEFAULT_ENV_PATH.exists(): return cls.from_env() return cls.from_yaml() @classmethod def reload(cls) -> bool: """Reload the config.""" return cls.__dict__.pop("inst", None) is None