"""Zero-dependency .env loader. The gallery/run scripts read credentials (JELLYFIN_URL, JELLYFIN_API_KEY, TMDB_API_KEY) from os.environ, but nothing populated os.environ from the project's .env file — so the keys only worked if you'd manually `set -a; source .env`. This loads .env into os.environ on import, without pulling in python-dotenv. Import this module early (before argparse reads os.environ defaults) so the .env values are available as defaults. """ import os from pathlib import Path # Walk up from this file to find the project root's .env (scripts/ is one # level down from the repo root). _DEFAULT_ENV = Path(__file__).resolve().parent.parent / ".env" def load_env(path: Path | str = _DEFAULT_ENV, *, override: bool = False) -> None: """Parse a .env file into os.environ. Lines are KEY=VALUE; blank lines and #-comments are ignored, surrounding whitespace is stripped, and a single layer of matching quotes around the value is removed. Existing os.environ entries win unless override=True, so an explicitly exported var (or one set on the command line) takes precedence over the file. """ path = Path(path) if not path.is_file(): return for raw in path.read_text().splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue key, _, value = line.partition("=") key = key.strip() value = value.strip() if len(value) >= 2 and value[0] == value[-1] and value[0] in ("'", '"'): value = value[1:-1] if not key: continue if override or key not in os.environ: os.environ[key] = value # Load on import so `os.environ.get(...)` argparse defaults see .env values. load_env()