Merge pull request #1533 from Hestia-Homes/fix/epc-schema-allowlist

Unsupported EPC schema versions skip with a warning instead of crashing
This commit is contained in:
Jun-te Kim 2026-07-10 12:43:40 +01:00 committed by GitHub
commit 121b3d991d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 11 deletions

View file

@ -2946,11 +2946,12 @@ class EpcPropertyDataMapper:
return [EpcPropertyDataMapper._map_energy_element(e) for e in elements]
@staticmethod
def from_api_response(data: Dict[str, Any]) -> "EpcPropertyData":
def from_api_response(data: Dict[str, Any]) -> Optional["EpcPropertyData"]:
"""
Dispatch to the correct schema mapper based on schema_type.
Supports RdSAP-Schema-21.0.0 and RdSAP-Schema-21.0.1 only.
Raises ValueError for unsupported schemas add cases here as needed.
Any `schema_type` not in the allow-list below (the schemas with a
dedicated mapper) is logged as a warning and skipped returns None
rather than raising, so one unrecognised cert doesn't break a batch.
"""
data = _normalize_shower_outlets(data)
@ -3053,7 +3054,12 @@ class EpcPropertyDataMapper:
"mapped to EpcPropertyData, which models a single dwelling."
)
else:
raise ValueError(f"Unsupported EPC schema: {schema!r}")
logger.warning(
"Unsupported EPC schema %r — skipping this EPC (uprn=%s)",
schema,
data.get("uprn"),
)
return None
return _clear_basement_flag_when_system_built(
_with_renewable_heat_incentive(

View file

@ -196,6 +196,8 @@ def build_property_report(
name: str = path.stem
try:
epc = EpcPropertyDataMapper.from_api_response(json.loads(path.read_text()))
if epc is None:
raise ValueError("Unsupported or unrecognised EPC schema")
lodged_sap: Optional[int] = epc.energy_rating_current
calculated_sap: float = Sap10Calculator().calculate(epc).sap_score_continuous
except Exception as error: # noqa: BLE001 — one bad cert must not abort the report

View file

@ -38,7 +38,7 @@ class EpcClientService:
except (TypeError, ValueError):
return None
def get_by_certificate_number(self, cert_num: str) -> EpcPropertyData:
def get_by_certificate_number(self, cert_num: str) -> Optional[EpcPropertyData]:
raw = call_with_retry(lambda: self._fetch_certificate(cert_num))
return EpcPropertyDataMapper.from_api_response(raw)

View file

@ -1,5 +1,3 @@
import pytest
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
from datatypes.epc.domain.epc_property_data import EpcPropertyData
@ -23,9 +21,13 @@ def test_from_api_response_rdsap_21_0_1(rdsap_21_0_1_cert):
# ---------------------------------------------------------------------------
# Test 3: unknown schema_type → ValueError
# Test 3: unknown schema_type → logged warning, None returned (not raised)
# ---------------------------------------------------------------------------
def test_from_api_response_unknown_schema_raises():
with pytest.raises(ValueError, match="Unsupported EPC schema"):
EpcPropertyDataMapper.from_api_response({"schema_type": "RdSAP-Schema-99.0.0"})
def test_from_api_response_unknown_schema_returns_none(caplog):
with caplog.at_level("WARNING"):
result = EpcPropertyDataMapper.from_api_response(
{"schema_type": "RdSAP-Schema-99.0.0"}
)
assert result is None
assert "RdSAP-Schema-99.0.0" in caplog.text