Scope bounded coverage to persisted extents
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-19 01:52:01 +02:00
parent 8085d106d4
commit a823342b5b
4 changed files with 67 additions and 1 deletions
@@ -422,6 +422,7 @@ class CoverageRegistryService:
definition: _SourceDefinition,
theme: str,
zone: str,
selection: Any,
) -> list[Dataset]:
if definition.operational_themes and theme not in definition.operational_themes:
return []
@@ -444,6 +445,18 @@ class CoverageRegistryService:
coverage_zones = metadata.get("coverage_zones") or metadata.get("coverage_zone") or []
if isinstance(coverage_zones, str):
coverage_zones = [coverage_zones]
acquired_bbox = metadata.get("bbox_epsg4326")
if (
definition.contract.acquisition_mode == "bounded_api"
and isinstance(acquired_bbox, list)
and len(acquired_bbox) == 4
):
try:
acquired_scope = box(*(float(value) for value in acquired_bbox))
except (TypeError, ValueError):
continue
if not acquired_scope.is_valid or not acquired_scope.covers(selection):
continue
layer_matches = not layer_names or dataset.reference_layer_name in layer_names
zone_matches = not coverage_zones or zone in coverage_zones or "belgium" in coverage_zones
if layer_matches and zone_matches:
@@ -456,6 +469,7 @@ class CoverageRegistryService:
zone: str,
theme: str,
datasets: list[Dataset],
selection: Any,
) -> CoverageResolutionItem:
definitions = [
definition
@@ -481,6 +495,7 @@ class CoverageRegistryService:
definition,
theme,
zone,
selection,
)
materialized.extend(matches)
if matches:
@@ -535,7 +550,12 @@ class CoverageRegistryService:
)
items = [
CoverageRegistryService._resolve_item(zone=zone, theme=theme, datasets=datasets)
CoverageRegistryService._resolve_item(
zone=zone,
theme=theme,
datasets=datasets,
selection=selection,
)
for zone in zones
for theme in requested_themes
]
@@ -180,6 +180,47 @@ def test_statbel_population_materialization_does_not_masquerade_as_admin_data()
assert population.materialized_dataset_ids == [statbel_id]
def test_bounded_api_materialization_only_covers_its_persisted_bbox() -> None:
project_id = uuid4()
dataset_id = uuid4()
dataset = SimpleNamespace(
id=dataset_id,
status="ready",
source_name="spw_picc",
reference_layer_name="buildings",
source_metadata={
"coverage_zones": ["wallonia"],
"bbox_epsg4326": [4.55, 50.58, 4.56, 50.59],
},
)
session = FakeSession(
project=SimpleNamespace(id=project_id),
areas=[
scope_area("Belgium land", box(2.5, 49.5, 6.4, 51.5)),
scope_area("Wallonia", box(2.5, 49.5, 6.4, 50.8)),
],
datasets=[dataset],
)
inside = CoverageRegistryService.resolve(
session,
project_id,
CoverageBBox(minx=4.551, miny=50.581, maxx=4.559, maxy=50.589),
["buildings"],
)
outside = CoverageRegistryService.resolve(
session,
project_id,
CoverageBBox(minx=4.7, miny=50.6, maxx=4.71, maxy=50.61),
["buildings"],
)
assert inside.items[0].status == "operational"
assert inside.items[0].materialized_dataset_ids == [dataset_id]
assert outside.items[0].status == "partial"
assert outside.items[0].materialized_dataset_ids == []
def test_mixed_land_and_north_sea_selection_remains_split() -> None:
project_id = uuid4()
project = SimpleNamespace(id=project_id)