from babel.support import LazyProxy from pydantic import computed_field, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict from typing import Literal, Self import warnings class Config(BaseSettings): model_config = SettingsConfigDict( env_file = ".env", env_ignore_empty = True, extra = "ignore" ) SECRET_KEY: str = "changethis" ENVIRONMENT: Literal["local", "staging", "production"] = "local" DB_NAME: str = "app" DB_HOST: str = "db" DB_PORT: int = 5432 DB_USER: str = "app" DB_PASSWORD: str = "changethis" @computed_field @property def DATABASE_URI(self) -> str: return f"postgresql+asyncpg://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}" DOMAIN: str @computed_field @property def API_DOMAIN(self) -> str: if self.ENVIRONMENT == "local": return self.DOMAIN return f'api.{self.DOMAIN}' @computed_field @property def API_URL(self) -> str: if self.USE_NGROK: return self.NGROK_URL return f"{"http" if self.ENVIRONMENT == "local" else "https"}://{self.API_DOMAIN}" API_PORT: int = 8000 TELEGRAM_BOT_TOKEN: str = "changethis" ADMIN_TELEGRAM_ID: int USE_NGROK : bool = False NGROK_AUTH_TOKEN: str = "changethis" NGROK_URL: str = "" LOG_LEVEL: str = "DEBUG" def _check_default_secret(self, var_name: str, value: str | None) -> None: if value == "changethis": message = ( f"The value of {var_name} is \"changethis\", " "for security, please change it, at least for deployments." ) if self.ENVIRONMENT == "local": warnings.warn(message, stacklevel=1) else: raise ValueError(message) @model_validator(mode="after") def _enforce_non_default_secrets(self) -> Self: self._check_default_secret("SECRET_KEY", self.SECRET_KEY) self._check_default_secret("DB_PASSWORD", self.DB_PASSWORD) self._check_default_secret("TELEGRAM_BOT_TOKEN", self.TELEGRAM_BOT_TOKEN) if self.USE_NGROK: self._check_default_secret("NGROK_AUTH_TOKEN", self.NGROK_AUTH_TOKEN) return self config = Config()