diff --git a/src/data_collection/weather_sources.py b/src/data_collection/weather_sources.py index e0627a15..a1a2f9b7 100644 --- a/src/data_collection/weather_sources.py +++ b/src/data_collection/weather_sources.py @@ -1059,29 +1059,6 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour if cwa_forecast is not None: results["cwa_forecast"] = cwa_forecast - def _attach_wunderground_historical( - self, - results: Dict, - city_lower: str, - use_fahrenheit: bool, - ) -> None: - try: - utc_offset = get_city_utc_offset_seconds(city_lower) - payload = self.fetch_wunderground_historical( - city_lower, - use_fahrenheit=use_fahrenheit, - utc_offset=utc_offset, - ) - except Exception as exc: - logger.warning( - "Wunderground historical attach failed city={} error={}", - city_lower, - exc, - ) - return - if payload: - results["wunderground_current"] = payload - def _attach_turkish_mgm_data( self, results: Dict, diff --git a/tests/test_city_payloads.py b/tests/test_city_payloads.py index ae2b288e..b47b7885 100644 --- a/tests/test_city_payloads.py +++ b/tests/test_city_payloads.py @@ -53,7 +53,7 @@ def test_city_payloads_expose_wunderground_current(): assert detail["timeseries"]["wunderground_today_obs"] == [{"time": "13:30", "temp": 26}] -def test_api_payload_overlay_uses_cached_wunderground_state_without_fetch(monkeypatch): +def test_api_payload_overlay_strips_cached_wunderground_state_without_fetch(monkeypatch): stale_payload = { "name": "guangzhou", "temp_symbol": "°C", @@ -87,12 +87,11 @@ def test_api_payload_overlay_uses_cached_wunderground_state_without_fetch(monkey monkeypatch.setattr(city_runtime._weather, "fetch_wunderground_historical", fail_fetch) overlay = getattr(city_runtime, "_overlay_latest_wunderground_current", None) - assert callable(overlay), "city API must preserve cached WU state without direct fetch" + assert callable(overlay), "city API must strip cached WU state without direct fetch" payload = overlay("guangzhou", stale_payload) - assert payload["wunderground_current"]["temp"] == 36 - assert payload["wunderground_current"]["max_so_far"] == 36 - assert payload["official"]["wunderground_current"]["max_so_far"] == 36 - assert payload["timeseries"]["wunderground_today_obs"] == [{"time": "14:00", "temp": 36}] + assert "wunderground_current" not in payload + assert "wunderground_current" not in payload["official"] + assert "wunderground_today_obs" not in payload["timeseries"] assert stale_payload["wunderground_current"]["max_so_far"] == 36 assert fetch_calls == [] diff --git a/tests/test_multi_model_sources.py b/tests/test_multi_model_sources.py index bac17685..0029800d 100644 --- a/tests/test_multi_model_sources.py +++ b/tests/test_multi_model_sources.py @@ -205,7 +205,6 @@ def test_fetch_all_sources_delegates_non_hf_forecast_bundle(monkeypatch, tmp_pat monkeypatch.setattr(collector, "_log_temperature_unit", lambda *args, **kwargs: None) monkeypatch.setattr(collector, "_evict_city_caches", lambda *args, **kwargs: None) monkeypatch.setattr(collector, "_attach_settlement_sources", lambda *args, **kwargs: None) - monkeypatch.setattr(collector, "_attach_wunderground_historical", lambda *args, **kwargs: None) monkeypatch.setattr(collector, "_supports_aviationweather", lambda city: False) monkeypatch.setattr(collector, "_attach_turkish_mgm_data", lambda *args, **kwargs: None) monkeypatch.setattr(collector, "_attach_korean_amos_data", lambda *args, **kwargs: None) diff --git a/web/services/city_runtime.py b/web/services/city_runtime.py index 2ab98220..16d9d2b5 100644 --- a/web/services/city_runtime.py +++ b/web/services/city_runtime.py @@ -299,7 +299,7 @@ def _cached_city_payload(kind: str, city: str) -> dict: if not isinstance(entry, dict): return {} payload = entry.get("payload") - return deepcopy(payload) if isinstance(payload, dict) else {} + return _strip_wunderground_current(payload) if isinstance(payload, dict) else {} def _canonical_city_payload(city: str, *, detail_depth: str) -> dict: @@ -432,34 +432,24 @@ def _refresh_city_full_cache(city: str, force_refresh: bool = False) -> dict: return _queued_city_cache_payload(city, "full", force_refresh=force_refresh) -def _overlay_wunderground_current(payload: dict, wunderground: dict) -> dict: - if not isinstance(payload, dict) or not isinstance(wunderground, dict) or not wunderground: +def _strip_wunderground_current(payload: dict) -> dict: + if not isinstance(payload, dict): return payload next_payload = deepcopy(payload) - next_payload["wunderground_current"] = dict(wunderground) - + next_payload.pop("wunderground_current", None) official = next_payload.get("official") if isinstance(official, dict): - official["wunderground_current"] = dict(wunderground) - + official.pop("wunderground_current", None) timeseries = next_payload.get("timeseries") if isinstance(timeseries, dict): - timeseries["wunderground_today_obs"] = list(wunderground.get("today_obs") or []) - + timeseries.pop("wunderground_today_obs", None) return next_payload def _overlay_latest_wunderground_current(city: str, payload: dict) -> dict: if not isinstance(payload, dict): return payload - latest_wu = payload.get("wunderground_current") - if not isinstance(latest_wu, dict) or not latest_wu: - official = payload.get("official") - if isinstance(official, dict): - latest_wu = official.get("wunderground_current") - if not isinstance(latest_wu, dict) or not latest_wu: - return deepcopy(payload) - return _overlay_wunderground_current(payload, latest_wu) + return _strip_wunderground_current(payload) def _normalize_city_or_404(name: str) -> str: city = name.lower().strip().replace("-", " ")