import os import json from types import SimpleNamespace from typing import Any, Dict class EnvConfigLoader: """ Carrega variáveis de ambiente com um prefixo comum e permite acessá-las diretamente via ponto, sem agrupar subníveis. """ def __init__(self, prefix: str): self.prefix = prefix.upper().strip("_") self._data = self._load() # transforma o dicionário em objeto (sem agrupar) self._object = SimpleNamespace(**self._data) # ------------------------------- # Conversão de valores automáticos # ------------------------------- def _convert_value(self, value: str) -> Any: value = value.strip() # Boolean if value.lower() in ["true", "false"]: return value.lower() == "true" # Integer if value.isdigit(): return int(value) # Float try: return float(value) except ValueError: pass # JSON (dicts, arrays) try: return json.loads(value) except Exception: pass return value # ------------------------------- # Carrega variáveis do ambiente # ------------------------------- def _load(self) -> Dict[str, Any]: prefix_match = f"{self.prefix}_" data = {} for key, value in os.environ.items(): if key.startswith(prefix_match): subkey = key[len(prefix_match) :].lower() # tudo em minúsculo data[subkey] = self._convert_value(value) return data # ------------------------------- # Permite acesso direto via ponto # ------------------------------- def __getattr__(self, name: str) -> Any: if hasattr(self._object, name): return getattr(self._object, name) raise AttributeError(f"'{self.prefix}' não contém '{name}'") # ------------------------------- # Acesso via dicionário # ------------------------------- def __getitem__(self, key: str) -> Any: return getattr(self._object, key.lower(), None) def __repr__(self) -> str: return json.dumps(self._data, indent=2, ensure_ascii=False)