refactor(server): extract the progression routes into routers/progression.py (R3) (#853)

4 routes (overview/add-paths/onboarding/events, spec 010) + their EXCLUSIVE
helpers (_goal_ui_progress, _progression_overview 112L) + the
_PROGRESSION_EVENT_TYPES whitelist. Bodies verbatim; @app -> @router,
meta_db -> appstate.meta_db, _clean_str from reqfields.

The two SHARED server accessors read through the seam: get_progression_content
(added for shop #851) and builtin_diagnostic_filename (new slot — a trivial
const-returning fn shared with the stats router's api_record_stats). Both are
injected via the second appstate.configure() after their defs (the import-top
configure runs before them). The cache + fns stay in server.py, so
test_progression_api's server._progression_content patch is untouched — 0 retarget.

server.py: 7,798 -> 7,594.

Verified: pyflakes clean; route table IDENTICAL (143); both seam accessors wired;
pytest 2401 passed (63 in test_progression_api); eslint 0. Boot smoke: GET
/api/progression 200 (drives _progression_overview + both accessors), events
400 on bad body.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Byron Gamatos
2026-07-11 00:25:53 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 5f58af4faa
commit f9f33320ac
4 changed files with 242 additions and 215 deletions
+2 -1
View File
@@ -86,12 +86,13 @@ audio_cache_dir = None
# through the seam. get_progression_content wraps a lazy content cache that stays
# in server.py (its `setattr(server, "_progression_content")` test is untouched).
get_progression_content = None
builtin_diagnostic_filename = None
_SLOTS = frozenset({
"meta_db", "audio_effect_mappings",
"config_dir", "dlc_dir", "dlc_dir_env",
"static_dir", "sloppak_cache_dir", "audio_cache_dir",
"get_progression_content",
"get_progression_content", "builtin_diagnostic_filename",
})