fix: restore Hong Kong CoWIN reference curve
This commit is contained in:
@@ -358,6 +358,49 @@ def test_hong_kong_cowin_primary_uses_station_6087_history(monkeypatch):
|
||||
]
|
||||
|
||||
|
||||
def test_hong_kong_cowin_primary_prefers_live_intraday_series(monkeypatch):
|
||||
from src.database import runtime_state
|
||||
|
||||
class FakeOfficialIntradayObservationRepository:
|
||||
def load_points(self, *, source_code, station_code, target_date):
|
||||
return [{"time": "09:00", "temp": 30.0}]
|
||||
|
||||
monkeypatch.setattr(
|
||||
runtime_state,
|
||||
"OfficialIntradayObservationRepository",
|
||||
FakeOfficialIntradayObservationRepository,
|
||||
)
|
||||
|
||||
snapshot = build_country_network_snapshot(
|
||||
"hong kong",
|
||||
{
|
||||
"cowin_current": {
|
||||
"temp": 31.3,
|
||||
"obs_time": "2026-05-27T02:41:00Z",
|
||||
"istNo": "6087",
|
||||
"icao": "COWIN6087",
|
||||
"station_label": "保良局陳守仁小學 1min (CoWIN)",
|
||||
},
|
||||
"cowin_today_obs": [
|
||||
{"time": "10:40", "temp": 31.1},
|
||||
{"time": "10:41", "temp": 31.3},
|
||||
],
|
||||
"settlement_current": {
|
||||
"station_code": "HKO",
|
||||
"station_name": "HK Observatory",
|
||||
"observation_time": "2026-05-27T10:40:00+08:00",
|
||||
"current": {"temp": 31.2},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert snapshot["airport_primary_current"]["source_code"] == "cowin_obs"
|
||||
assert snapshot["airport_primary_today_obs"] == [
|
||||
{"time": "10:40", "temp": 31.1},
|
||||
{"time": "10:41", "temp": 31.3},
|
||||
]
|
||||
|
||||
|
||||
def test_moscow_provider_uses_realtime_metar_cluster_not_station_archive_rows():
|
||||
raw = {
|
||||
"metar": {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import threading
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import httpx
|
||||
|
||||
from src.data_collection import cowin_sources
|
||||
from src.data_collection.cowin_sources import CowinSourceMixin
|
||||
|
||||
|
||||
class _FakeResponse:
|
||||
content = b"{}"
|
||||
|
||||
def __init__(self, payload):
|
||||
self._payload = payload
|
||||
self.text = "{}"
|
||||
|
||||
def json(self):
|
||||
return self._payload
|
||||
|
||||
def raise_for_status(self):
|
||||
return None
|
||||
|
||||
|
||||
class _FakeCowinCollector(CowinSourceMixin):
|
||||
timeout = 2
|
||||
cowin_obs_cache_ttl_sec = 0
|
||||
_cowin_obs_cache = {}
|
||||
_cowin_obs_cache_lock = threading.Lock()
|
||||
user_agent = "test"
|
||||
|
||||
def _http_get(self, url):
|
||||
raise httpx.ConnectError("[SSL: CERTIFICATE_VERIFY_FAILED] unable to get local issuer certificate")
|
||||
|
||||
|
||||
def test_cowin_current_retries_without_tls_verification_when_chain_is_incomplete(monkeypatch):
|
||||
calls = []
|
||||
|
||||
def fake_get(url, **kwargs):
|
||||
calls.append({"url": url, **kwargs})
|
||||
return _FakeResponse(
|
||||
{
|
||||
"station": 6087,
|
||||
"minutely": [
|
||||
{"obstime": "2026-05-28T07:59:00", "value1": 30.1},
|
||||
{"obstime": "2026-05-28T08:00:00", "value1": 30.0},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
monkeypatch.setattr(cowin_sources.requests, "get", fake_get)
|
||||
|
||||
current = _FakeCowinCollector().fetch_cowin_obs_current("hong kong")
|
||||
|
||||
assert current is not None
|
||||
assert current["station_code"] == "6087"
|
||||
assert current["current"]["temp"] == 30.0
|
||||
assert current["obs_time"] == "2026-05-28T08:00:00+08:00"
|
||||
assert calls
|
||||
assert calls[0]["verify"] is False
|
||||
|
||||
|
||||
def test_cowin_today_series_returns_hong_kong_local_intraday_points(monkeypatch):
|
||||
def fake_get(url, **kwargs):
|
||||
return _FakeResponse(
|
||||
{
|
||||
"station": 6087,
|
||||
"minutely": [
|
||||
{"obstime": "2026-05-27T23:59:00", "value1": 29.8},
|
||||
{"obstime": "2026-05-28T00:00:00", "value1": 29.9},
|
||||
{"obstime": "2026-05-28T07:58:00", "value1": 30.1},
|
||||
{"obstime": "2026-05-28T08:00:00", "value1": 30.0},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
monkeypatch.setattr(cowin_sources.requests, "get", fake_get)
|
||||
|
||||
points = _FakeCowinCollector().fetch_cowin_obs_today_series(
|
||||
"hong kong",
|
||||
now_utc=datetime(2026, 5, 28, 0, 5, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
assert points == [
|
||||
{"time": "00:00", "temp": 29.9},
|
||||
{"time": "07:58", "temp": 30.1},
|
||||
{"time": "08:00", "temp": 30.0},
|
||||
]
|
||||
@@ -21,9 +21,9 @@ def test_aeroweb_obs_time_is_utc_aware():
|
||||
)
|
||||
|
||||
|
||||
def test_cowin_obs_time_uses_utc_window_when_timezone_is_missing():
|
||||
assert _cowin_obs_time_to_iso("2026-05-27T01:15:00") == "2026-05-27T01:15:00Z"
|
||||
assert _cowin_obs_time_to_iso("2026-05-27T09:15:00+08:00") == "2026-05-27T01:15:00Z"
|
||||
def test_cowin_obs_time_keeps_hong_kong_timezone_when_timezone_is_missing():
|
||||
assert _cowin_obs_time_to_iso("2026-05-27T09:15:00") == "2026-05-27T09:15:00+08:00"
|
||||
assert _cowin_obs_time_to_iso("2026-05-27T09:15:00+08:00") == "2026-05-27T09:15:00+08:00"
|
||||
|
||||
|
||||
def test_hko_one_minute_obs_time_keeps_hong_kong_timezone():
|
||||
|
||||
Reference in New Issue
Block a user