From dc677c254bca64fe59d65c0be9467802bfcb4eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Vuilleumier?= Date: Mon, 7 Oct 2024 15:25:37 +0200 Subject: [PATCH] Support i18n titles in cascaded layers Remote WMTS layers do not cascade i18n titles and abstracts (since the language is set in the GetCapabilities request and we have only one capabilities URL per cascaded WMTS stores). So we add the possibility to hardcode i18n titles and abstracts when publishing a layer --- geoservercloud/geoservercloud.py | 20 ++++++---- geoservercloud/templates.py | 6 +++ tests/test_cascaded_wmts.py | 64 +++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/geoservercloud/geoservercloud.py b/geoservercloud/geoservercloud.py index fcd3f28..c5ded87 100644 --- a/geoservercloud/geoservercloud.py +++ b/geoservercloud/geoservercloud.py @@ -316,16 +316,17 @@ def create_wmts_layer( native_layer: str, published_layer: str | None = None, epsg: int = 4326, - ) -> Response | None: + international_title: dict[str, str] | None = None, + international_abstract: dict[str, str] | None = None, + ) -> Response: """ - Publish a remote WMTS layer if it does not already exist. + Publish a remote WMTS layer (first delete it if it already exists) """ if not published_layer: published_layer = native_layer - if self.resource_exists( - f"/rest/workspaces/{workspace}/wmtsstores/{wmts_store}/layers/{published_layer}.json" - ): - return None + resource_path = f"/rest/workspaces/{workspace}/wmtsstores/{wmts_store}/layers/{published_layer}.json" + if self.resource_exists(resource_path): + self.delete_request(resource_path, params={"recurse": "true"}) wmts_store_path = f"/rest/workspaces/{workspace}/wmtsstores/{wmts_store}.json" capabilities_url = ( self.get_request(wmts_store_path) @@ -337,7 +338,12 @@ def create_wmts_layer( path = f"/rest/workspaces/{workspace}/wmtsstores/{wmts_store}/layers.json" payload = Templates.wmts_layer( - published_layer, native_layer, wgs84_bbox=wgs84_bbox, epsg=epsg + published_layer, + native_layer, + wgs84_bbox=wgs84_bbox, + epsg=epsg, + international_title=international_title, + international_abstract=international_abstract, ) return self.post_request(path, json=payload) diff --git a/geoservercloud/templates.py b/geoservercloud/templates.py index 608106a..addea36 100644 --- a/geoservercloud/templates.py +++ b/geoservercloud/templates.py @@ -264,6 +264,8 @@ def wmts_layer( native_name: str, epsg: int = 4326, wgs84_bbox: tuple[float, float, float, float] | None = None, + international_title: dict[str, str] | None = None, + international_abstract: dict[str, str] | None = None, ) -> dict[str, dict[str, Any]]: template = { "wmtsLayer": { @@ -293,6 +295,10 @@ def wmts_layer( "miny": wgs84_bbox[1], "maxy": wgs84_bbox[3], } + if international_title: + template["wmtsLayer"]["internationalTitle"] = international_title + if international_abstract: + template["wmtsLayer"]["internationalAbstract"] = international_abstract return template @staticmethod diff --git a/tests/test_cascaded_wmts.py b/tests/test_cascaded_wmts.py index ee7a12f..bcc6e40 100644 --- a/tests/test_cascaded_wmts.py +++ b/tests/test_cascaded_wmts.py @@ -148,18 +148,78 @@ def test_create_wmts_layer( assert response.status_code == 201 -def test_create_wmts_layer_already_exists(geoserver: GeoServerCloud) -> None: +def test_create_wmts_layer_already_exists( + geoserver: GeoServerCloud, wmts_layer_payload: dict[str, dict[str, Any]] +) -> None: with responses.RequestsMock() as rsps: rsps.get( f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}/layers/{LAYER}.json", status=200, ) + rsps.delete( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}/layers/{LAYER}.json", + status=200, + match=[responses.matchers.query_param_matcher({"recurse": "true"})], + ) + rsps.get( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}.json", + status=200, + json={"wmtsStore": {"capabilitiesURL": CAPABILITIES_URL}}, + ) + rsps.get( + CAPABILITIES_URL, + status=200, + body=CAPABILITIES, + headers={"Content-Type": "application/xml"}, + ) + rsps.post( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}/layers.json", + match=[responses.matchers.json_params_matcher(wmts_layer_payload)], + status=201, + ) + response = geoserver.create_wmts_layer( + workspace=WORKSPACE, + wmts_store=STORE, + native_layer=NATIVE_LAYER, + published_layer=LAYER, + ) + assert response.status_code == 201 + + +def test_create_wmts_layer_international_title( + geoserver: GeoServerCloud, wmts_layer_payload: dict[str, dict[str, Any]] +) -> None: + wmts_layer_payload["wmtsLayer"]["internationalTitle"] = {"en": "Title"} + wmts_layer_payload["wmtsLayer"]["internationalAbstract"] = {"en": "Abstract"} + with responses.RequestsMock() as rsps: + rsps.get( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}/layers/{LAYER}.json", + status=404, + ) + rsps.get( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}.json", + status=200, + json={"wmtsStore": {"capabilitiesURL": CAPABILITIES_URL}}, + ) + rsps.get( + CAPABILITIES_URL, + status=200, + body=CAPABILITIES, + headers={"Content-Type": "application/xml"}, + ) + rsps.post( + f"{geoserver.url}/rest/workspaces/{WORKSPACE}/wmtsstores/{STORE}/layers.json", + match=[responses.matchers.json_params_matcher(wmts_layer_payload)], + status=201, + ) response = geoserver.create_wmts_layer( workspace=WORKSPACE, wmts_store=STORE, native_layer=NATIVE_LAYER, published_layer=LAYER, + international_title={"en": "Title"}, + international_abstract={"en": "Abstract"}, ) - assert response is None + assert response.status_code == 201