Map SAP-Schema-15.0's "Main building" identifier to MAIN

Properties 741843/741872 (uprns 100060714155/100021944594) failed
modelling_e2e subtasks 6ac7841a-9338-4efe-97e5-7e0d19b3055d and
c5450f03-5b0d-4068-a3b3-d1470bc0af57 with a bare StopIteration: their
SAP-Schema-15.0 (2011-era LIG-lodged) certs identify the main dwelling's
building part as "Main building" rather than "Main Dwelling", so
from_api_string fell to OTHER and left the property with no MAIN part —
crashing wall_recommendation.py's unguarded next(...).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jun-te Kim 2026-07-10 15:03:28 +00:00
parent 0a7b2c1d66
commit 64abeb9066
2 changed files with 14 additions and 2 deletions

View file

@ -39,12 +39,13 @@ class BuildingPartIdentifier(Enum):
cls, api_identifier: Optional[object]
) -> "BuildingPartIdentifier":
"""Map a gov-EPC API `BuildingPart.identifier` to its canonical
member. "Main Dwelling" MAIN; "Extension N" EXTENSION_N
member. "Main Dwelling" / "Main building" (the 2011-era LIG-lodged
SAP-Schema-15.0 wording) MAIN; "Extension N" EXTENSION_N
(for N in 1..4). `None` (permitted by the 21_0_1 schema), a non-string
identifier (some SAP-16.x certs lodge a bare int), and anything else
unrecognised fall to OTHER.
"""
if api_identifier == "Main Dwelling":
if api_identifier in ("Main Dwelling", "Main building"):
return cls.MAIN
if isinstance(api_identifier, str):
match = _API_EXTENSION.match(api_identifier)

View file

@ -9,6 +9,17 @@ def test_main_dwelling_maps_to_main() -> None:
)
def test_main_building_maps_to_main() -> None:
# SAP-Schema-15.0 (2011-era LIG-lodged) certs use "Main building" instead
# of "Main Dwelling" for the main dwelling's building-part identifier.
# Previously this fell to OTHER, leaving the property with no MAIN part
# and crashing every recommendation generator that assumes one exists
# (e.g. `next(...)` with no default in wall_recommendation.py).
assert BuildingPartIdentifier.from_api_string("Main building") == (
BuildingPartIdentifier.MAIN
)
def test_extension_string_maps_to_numbered_extension() -> None:
assert BuildingPartIdentifier.from_api_string("Extension 2") == (
BuildingPartIdentifier.EXTENSION_2