diff --git a/scripts/combine_belgium_building_portfolio_specs.py b/scripts/combine_belgium_building_portfolio_specs.py index 34603f8f..537d4144 100644 --- a/scripts/combine_belgium_building_portfolio_specs.py +++ b/scripts/combine_belgium_building_portfolio_specs.py @@ -28,15 +28,18 @@ def combine_specs(paths: list[Path]) -> dict[str, Any]: sources = [] for path in paths: payload = json.loads(path.read_text(encoding="utf-8-sig")) - if payload.get("status") != "complete": + status = payload.get("status") + legacy_unstated = status is None and payload.get("schema_version") == 1 and bool(payload.get("samples")) + if status != "complete" and not legacy_unstated: raise ValueError(f"Portfolio spec is not complete: {path}") - current_side = float(payload["side_m"]) - current_resolution = float(payload["resolution_m"]) - if side_m is not None and current_side != side_m: + current_side = float(payload["side_m"]) if payload.get("side_m") is not None else None + current_resolution = float(payload["resolution_m"]) if payload.get("resolution_m") is not None else None + if side_m is not None and current_side is not None and current_side != side_m: raise ValueError(f"Portfolio side_m differs: {path}") - if resolution_m is not None and current_resolution != resolution_m: + if resolution_m is not None and current_resolution is not None and current_resolution != resolution_m: raise ValueError(f"Portfolio resolution_m differs: {path}") - side_m, resolution_m = current_side, current_resolution + side_m = current_side if current_side is not None else side_m + resolution_m = current_resolution if current_resolution is not None else resolution_m for sample in payload.get("samples") or []: slug = str(sample.get("sample_slug") or sample.get("slug") or "") if not slug: @@ -48,7 +51,14 @@ def combine_specs(paths: list[Path]) -> dict[str, Any]: normalized["sample_slug"] = slug normalized.pop("slug", None) samples.append(normalized) - sources.append({"path": str(path), "sha256": sha256(path), "sample_count": len(payload.get("samples") or [])}) + sources.append({ + "path": str(path), + "sha256": sha256(path), + "sample_count": len(payload.get("samples") or []), + "source_status": status or "legacy_unstated", + }) + if side_m is None or resolution_m is None: + raise ValueError("Combined portfolio dimensions are unknown") return { "schema_version": 2, "status": "complete", diff --git a/tests/test_combine_belgium_building_portfolio_specs.py b/tests/test_combine_belgium_building_portfolio_specs.py index f4a28c9a..183f4850 100644 --- a/tests/test_combine_belgium_building_portfolio_specs.py +++ b/tests/test_combine_belgium_building_portfolio_specs.py @@ -36,3 +36,18 @@ def test_combine_specs_rejects_mismatched_resolution(tmp_path: Path) -> None: def test_combine_specs_rejects_incomplete_source(tmp_path: Path) -> None: with pytest.raises(ValueError, match="not complete"): combine_specs([write_spec(tmp_path / "one.json", "one", status="in_progress")]) + + +def test_combine_specs_accepts_populated_legacy_v1_when_dimensions_come_from_complete_spec(tmp_path: Path) -> None: + legacy = tmp_path / "legacy.json" + legacy.write_text(json.dumps({"schema_version": 1, "samples": [{"sample_slug": "legacy"}]}), encoding="utf-8") + payload = combine_specs([legacy, write_spec(tmp_path / "current.json", "current")]) + assert payload["sample_count"] == 2 + assert payload["source_specs"][0]["source_status"] == "legacy_unstated" + + +def test_combine_specs_rejects_empty_legacy_v1(tmp_path: Path) -> None: + legacy = tmp_path / "legacy.json" + legacy.write_text(json.dumps({"schema_version": 1, "samples": []}), encoding="utf-8") + with pytest.raises(ValueError, match="not complete"): + combine_specs([legacy, write_spec(tmp_path / "current.json", "current")])