from __future__ import annotations from typing import Annotated from pydantic import BaseModel, SecretStr from pydantic.functional_validators import model_validator from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, ) class HttpSettings(BaseModel): host: str = "127.0.0.1" port: int = 8080 cert: str | None = None class DatabaseSettings(BaseModel): name: str host: str port: int driver: str = "postgresql+psycopg" user: str password: Annotated[SecretStr, check_user_password] class CacheSettings(BaseModel): enable: bool = False host: str = "127.0.0.1" port: int = 6379 user: str | None = None password: Annotated[SecretStr | None, check_user_password] = None @model_validator(mode="after") def check_user_password(self) -> DatabaseSettings | CacheSettings: if self.user is not None and self.password is None: raise ValueError("user is set, password shall be set too.") if self.password is not None and self.user is None: raise ValueError("password is set, user shall be set too.") return self class TracingSettings(BaseModel): enable: bool = False class Settings(BaseSettings): app_name: str idfm_api_key: SecretStr clear_static_data: bool http: HttpSettings db: DatabaseSettings cache: CacheSettings tracing: TracingSettings model_config = SettingsConfigDict(env_prefix="CER__", env_nested_delimiter="__") @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return env_settings, init_settings, file_secret_settings