AI-Sprint-bot / core /config /settings.py
FreshPixels's picture
Create core/config/settings.py
66a185a verified
Raw
History Blame Contribute Delete
1.95 kB
from __future__ import annotations
import functools
from typing import Literal
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables.
Required variables must be present at startup.
Optional variables have sensible defaults.
No .env files are used — all values come from os.environ.
"""
model_config = SettingsConfigDict(
env_file="",
env_file_encoding="utf-8",
case_sensitive=True,
extra="ignore",
)
BOT_TOKEN: str | None = None
OPENAI_API_KEY: str | None = None
ADMIN_ID: str | None = None
ADMIN_USERNAME: str = ""
PORT: int = Field(default=7860, ge=1, le=65535)
SUPPORT_API_KEY: str = ""
YOOKASSA_SECRET_KEY: str = ""
YOOKASSA_SHOP_ID: str = ""
DATABASE_URL: str = ""
TELEGRAM_API_SERVER: str = "https://api.telegram.org"
WEBHOOK_URL: str = ""
DEFAULT_PROVIDER: Literal["openai", "claude", "gemini", "glm", "qwen"] = "openai"
LOG_LEVEL: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO"
LOG_FORMAT: Literal["json", "console"] = "json"
@property
def required_fields(self) -> dict[str, str | None]:
"""Return mapping of required field names to their current values."""
return {
"BOT_TOKEN": self.BOT_TOKEN,
"OPENAI_API_KEY": self.OPENAI_API_KEY,
"ADMIN_ID": self.ADMIN_ID,
}
@functools.lru_cache(maxsize=1)
def get_settings() -> Settings:
"""Return the cached Settings singleton.
Lazy initialization — Settings() is created only on the first call,
not at import time. This avoids import-time side effects and allows
test fixtures to override environment variables before the first call.
To reset the cache in tests, call:
get_settings.cache_clear()
"""
return Settings()