Move secrets and URLs out of source into .env
All checks were successful
lint / ruff (push) Successful in 45s

Adds a stdlib-only loader (src/lib/env.py) that walks up to find the
nearest .env. display.py and notebooks/_helpers.py now `require()` the
config values; wifi-check.sh sources .env to derive its probe host. The
.env file is gitignored; .env.example documents the required keys. The
existing tokens are still present in git history and will be scrubbed
in the next commit; rotate them after the rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andras Schmelczer 2026-05-03 11:22:54 +01:00
parent 8609b4a884
commit 90b692da39
8 changed files with 69 additions and 19 deletions

View file

@ -1,7 +1,6 @@
#!/usr/bin/env python3
import argparse
import fcntl
import os
import sys
from datetime import datetime
from pathlib import Path
@ -10,6 +9,7 @@ from PIL import Image
sys.path.append(str(Path(__file__).parent / "lib"))
from crop import face_aware_crop
from env import load_env, require
from homeassistant import HomeAssistantClient
from immich import ImmichClient, get_random_photo_from_album, get_random_photo_of_people
from overlay import format_age, format_location
@ -18,14 +18,11 @@ from overlay import format_age, format_location
# GPIO pins at import time, so two overlapping invocations would both crash
# on "GPIO busy" before reaching the flock below.
IMMICH_URL = os.environ.get("IMMICH_URL", "https://immich.example.com")
IMMICH_API_KEY = os.environ.get("IMMICH_API_KEY", "REDACTED_IMMICH_API_KEY")
HA_URL = os.environ.get("HA_URL", "https://homeassistant.example.com")
HA_TOKEN = os.environ.get(
"HA_TOKEN",
"REDACTED_HA_TOKEN",
)
load_env()
IMMICH_URL = require("IMMICH_URL")
IMMICH_API_KEY = require("IMMICH_API_KEY")
HA_URL = require("HA_URL")
HA_TOKEN = require("HA_TOKEN")
HA_PRESENCE = {"Andras": "person.andras", "Ruby": "person.ruby"}

43
src/lib/env.py Normal file
View file

@ -0,0 +1,43 @@
"""Minimal stdlib .env loader.
Reads KEY=VALUE lines from a .env file (project root by default) into
`os.environ`, leaving already-set variables untouched.
"""
from __future__ import annotations
import os
from pathlib import Path
def _find_env() -> Path | None:
# Walk up from this file and from cwd; first .env wins. Handles both the
# dev layout (src/lib/env.py with .env at repo root) and the Pi layout
# (lib/env.py with .env at ~/frame/.env).
for start in (Path(__file__).resolve().parent, Path.cwd().resolve()):
for d in (start, *start.parents):
candidate = d / ".env"
if candidate.is_file():
return candidate
return None
def load_env(path: Path | None = None) -> None:
env_path = path or _find_env()
if env_path is None or not env_path.exists():
return
for raw in env_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().strip('"').strip("'")
os.environ.setdefault(key, value)
def require(key: str) -> str:
value = os.environ.get(key)
if not value:
raise RuntimeError(f"missing required env var: {key} (set it in .env or the environment)")
return value

View file

@ -4,7 +4,13 @@
# brcmfmac chip on the Pi Zero 2W.
CONNECTION="netplan-wlan0-HiddenPlace"
PROBE_HOST="homeassistant.example.com"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck disable=SC1091
[ -f "$SCRIPT_DIR/.env" ] && set -a && . "$SCRIPT_DIR/.env" && set +a
PROBE_HOST="${HA_URL#http*://}"
PROBE_HOST="${PROBE_HOST%%/*}"
: "${PROBE_HOST:?HA_URL must be set in .env}"
probe() {
ping -c 1 -W 5 192.168.0.1 >/dev/null 2>&1 \