Auto-load .env; make --spotify-full force the cached path too

The live fetch was being skipped because creds never reached the process:
Env.py only read os.environ, and .env uses `export ...`, so without a prior
`source .env` the run fell to the cached branch — which then skipped on an
unchanged cache signature ("Spotify cache unchanged — skipping").

- Env.py now auto-loads a project-root .env (setdefault, so an exported value
  still wins; tolerates `export ` and quotes).
- --spotify-full now also passes force=True to ingest_spotify, so the cached
  fallback re-ingests instead of skipping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Шурупов Илья Викторович 2026-06-16 00:48:03 +03:00
parent 48bf84bcb7
commit cbb127115c
3 changed files with 29 additions and 3 deletions

23
Env.py
View file

@ -10,6 +10,29 @@ import os
from pathlib import Path
def _load_dotenv():
"""Load a project-root .env into os.environ if present, so `python main.py`
works without remembering to `source .env`. Already-set environment
variables win (setdefault), so an explicit `source .env`/export still
overrides. Supports an optional leading `export ` and quoted values."""
path = Path(__file__).with_name(".env")
if not path.exists():
return
for raw in path.read_text().splitlines():
line = raw.strip()
if not line or line.startswith("#"):
continue
if line.startswith("export "):
line = line[len("export "):]
key, sep, value = line.partition("=")
if not sep:
continue
os.environ.setdefault(key.strip(), value.strip().strip('"').strip("'"))
_load_dotenv()
def _path(env, default):
return Path(os.environ.get(env, default)).expanduser()

View file

@ -51,9 +51,12 @@ pip install -r requirements.txt
### Configure (`.env`)
```bash
cp .env.example .env # then edit and `source .env`
cp .env.example .env # then edit — it's auto-loaded (no `source` needed)
```
The project root `.env` is read automatically on startup; any variable already
exported in your shell still takes precedence.
Three things you point at your own data:
| Variable | What |

View file

@ -50,10 +50,10 @@ def run_fetch(enrich_limit=None, enrich=True, spotify_full=False, include_top=Fa
fetch_spotify_incremental(full=spotify_full, include_top=include_top)
except Exception as exc: # keep going on cached data
log.error("live fetch failed (%s); falling back to cached responses", exc)
ingest_spotify(include_top=include_top)
ingest_spotify(include_top=include_top, force=spotify_full)
else:
log.info("no SPOTIFY_CLIENT_ID/SECRET -> using cached responses")
ingest_spotify(include_top=include_top)
ingest_spotify(include_top=include_top, force=spotify_full)
_step("iTunes")
ingest_itunes()