thermograph/paths.py

40 lines
1.6 KiB
Python

"""Canonical filesystem locations, resolved once from the repo root.
Every path the backend needs (the climate cache, the accounts DB, logs, the
bundled city data) is derived here from the repository root rather than from
each module's own ``__file__``. That keeps the locations stable no matter how
deep in the package tree a module lives, so moving a module never silently
re-points the cache or the accounts DB.
Callers that support an environment override (e.g. ``THERMOGRAPH_ACCOUNTS_DB``)
keep doing so; these are only the defaults.
"""
import os
_HERE = os.path.dirname(os.path.abspath(__file__))
def _repo_root() -> str:
"""Walk up from this file until a directory holds both ``backend/`` and
``frontend/`` — the repository root, in every checkout (dev, prod, worktree)."""
d = _HERE
while True:
if os.path.isdir(os.path.join(d, "backend")) and os.path.isdir(os.path.join(d, "frontend")):
return d
parent = os.path.dirname(d)
if parent == d:
raise RuntimeError(
"cannot locate the repo root (no ancestor has sibling backend/ and frontend/)"
)
d = parent
REPO_DIR = _repo_root()
BACKEND_DIR = os.path.join(REPO_DIR, "backend")
DATA_DIR = os.path.join(REPO_DIR, "data")
LOGS_DIR = os.path.join(REPO_DIR, "logs")
# Bundled reference data shipped alongside the code (generated by gen_cities /
# gen_flavor), not runtime state — hence under backend/, not data/.
CITIES_JSON = os.path.join(BACKEND_DIR, "cities.json")
CITIES_FLAVOR_JSON = os.path.join(BACKEND_DIR, "cities_flavor.json")