import logging from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict logger = logging.getLogger(__name__) class Settings(BaseSettings): model_config = SettingsConfigDict(env_file=".env") secret_key: str sqlalchemy_database_url: str = "sqlite:///./gatekeeper.db" mqtt_host: str = "localhost" mqtt_port: int = 1883 mock: bool = True alembic_config: str = "./alembic.ini" disable_cards: bool = False mifare_app_master_key: str | None = None mifare_acl_read_base_key: str | None = None mifare_acl_write_base_key: str | None = None @lru_cache(1) def _create_settings(): settings = Settings() if not settings.disable_cards: missing = [ name.upper() for name in ( "mifare_app_master_key", "mifare_acl_read_base_key", "mifare_acl_write_base_key", ) if not getattr(settings, name) ] if missing: logger.critical( "Missing environment variable for scanner start: %s" "Card scanner and related funcionality is disabled!", ", ".join(missing), ) settings.disable_cards = True return settings class _SettingsProxy: _instance: Settings | None = None def _load(self) -> Settings: if self._instance is None: self._instance = _create_settings() return self._instance def __getattr__(self, name: str): return getattr(self._load(), name) def __setattr__(self, name: str, value): if name == "_instance": super().__setattr__(name, value) else: setattr(self._load(), name, value) def reset(self) -> None: self._instance = None _create_settings.cache_clear() settings = _SettingsProxy()