from functools import lru_cache from pathlib import Path from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_prefix="TUXDMX_", env_file=".env", extra="ignore") app_name: str = "TuxDMX" env: str = "development" secret_key: str = "development-secret-change-me" database_url: str = "sqlite+aiosqlite:///./data/tuxdmx.db" simulator_enabled: bool = True allow_local_docs: bool = True log_level: str = "INFO" target_fps: int = Field(default=30, ge=1, le=44) ola_universe: int = Field(default=1, ge=1, le=63999) ola_output_port: str | None = None ola_send_timeout_ms: int = Field(default=1000, ge=100, le=10000) system_control_enabled: bool = True system_service_name: str = "tuxdmx.service" system_control_helper: str = "/opt/tuxdmx/scripts/control-system.sh" frontend_dist: Path = Path("frontend/dist") data_dir: Path = Path("data") backup_dir: Path = Path("data/backups") fixture_cache_dir: Path = Path("data/fixtures") diagnostics_dir: Path = Path("data/diagnostics") uploads_dir: Path = Path("data/uploads") log_dir: Path = Path("data") def resolve_path(path: Path) -> Path: return path.expanduser().resolve(strict=False) @lru_cache(maxsize=1) def get_settings() -> Settings: settings = Settings() settings.frontend_dist = resolve_path(settings.frontend_dist) settings.data_dir = resolve_path(settings.data_dir) settings.backup_dir = resolve_path(settings.backup_dir) settings.fixture_cache_dir = resolve_path(settings.fixture_cache_dir) settings.diagnostics_dir = resolve_path(settings.diagnostics_dir) settings.uploads_dir = resolve_path(settings.uploads_dir) settings.log_dir = resolve_path(settings.log_dir) settings.data_dir.mkdir(parents=True, exist_ok=True) settings.backup_dir.mkdir(parents=True, exist_ok=True) settings.fixture_cache_dir.mkdir(parents=True, exist_ok=True) settings.diagnostics_dir.mkdir(parents=True, exist_ok=True) settings.uploads_dir.mkdir(parents=True, exist_ok=True) settings.log_dir.mkdir(parents=True, exist_ok=True) return settings def get_alembic_database_url(database_url: str) -> str: if database_url.startswith("sqlite+aiosqlite:///"): return database_url.replace("sqlite+aiosqlite:///", "sqlite:///", 1) return database_url