From a6b798218fb3dd6821318f4a815a39474276673e Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 5 Jun 2026 10:45:44 +0000 Subject: [PATCH] fix: normalize empty API sap_roof_windows to None for round-trip fidelity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `test_epc_property_data_round_trips[RdSAP-Schema-21.0.1]` failed with `sap_roof_windows: None != []` — a normalization mismatch, not lost data. The 21.0.1 fixture has no roof windows, but the 21.0.1 API mapper emitted an empty list `[]` while the domain field defaults to None (`Optional[List[SapRoofWindow]] = None`), the 21.0.0 path yields None, and the persistence reload yields None (roof windows aren't stored yet — doc §2.4). Append `or None` so "no roof windows" has one canonical representation across mapper paths and the round-trip. No data-loss change: a cert WITH roof windows still produces the populated list (test_golden_fixtures pins a 6-roof-window cert), and the §2.4 roof-window persistence gap remains separately tracked. Full sap10_calculator + documents_parser + epc-repository suites pass (2420); pyright unchanged. Co-Authored-By: Claude Opus 4.8 --- datatypes/epc/domain/mapper.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 32765df1..83a0a9eb 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -1634,11 +1634,17 @@ class EpcPropertyDataMapper: for w in schema.sap_windows if not _api_is_roof_window(w) ], + # Empty → None (not []) so "no roof windows" has the single + # canonical representation the domain field defaults to + # (`Optional[List] = None`), matching the 21.0.0 path and the + # persistence round-trip (roof windows aren't yet stored — doc + # §2.4 — so a reloaded cert always reads None here). sap_roof_windows=[ _api_sap_roof_window(w) for w in schema.sap_windows if _api_is_roof_window(w) - ], + ] + or None, # SAP energy source sap_energy_source=SapEnergySource( mains_gas=es.mains_gas == "Y",