diff --git a/backend/config.py b/backend/config.py index 7ca139a..3830ec8 100644 --- a/backend/config.py +++ b/backend/config.py @@ -76,32 +76,6 @@ from backend.logger import make_logger -# Which sources report each parameter (empirical availability). A plain -# parameter -> [source_key, ...] map; the waterlevels list mirrors the sources -# with a waterlevel class in the SOURCES registry (asserted by -# tests/test_source_registry.py), while the analyte lists are authored because -# they encode which analytes each agency actually reports. -PARAMETER_SOURCE_MAP = { - WATERLEVELS: ["bernco", "cabq", "ebid", "nmbgmr_amp", "nmose_isc_seven_rivers", "nmose_roswell", "nwis", "pvacd", "wqp"], - CARBONATE: ["nmbgmr_amp", "wqp"], - ARSENIC: ["bor", "nmbgmr_amp", "nmed_dwb", "wqp"], - URANIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "wqp"], - SPECIFIC_CONDUCTANCE: ["nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - CONDUCTIVITY: ["bor", "nmose_isc_seven_rivers", "wqp"], - BICARBONATE: ["nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - CALCIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - CHLORIDE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - FLUORIDE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - MAGNESIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - NITRATE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - PH: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - POTASSIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - SILICA: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - SODIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - SULFATE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], - TDS: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], -} - @dataclass(frozen=True) class SourceDef: """One data source's class wiring, declared in a single place. @@ -160,6 +134,33 @@ class SourceDef: s.key: (s.site, s.waterlevel) for s in SOURCES if s.waterlevel is not None } +# Which sources report each parameter (empirical availability), parameter -> +# [source_key, ...]. The waterlevels list is DERIVED from the registry (every +# source with a waterlevel class). The analyte lists are authored because they +# encode which analytes each agency actually reports — which can't be inferred +# from the class wiring. tests/test_source_registry.py guards both against the +# registry. +PARAMETER_SOURCE_MAP = { + WATERLEVELS: [s.key for s in SOURCES if s.waterlevel is not None], + CARBONATE: ["nmbgmr_amp", "wqp"], + ARSENIC: ["bor", "nmbgmr_amp", "nmed_dwb", "wqp"], + URANIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "wqp"], + SPECIFIC_CONDUCTANCE: ["nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + CONDUCTIVITY: ["bor", "nmose_isc_seven_rivers", "wqp"], + BICARBONATE: ["nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + CALCIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + CHLORIDE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + FLUORIDE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + MAGNESIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + NITRATE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + PH: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + POTASSIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + SILICA: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + SODIUM: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + SULFATE: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], + TDS: ["bor", "nmbgmr_amp", "nmed_dwb", "nmose_isc_seven_rivers", "wqp"], +} + def get_source(source): try: diff --git a/docs/cleanup-todo.md b/docs/cleanup-todo.md index 01f1853..01c5716 100644 --- a/docs/cleanup-todo.md +++ b/docs/cleanup-todo.md @@ -1,7 +1,8 @@ # DIE Cleanup TODO -> **Status:** Tier 1 (all) and **all of Tier 2 except 2.6** are **DONE**. 2.6 is -> **deferred** (see note below). Remaining: 2.6, all of Tier 3, all of Tier 4. +> **Status:** Tier 1 (all), all of Tier 2 except 2.6, and Tier 3 item 3.3 are +> **DONE**. 2.6 is **deferred** (see note). Remaining: 2.6, Tier 3 items 3.1/3.2, +> all of Tier 4. Prioritized cleanup backlog from a code-analysis sweep (backend + frontend + orchestration). Each item: location, effort (S/M/L), risk, and whether it @@ -50,7 +51,7 @@ registry). Tiers are ordered by safety — Tier 1 is batchable into one no-risk |---|----------|--------|--------|---| | 3.1 | `frontend/cli.py:36-121` (`--no-X` flags) + `cli.py:385-398` (hardcoded agency list in `sites()`) | Derive from `backend.config.SOURCE_KEYS` — the remaining hardcoded source list after #101/#102. Click flags are harder to generate dynamically; at minimum dedup the `sites()` list. | M | ✓ | | 3.2 | `orchestration/definitions.py:60-68` (`_SUPPORTED_OUTPUT_TYPES`) vs `products.py` combine `if/elif` chain | Single registry mapping `output_type → (dumper, is_summary)`; both the supported-set and the dispatch derive from it. Adding an output type → one entry. | M | | -| 3.3 | `backend/config.py:79` `PARAMETER_SOURCE_MAP[WATERLEVELS]` | Derive the waterlevels agency list from the `SOURCES` registry (== sources with a waterlevel class; the desync test already asserts equality). Keep analyte entries authored. | S | ✓ | +| 3.3 ✅ | `backend/config.py` `PARAMETER_SOURCE_MAP[WATERLEVELS]` | Derived from the `SOURCES` registry (`[s.key for s in SOURCES if s.waterlevel]`). Analyte entries stay authored. Map moved below the registry so it can reference `SOURCES`. | S | ✓ | ---