123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
"""Canonical operator scope definitions for GeoIntel.
|
|
|
|
These definitions describe administrative/policy scopes only. They do not
|
|
claim that a policy boundary equals a cultural or physical landscape region.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ScopeMember:
|
|
name: str
|
|
nis_code: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GeographicScope:
|
|
key: str
|
|
display_name: str
|
|
project_name: str
|
|
project_region: str
|
|
area_name: str
|
|
authority_name: str
|
|
authority_url: str
|
|
scope_type: str
|
|
limitation_message: str
|
|
members: tuple[ScopeMember, ...]
|
|
|
|
@property
|
|
def nis_codes(self) -> tuple[str, ...]:
|
|
return tuple(member.nis_code for member in self.members)
|
|
|
|
|
|
MOL_SCOPE = GeographicScope(
|
|
key="mol",
|
|
display_name="Mol",
|
|
project_name="Mol Municipality Workbench",
|
|
project_region="Mol, Kempen",
|
|
area_name="Gemeente Mol - officiële grens",
|
|
authority_name="Digitaal Vlaanderen VRBG",
|
|
authority_url="https://geo.api.vlaanderen.be/VRBG/ogc/features/v1/collections/Refgem/items",
|
|
scope_type="municipality",
|
|
limitation_message="Officiële gemeentegrens; dit is geen perceelsgrens.",
|
|
members=(ScopeMember("Mol", "13025"),),
|
|
)
|
|
|
|
|
|
KEMPEN_TRANSPORT_REGION_SCOPE = GeographicScope(
|
|
key="kempen-transport-region",
|
|
display_name="Kempen (28 gemeenten)",
|
|
project_name="Kempen Regional Workbench",
|
|
project_region="Vervoerregio Kempen, Vlaanderen",
|
|
area_name="Vervoerregio Kempen - officiële operationele grens",
|
|
authority_name="Vlaamse overheid - Vervoerregio Kempen",
|
|
authority_url=(
|
|
"https://www.vlaanderen.be/mobiliteitsprofessionals/personenvervoer/"
|
|
"basisbereikbaarheid/mobiliteitsuitdagingen-regionaal-aanpakken/"
|
|
"vervoerregios/over-de-vervoerregio-kempen"
|
|
),
|
|
scope_type="transport_region",
|
|
limitation_message=(
|
|
"Operationele beleidsgrens van de Vlaamse vervoerregio Kempen; "
|
|
"geen claim over de ruimere culturele, landschappelijke of historische Kempen."
|
|
),
|
|
members=(
|
|
ScopeMember("Arendonk", "13001"),
|
|
ScopeMember("Baarle-Hertog", "13002"),
|
|
ScopeMember("Balen", "13003"),
|
|
ScopeMember("Beerse", "13004"),
|
|
ScopeMember("Dessel", "13006"),
|
|
ScopeMember("Geel", "13008"),
|
|
ScopeMember("Grobbendonk", "13010"),
|
|
ScopeMember("Herentals", "13011"),
|
|
ScopeMember("Herenthout", "13012"),
|
|
ScopeMember("Herselt", "13013"),
|
|
ScopeMember("Hoogstraten", "13014"),
|
|
ScopeMember("Hulshout", "13016"),
|
|
ScopeMember("Kasterlee", "13017"),
|
|
ScopeMember("Laakdal", "13053"),
|
|
ScopeMember("Lille", "13019"),
|
|
ScopeMember("Meerhout", "13021"),
|
|
ScopeMember("Merksplas", "13023"),
|
|
ScopeMember("Mol", "13025"),
|
|
ScopeMember("Nijlen", "12026"),
|
|
ScopeMember("Olen", "13029"),
|
|
ScopeMember("Oud-Turnhout", "13031"),
|
|
ScopeMember("Ravels", "13035"),
|
|
ScopeMember("Retie", "13036"),
|
|
ScopeMember("Rijkevorsel", "13037"),
|
|
ScopeMember("Turnhout", "13040"),
|
|
ScopeMember("Vorselaar", "13044"),
|
|
ScopeMember("Vosselaar", "13046"),
|
|
ScopeMember("Westerlo", "13049"),
|
|
),
|
|
)
|
|
|
|
|
|
GEOGRAPHIC_SCOPES = {
|
|
scope.key: scope
|
|
for scope in (MOL_SCOPE, KEMPEN_TRANSPORT_REGION_SCOPE)
|
|
}
|
|
|
|
|
|
def validate_scope(scope: GeographicScope) -> None:
|
|
if not scope.key or not scope.project_name or not scope.area_name:
|
|
raise ValueError("Geographic scope identity fields must not be empty")
|
|
if len(scope.members) == 0:
|
|
raise ValueError(f"Geographic scope {scope.key} has no members")
|
|
names = [member.name.casefold() for member in scope.members]
|
|
codes = [member.nis_code for member in scope.members]
|
|
if len(names) != len(set(names)):
|
|
raise ValueError(f"Geographic scope {scope.key} contains duplicate municipality names")
|
|
if len(codes) != len(set(codes)):
|
|
raise ValueError(f"Geographic scope {scope.key} contains duplicate NIS codes")
|
|
if any(len(code) != 5 or not code.isdigit() for code in codes):
|
|
raise ValueError(f"Geographic scope {scope.key} contains an invalid NIS code")
|
|
|
|
|
|
for _scope in GEOGRAPHIC_SCOPES.values():
|
|
validate_scope(_scope)
|