thermograph/backend/paths.py
Emi Griffith d1ef5be859
All checks were successful
secrets-guard / encrypted (pull_request) Successful in 6s
PR build (required check) / changes (pull_request) Successful in 12s
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Successful in 1m24s
PR build (required check) / build-backend (pull_request) Successful in 1m32s
PR build (required check) / gate (pull_request) Successful in 1s
Add editorial city copy for 83 city/record pages, wired through payload + templates
Introduce backend/city_copy.json: original, researched per-city editorial copy
(a lede, 2-4 body paragraphs, and a records-page intro), keyed by slug next to
the existing Wikipedia cities_flavor.json. Covers 83 of the 90 cities that had
no flavor blurb at all; each entry carries the independent sources it was
written from and reviewed:false pending a human spot-check.

Wire it end to end:
- cities.copy(slug) loader, mirroring cities.flavor() (lazy, tolerant of a
  missing file so pages render fine until copy exists).
- A `copy` field on the city and records content payloads. PAYLOAD_VER p2->p3
  so cached content rows rebuild with the new field instead of serving the old
  shape.
- city.html.j2 renders the editorial lede + body in place of the Wikipedia
  blurb, falling back to the flavor blurb (with its "via Wikipedia" credit)
  wherever copy isn't written yet. records.html.j2 gains a per-city intro line
  it never had before.

Additive and backward-compatible: no API contract bump, and any slug without a
copy entry keeps its existing behavior.
2026-07-24 02:04:36 -07:00

30 lines
1.7 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
REPO_DIR = os.path.dirname(os.path.abspath(__file__))
# Runtime state dirs default under the repo root, but MUST be overridable: after
# the repo split the code lives at the image root (/app), so the Python package
# `data/` and the runtime data dir `<root>/data` collide at the same path. When
# a persistent volume is mounted at that path (as the deploy compose does for
# the parquet cache / notifier.lock / geonames) it shadows and erases the
# `data/*.py` modules, so `import data.climate` fails at boot. Point
# THERMOGRAPH_DATA_DIR (and _LOGS_DIR) at a path OUTSIDE the code tree in the
# container to keep the volume clear of the package.
DATA_DIR = os.environ.get("THERMOGRAPH_DATA_DIR") or os.path.join(REPO_DIR, "data")
LOGS_DIR = os.environ.get("THERMOGRAPH_LOGS_DIR") or os.path.join(REPO_DIR, "logs")
# Bundled reference data shipped alongside the code (generated by gen_cities /
# gen_flavor), not runtime state — hence at the repo root, not data/.
CITIES_JSON = os.path.join(REPO_DIR, "cities.json")
CITIES_FLAVOR_JSON = os.path.join(REPO_DIR, "cities_flavor.json")
CITY_COPY_JSON = os.path.join(REPO_DIR, "city_copy.json")