Split the backend into domain packages (#217)
* Centralize filesystem paths in a single module
Add paths.py, which resolves the repo root once and derives the cache,
accounts DB, logs, templates, frontend and bundled-city-data locations
from it. Replace the 13 per-module `dirname(__file__)/..` anchors with
references to it, so a module's location no longer determines where the
app reads its data. Env overrides (accounts DB, VAPID, IndexNow) are
unchanged; every resolved path is byte-identical to before.
Groundwork for moving modules into packages without re-pointing paths.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
* Split the backend into domain packages
Group the flat backend modules into packages that mirror their concerns:
data/ climate, grading, scoring, grid, places, cities,
city_events, store
web/ app, views, homepage, content, schemas
notifications/ notify, digest, push, mailer, discord,
discord_interactions, discord_link
accounts/ models, users, api_accounts, db
core/ metrics, singleton, audit
Intra-project imports are rewritten to the package-qualified form. The
entry scripts (indexnow, warm_cities, migrate, gen_cities, gen_flavor)
and paths.py stay at the backend/ root, and backend/app.py becomes a
shim re-exporting web.app:app so the launch target stays `app:app` —
run.sh, the systemd units, and CI need no change.
Verified: full suite (318) passes, `uvicorn app:app` boots and serves
the home/SEO/static/API surfaces, and every root script imports clean.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
2026-07-20 05:31:03 +00:00
|
|
|
"""Canonical filesystem locations, resolved once from the repo root.
|
|
|
|
|
|
|
|
|
|
Every path the backend needs (the climate cache, the accounts DB, logs, the
|
2026-07-21 22:48:59 +00:00
|
|
|
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.
|
Split the backend into domain packages (#217)
* Centralize filesystem paths in a single module
Add paths.py, which resolves the repo root once and derives the cache,
accounts DB, logs, templates, frontend and bundled-city-data locations
from it. Replace the 13 per-module `dirname(__file__)/..` anchors with
references to it, so a module's location no longer determines where the
app reads its data. Env overrides (accounts DB, VAPID, IndexNow) are
unchanged; every resolved path is byte-identical to before.
Groundwork for moving modules into packages without re-pointing paths.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
* Split the backend into domain packages
Group the flat backend modules into packages that mirror their concerns:
data/ climate, grading, scoring, grid, places, cities,
city_events, store
web/ app, views, homepage, content, schemas
notifications/ notify, digest, push, mailer, discord,
discord_interactions, discord_link
accounts/ models, users, api_accounts, db
core/ metrics, singleton, audit
Intra-project imports are rewritten to the package-qualified form. The
entry scripts (indexnow, warm_cities, migrate, gen_cities, gen_flavor)
and paths.py stay at the backend/ root, and backend/app.py becomes a
shim re-exporting web.app:app so the launch target stays `app:app` —
run.sh, the systemd units, and CI need no change.
Verified: full suite (318) passes, `uvicorn app:app` boots and serves
the home/SEO/static/API surfaces, and every root script imports clean.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
2026-07-20 05:31:03 +00:00
|
|
|
|
|
|
|
|
Callers that support an environment override (e.g. ``THERMOGRAPH_ACCOUNTS_DB``)
|
|
|
|
|
keep doing so; these are only the defaults.
|
|
|
|
|
"""
|
|
|
|
|
import os
|
|
|
|
|
|
2026-07-21 22:57:17 +00:00
|
|
|
REPO_DIR = os.path.dirname(os.path.abspath(__file__))
|
2026-07-22 21:45:26 +00:00
|
|
|
# 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")
|
Split the backend into domain packages (#217)
* Centralize filesystem paths in a single module
Add paths.py, which resolves the repo root once and derives the cache,
accounts DB, logs, templates, frontend and bundled-city-data locations
from it. Replace the 13 per-module `dirname(__file__)/..` anchors with
references to it, so a module's location no longer determines where the
app reads its data. Env overrides (accounts DB, VAPID, IndexNow) are
unchanged; every resolved path is byte-identical to before.
Groundwork for moving modules into packages without re-pointing paths.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
* Split the backend into domain packages
Group the flat backend modules into packages that mirror their concerns:
data/ climate, grading, scoring, grid, places, cities,
city_events, store
web/ app, views, homepage, content, schemas
notifications/ notify, digest, push, mailer, discord,
discord_interactions, discord_link
accounts/ models, users, api_accounts, db
core/ metrics, singleton, audit
Intra-project imports are rewritten to the package-qualified form. The
entry scripts (indexnow, warm_cities, migrate, gen_cities, gen_flavor)
and paths.py stay at the backend/ root, and backend/app.py becomes a
shim re-exporting web.app:app so the launch target stays `app:app` —
run.sh, the systemd units, and CI need no change.
Verified: full suite (318) passes, `uvicorn app:app` boots and serves
the home/SEO/static/API surfaces, and every root script imports clean.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
2026-07-20 05:31:03 +00:00
|
|
|
|
|
|
|
|
# Bundled reference data shipped alongside the code (generated by gen_cities /
|
2026-07-21 22:57:17 +00:00
|
|
|
# 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")
|