feat: complete governed Walloon coverage sources
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-22 03:39:08 +02:00
parent 17d4442e60
commit c2101ea8f9
37 changed files with 1813 additions and 45 deletions
@@ -460,6 +460,75 @@ class OfficialVectorAcquisitionService:
identity_field="GEOREF_ID",
requires_coverage_area=True,
),
OfficialVectorProduct(
key="spw_flood_hazard_2021",
display_name="Waalse overstromingsgevaarkaart 2021",
theme="flood_hazard",
provider="Service public de Wallonie",
source_name="spw_flood_hazard",
reference_layer_name="flood_hazard",
service_type="ArcGIS REST",
collection="2",
source_crs="EPSG:31370",
source_version="2021-03-04",
observation_label="Juridisch geldende toestand 2021",
authority_level="authoritative",
catalog_url=(
"https://geoportail.wallonie.be/catalogue/"
"14084108-2c7b-4091-b62d-ff0fc235213a.html"
),
attribution="Service public de Wallonie (SPW) - Cartographie de l'alea d'inondation",
license_note="CC BY 4.0; cite SPW and identify modifications.",
limitation_message=(
"Juridische gevarenkaart voor overstroming door waterloopoverloop en afstroming. "
"Dit is geen actuele overstroming, gemeten waterdiepte, voorspelling of bathymetrie."
),
source="SPW flood-hazard ArcGIS REST",
observed_at=datetime(2021, 3, 4, tzinfo=UTC),
valid_from=datetime(2021, 3, 4, tzinfo=UTC),
valid_to=None,
primary_metric={
"metric_key": "flood_hazard_area",
"method": "intersection_area",
"label": "Oppervlakte met overstromingsgevaar",
"unit": "ha",
"geometry_dimension": 2,
"is_estimate": False,
},
selection_metrics=(
{
"metric_key": "flood_hazard_high_area",
"method": "intersection_area",
"label": "Hoog overstromingsgevaar",
"unit": "ha",
"geometry_dimension": 2,
"filter_property": "CLASSEMENT",
"filter_values": [130, 230, 330, "130", "230", "330"],
},
{
"metric_key": "flood_hazard_medium_area",
"method": "intersection_area",
"label": "Middelgroot overstromingsgevaar",
"unit": "ha",
"geometry_dimension": 2,
"filter_property": "CLASSEMENT",
"filter_values": [120, 220, 320, "120", "220", "320"],
},
{
"metric_key": "flood_hazard_low_area",
"method": "intersection_area",
"label": "Laag overstromingsgevaar",
"unit": "ha",
"geometry_dimension": 2,
"filter_property": "CLASSEMENT",
"filter_values": [110, 210, 310, "110", "210", "310"],
},
),
coverage_zones=("wallonia",),
endpoint_kind="spw_flood_arcgis",
identity_field="LOCALID",
requires_coverage_area=True,
),
OfficialVectorProduct(
key="urbis_buildings",
display_name="UrbIS buildings",
@@ -869,6 +938,12 @@ class OfficialVectorAcquisitionService:
message="Bounded SPW PICC acquisition is disabled",
status_code=503,
)
if product.endpoint_kind == "spw_flood_arcgis" and not settings.spw_flood_hazard_enabled:
raise AppError(
code="SPW_FLOOD_HAZARD_NOT_CONFIGURED",
message="Bounded SPW flood-hazard acquisition is disabled",
status_code=503,
)
if product.endpoint_kind == "urbis_wfs" and not settings.urbis_enabled:
raise AppError(
code="URBIS_NOT_CONFIGURED",
@@ -1132,7 +1207,11 @@ class OfficialVectorAcquisitionService:
"f": "geojson",
}
)
base = settings.spw_picc_mapserver_url.rstrip("/")
base = (
settings.spw_flood_hazard_mapserver_url
if product.endpoint_kind == "spw_flood_arcgis"
else settings.spw_picc_mapserver_url
).rstrip("/")
return f"{base}/{product.collection}/query?{query}"
@staticmethod
@@ -1178,7 +1257,7 @@ class OfficialVectorAcquisitionService:
tuple(scope_metric.bounds),
start_index,
)
if product.endpoint_kind == "spw_arcgis":
if product.endpoint_kind in {"spw_arcgis", "spw_flood_arcgis"}:
return OfficialVectorAcquisitionService._spw_url(
settings,
product,
@@ -1209,6 +1288,7 @@ class OfficialVectorAcquisitionService:
"bwk_wfs": settings.bwk_wfs_url,
"dov_wfs": settings.dov_soil_wfs_url,
"spw_arcgis": settings.spw_picc_mapserver_url,
"spw_flood_arcgis": settings.spw_flood_hazard_mapserver_url,
"urbis_wfs": settings.urbis_wfs_url,
}.get(product.endpoint_kind)
if configured_url is None:
@@ -1220,7 +1300,7 @@ class OfficialVectorAcquisitionService:
base = urlparse(configured_url)
expected_path = (
f"{base.path.rstrip('/')}/{product.collection}/query"
if product.endpoint_kind == "spw_arcgis"
if product.endpoint_kind in {"spw_arcgis", "spw_flood_arcgis"}
else base.path
)
if (
@@ -1361,7 +1441,7 @@ class OfficialVectorAcquisitionService:
scope_metric: Any,
coverage_scope: str,
) -> dict[str, Any] | None:
if product.endpoint_kind in {"spw_arcgis", "urbis_wfs"}:
if product.endpoint_kind in {"spw_arcgis", "spw_flood_arcgis", "urbis_wfs"}:
return OfficialVectorAcquisitionService._normalize_regional_feature(
product,
feature,
@@ -1601,7 +1681,7 @@ class OfficialVectorAcquisitionService:
)
start_index += returned_count
arcgis_has_more = payload.get("exceededTransferLimit") is True
if product.endpoint_kind == "spw_arcgis":
if product.endpoint_kind in {"spw_arcgis", "spw_flood_arcgis"}:
if arcgis_has_more and returned_count == 0:
raise AppError(
code="OFFICIAL_VECTOR_PROVIDER_INCOMPLETE_RESPONSE",