"""Backend configuration using pydantic-settings. Reads from environment variables and .env file automatically. Uses a flat settings model so that standard env vars like SSH_HOST, JELLYFIN_URL etc. are picked up directly without nested-model complications. """ from __future__ import annotations from functools import lru_cache from pathlib import Path from pydantic_settings import BaseSettings class Settings(BaseSettings): """Flat application settings read from env vars / .env file.""" # Jellyfin jellyfin_url: str = "" jellyfin_api_key: str = "" jellyfin_user_id: str = "" # SSH ssh_host: str = "" ssh_username: str = "" ssh_port: int = 22 ssh_key_filename: str = str(Path.home() / ".ssh" / "id_rsa") ssh_password: str = "" # Remote paths remote_media_root: str = "" remote_path_prefix: str = "" # Derived convenience @property def media_root(self) -> str: return self.remote_media_root or "" @property def path_prefix(self) -> str: return self.remote_path_prefix or "" model_config = {"env_file": ".env", "env_file_encoding": "utf-8", "extra": "ignore"} def _find_env_file() -> str | None: """Look for .env in CWD, then parent directories up to the repo root.""" current = Path.cwd() for directory in [current, *current.parents]: candidate = directory / ".env" if candidate.is_file(): return str(candidate) # Stop at repo root (has .git) if (directory / ".git").exists(): break return None @lru_cache def get_settings() -> Settings: """Return a cached Settings instance.""" env_file = _find_env_file() if env_file: return Settings(_env_file=env_file) return Settings()