diff --git a/config/settings/base.py b/config/settings/base.py
index 0dd4af0..b717a6c 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -94,6 +94,7 @@
"metadata_catalogue.core",
"metadata_catalogue.datasets",
"metadata_catalogue.datasets.csw",
+ "metadata_catalogue.datasets.geoapi",
]
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
@@ -310,3 +311,8 @@
"repository": "metadata_catalogue.datasets.repository.DatasetsRepository",
"mappings": "metadata_catalogue.datasets.mappings",
}
+
+GEOAPI = {
+ "cors": False,
+ "gzip": False,
+}
diff --git a/config/urls.py b/config/urls.py
index eb4dbac..f72fdc5 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -15,6 +15,7 @@
path("accounts/", include("allauth.urls")),
path("ht/", include("health_check.urls")),
path("csw/", include("metadata_catalogue.datasets.csw.urls")),
+ path("geoapi/", include("metadata_catalogue.datasets.geoapi.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/metadata_catalogue/datasets/csw/models.py b/metadata_catalogue/datasets/csw/models.py
index 5166027..a14af6f 100644
--- a/metadata_catalogue/datasets/csw/models.py
+++ b/metadata_catalogue/datasets/csw/models.py
@@ -7,7 +7,6 @@
class CSWConfig(SingletonModel):
- language = models.CharField(max_length=7, null=True, blank=True)
max_records = models.IntegerField(default=10)
profiles = models.TextField(default="apiso", blank=True)
pretty_print = models.BooleanField(default=False)
@@ -21,7 +20,7 @@ def get_config(self, url=""):
"home": ".",
"mimetype": "application/xml; charset=UTF-8",
"encoding": "UTF-8",
- "language": self.language or "en-US",
+ "language": info.language or "en-US",
"maxrecords": str(self.max_records),
"pretty_print": "true" if self.pretty_print else "false",
"url": url,
diff --git a/metadata_catalogue/datasets/geoapi/__init__.py b/metadata_catalogue/datasets/geoapi/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/metadata_catalogue/datasets/geoapi/admin.py b/metadata_catalogue/datasets/geoapi/admin.py
new file mode 100644
index 0000000..3d82372
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/admin.py
@@ -0,0 +1,6 @@
+from django.contrib import admin
+from solo.admin import SingletonModelAdmin
+
+from .models import GeoAPIConfig
+
+admin.site.register(GeoAPIConfig, SingletonModelAdmin)
diff --git a/metadata_catalogue/datasets/geoapi/apps.py b/metadata_catalogue/datasets/geoapi/apps.py
new file mode 100644
index 0000000..e9e1aa9
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/apps.py
@@ -0,0 +1,7 @@
+from django.apps import AppConfig
+from django.utils.translation import gettext_lazy as _
+
+
+class GeoapiConfig(AppConfig):
+ name = "metadata_catalogue.datasets.geoapi"
+ verbose_name = _("GeoAPI")
diff --git a/metadata_catalogue/datasets/geoapi/migrations/0001_initial.py b/metadata_catalogue/datasets/geoapi/migrations/0001_initial.py
new file mode 100644
index 0000000..c26b17f
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# Generated by Django 4.2.6 on 2023-11-13 12:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ initial = True
+
+ dependencies = []
+
+ operations = [
+ migrations.CreateModel(
+ name="GeoAPIConfig",
+ fields=[
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("max_records", models.IntegerField(default=10)),
+ ("pretty_print", models.BooleanField(default=False)),
+ ("map_url", models.URLField(default="https://tile.openstreetmap.org/{z}/{x}/{y}.png")),
+ (
+ "map_attribution",
+ models.TextField(
+ default='© OpenStreetMap contributors'
+ ),
+ ),
+ ],
+ options={
+ "abstract": False,
+ },
+ ),
+ ]
diff --git a/metadata_catalogue/datasets/geoapi/migrations/__init__.py b/metadata_catalogue/datasets/geoapi/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/metadata_catalogue/datasets/geoapi/models.py b/metadata_catalogue/datasets/geoapi/models.py
new file mode 100644
index 0000000..368ee57
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/models.py
@@ -0,0 +1,77 @@
+from pathlib import Path
+
+from django.apps import apps
+from django.db import models
+from solo.models import SingletonModel
+
+from ..libs.utils import safe_get
+
+
+class GeoAPIConfig(SingletonModel):
+ max_records = models.IntegerField(default=10)
+ pretty_print = models.BooleanField(default=False)
+ map_url = models.URLField(default="https://tile.openstreetmap.org/{z}/{x}/{y}.png")
+ map_attribution = models.TextField(
+ default='© OpenStreetMap contributors'
+ )
+
+ def get_config(self, url=""):
+ ServiceInfo = apps.get_model("datasets", "ServiceInfo")
+ Dataset = apps.get_model("datasets", "Dataset")
+ info = ServiceInfo.objects.select_related("contact", "license", "provider").get()
+
+ resources = {id: value for id, value in Dataset.objects.select_related("metadata").all().as_geoapi_resource()}
+
+ return {
+ "server": {
+ "mimetype": "application/xml; charset=UTF-8",
+ "encoding": "utf-8",
+ "language": info.language or "en-US",
+ "limit": str(self.max_records),
+ "pretty_print": self.pretty_print,
+ "url": url,
+ "templates": {"static": str(Path(__name__).parent / "statics" / "geoapi")},
+ "map": {
+ "url": self.map_url,
+ "attribute": self.map_attribution,
+ },
+ },
+ "logging": {
+ "level": "DEBUG",
+ },
+ "metadata": {
+ "identification": {
+ "title": info.identification_title,
+ "description": info.identification_abstract,
+ "keywords": info.identification_keywords.split(",") if info.identification_keywords else "",
+ "keywords_type": "theme",
+ "terms_of_service": info.identification_accessconstraints,
+ "url": "",
+ },
+ "license": {
+ "name": info.license.name if info.license else "",
+ "url": info.license.url if info.license else "",
+ },
+ "provider": {
+ "name": info.provider,
+ "url": "",
+ },
+ "contact": {
+ "name": str(info.contact),
+ "position": safe_get(info.contact, "position"),
+ "address": safe_get(info.contact, "delivery_point"),
+ "city": safe_get(info.contact, "city"),
+ "stateorprovince": safe_get(info.contact, "country"),
+ "postalcode": safe_get(info.contact, "postal_code"),
+ "country": safe_get(info.contact, "country"),
+ "phone": safe_get(info.contact, "phone"),
+ "fax": safe_get(info.contact, "phone"),
+ "email": safe_get(info.contact, "email"),
+ "url": "",
+ "hours": info.contact_hours or "",
+ "instructions": info.contact_instructions or "",
+ "role": "pointOfContact",
+ },
+ },
+ "resources": resources,
+ }
diff --git a/metadata_catalogue/datasets/geoapi/urls.py b/metadata_catalogue/datasets/geoapi/urls.py
new file mode 100644
index 0000000..24354b6
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/urls.py
@@ -0,0 +1,158 @@
+from django.conf import settings
+from django.conf.urls.static import static
+from django.urls import path
+
+from . import views
+
+urlpatterns = [
+ path("", views.landing_page, name="landing-page"),
+ path("openapi/", views.openapi, name="openapi"),
+ path("conformance/", views.conformance, name="conformance"),
+ path("collections/", views.collections, name="collections"),
+ path(
+ "collections/",
+ views.collections,
+ name="collection-detail",
+ ),
+ path(
+ "collections//queryables/",
+ views.collection_queryables,
+ name="collection-queryables",
+ ),
+ path(
+ "collections//items/",
+ views.collection_items,
+ name="collection-items",
+ ),
+ path(
+ "collections//items/",
+ views.collection_item,
+ name="collection-item",
+ ),
+ path(
+ "collections//coverage/",
+ views.collection_coverage,
+ name="collection-coverage",
+ ),
+ path(
+ "collections//coverage/domainset/", # noqa
+ views.collection_coverage_domainset,
+ name="collection-coverage-domainset",
+ ),
+ path(
+ "collections//coverage/rangetype/", # noqa
+ views.collection_coverage_rangetype,
+ name="collection-coverage-rangetype",
+ ),
+ path(
+ "collections//map",
+ views.collection_map,
+ name="collection-map",
+ ),
+ path(
+ "collections//styles//map",
+ views.collection_style_map,
+ name="collection-style-map",
+ ),
+ path(
+ "collections//tiles/",
+ views.collection_tiles,
+ name="collection-tiles",
+ ),
+ path(
+ "collections//tiles/",
+ views.collection_tiles_metadata,
+ name="collection-tiles-metadata",
+ ),
+ path(
+ "collections//tiles//metadata",
+ views.collection_tiles_metadata,
+ name="collection-tiles-metadata",
+ ),
+ path(
+ "collections//tiles/\
+ ///",
+ views.collection_item_tiles,
+ name="collection-item-tiles",
+ ),
+ path(
+ "collections//position",
+ views.get_collection_edr_query,
+ name="collection-edr-position",
+ ),
+ path(
+ "collections//area",
+ views.get_collection_edr_query,
+ name="collection-edr-area",
+ ),
+ path(
+ "collections//cube",
+ views.get_collection_edr_query,
+ name="collection-edr-cube",
+ ),
+ path(
+ "collections//radius",
+ views.get_collection_edr_query,
+ name="collection-edr-radius",
+ ),
+ path(
+ "collections//trajectory",
+ views.get_collection_edr_query,
+ name="collection-edr-trajectory",
+ ),
+ path(
+ "collections//corridor",
+ views.get_collection_edr_query,
+ name="collection-edr-corridor",
+ ),
+ path(
+ "collections//instances//position",
+ views.get_collection_edr_query,
+ name="collection-edr-instance-position",
+ ),
+ path(
+ "collections//instances//area",
+ views.get_collection_edr_query,
+ name="collection-edr-instance-area",
+ ),
+ path(
+ "collections//instances//cube",
+ views.get_collection_edr_query,
+ name="collection-edr-instance-cube",
+ ),
+ path(
+ "collections//instances//radius",
+ views.get_collection_edr_query,
+ name="collection-edr-instance-radius",
+ ),
+ path(
+ "collections//instances//trajectory", # noqa
+ views.get_collection_edr_query,
+ name="collection-edr-instance-trajectory",
+ ),
+ path(
+ "collections//instances//corridor",
+ views.get_collection_edr_query,
+ name="collection-edr-instance-corridor",
+ ),
+ path("processes/", views.processes, name="processes"),
+ path("processes/", views.processes, name="process-detail"),
+ path("jobs/", views.jobs, name="jobs"),
+ path("jobs/", views.jobs, name="job"),
+ path(
+ "jobs//results/",
+ views.job_results,
+ name="job-results",
+ ),
+ path(
+ "jobs//results/",
+ views.job_results_resource,
+ name="job-results-resource",
+ ),
+ path("stac/", views.stac_catalog_root, name="stac-catalog-root"),
+ path("stac/", views.stac_catalog_path, name="stac-catalog-path"),
+ path("stac/search/", views.stac_catalog_search, name="stac-catalog-search"),
+]
+
+# Add static URLs to serve pygeoapi statics
+urlpatterns += static(settings.STATIC_URL, document_root=str(settings.APPS_DIR / "static" / "geoapi"))
diff --git a/metadata_catalogue/datasets/geoapi/views.py b/metadata_catalogue/datasets/geoapi/views.py
new file mode 100644
index 0000000..0df3ee9
--- /dev/null
+++ b/metadata_catalogue/datasets/geoapi/views.py
@@ -0,0 +1,469 @@
+# =================================================================
+#
+# Authors: Francesco Bartoli
+# Luca Delucchi
+# Krishna Lodha
+# Tom Kralidis
+#
+# Copyright (c) 2022 Francesco Bartoli
+# Copyright (c) 2022 Luca Delucchi
+# Copyright (c) 2022 Krishna Lodha
+# Copyright (c) 2022 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+"""Integration module for Django"""
+from collections.abc import Mapping
+from typing import Dict, Optional, Tuple
+
+from django.http import HttpRequest, HttpResponse
+from pygeoapi.api import API
+
+from .models import GeoAPIConfig
+
+
+def landing_page(request: HttpRequest) -> HttpResponse:
+ """
+ OGC API landing page endpoint
+
+ :request Django HTTP Request
+
+ :returns: Django HTTP Response
+ """
+
+ response_ = _feed_response(request, "landing_page")
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def openapi(request: HttpRequest) -> HttpResponse:
+ """
+ OpenAPI endpoint
+
+ :request Django HTTP Request
+
+ :returns: Django HTTP Response
+ """
+
+ response_ = _feed_response(request, "openapi_")
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def conformance(request: HttpRequest) -> HttpResponse:
+ """
+ OGC API conformance endpoint
+
+ :request Django HTTP Request
+
+ :returns: Django HTTP Response
+ """
+
+ response_ = _feed_response(request, "conformance")
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collections(request: HttpRequest, collection_id: str | None = None) -> HttpResponse:
+ """
+ OGC API collections endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP Response
+ """
+
+ response_ = _feed_response(request, "describe_collections", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_queryables(request: HttpRequest, collection_id: str | None = None) -> HttpResponse:
+ """
+ OGC API collections queryables endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP Response
+ """
+
+ response_ = _feed_response(request, "get_collection_queryables", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_items(request: HttpRequest, collection_id: str) -> HttpResponse:
+ """
+ OGC API collections items endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP response
+ """
+
+ if request.method == "GET":
+ response_ = _feed_response(
+ request,
+ "get_collection_items",
+ collection_id,
+ )
+ elif request.method == "POST":
+ if request.content_type is not None:
+ if request.content_type == "application/geo+json":
+ response_ = _feed_response(request, "manage_collection_item", request, "create", collection_id)
+ else:
+ response_ = _feed_response(request, "post_collection_items", request, collection_id)
+ elif request.method == "OPTIONS":
+ response_ = _feed_response(request, "manage_collection_item", request, "options", collection_id)
+
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_map(request: HttpRequest, collection_id: str):
+ """
+ OGC API - Maps map render endpoint
+
+ :param collection_id: collection identifier
+
+ :returns: HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_map", collection_id)
+
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_style_map(request: HttpRequest, collection_id: str, style_id: str = None):
+ """
+ OGC API - Maps map render endpoint
+
+ :param collection_id: collection identifier
+ :param collection_id: style identifier
+
+ :returns: HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_map", collection_id, style_id)
+
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_item(request: HttpRequest, collection_id: str, item_id: str) -> HttpResponse:
+ """
+ OGC API collections items endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+ :param item_id: item identifier
+
+ :returns: Django HTTP response
+ """
+
+ if request.method == "GET":
+ response_ = _feed_response(request, "get_collection_item", collection_id, item_id)
+ elif request.method == "PUT":
+ response_ = _feed_response(request, "manage_collection_item", request, "update", collection_id, item_id)
+ elif request.method == "DELETE":
+ response_ = _feed_response(request, "manage_collection_item", request, "delete", collection_id, item_id)
+ elif request.method == "OPTIONS":
+ response_ = _feed_response(request, "manage_collection_item", request, "options", collection_id, item_id)
+
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_coverage(request: HttpRequest, collection_id: str) -> HttpResponse:
+ """
+ OGC API - Coverages coverage endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_coverage", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_coverage_domainset(request: HttpRequest, collection_id: str) -> HttpResponse:
+ """
+ OGC API - Coverages coverage domainset endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_coverage_domainset", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_coverage_rangetype(request: HttpRequest, collection_id: str) -> HttpResponse:
+ """
+ OGC API - Coverages coverage rangetype endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_coverage_rangetype", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_tiles(request: HttpRequest, collection_id: str) -> HttpResponse:
+ """
+ OGC API - Tiles collection tiles endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_collection_tiles", collection_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_tiles_metadata(request: HttpRequest, collection_id: str, tileMatrixSetId: str) -> HttpResponse:
+ """
+ OGC API - Tiles collection tiles metadata endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+ :param tileMatrixSetId: identifier of tile matrix set
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(
+ request,
+ "get_collection_tiles_metadata",
+ collection_id,
+ tileMatrixSetId,
+ )
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def collection_item_tiles(
+ request: HttpRequest,
+ collection_id: str,
+ tileMatrixSetId: str,
+ tileMatrix: str,
+ tileRow: str,
+ tileCol: str,
+) -> HttpResponse:
+ """
+ OGC API - Tiles collection tiles data endpoint
+
+ :request Django HTTP Request
+ :param collection_id: collection identifier
+ :param tileMatrixSetId: identifier of tile matrix set
+ :param tileMatrix: identifier of {z} matrix index
+ :param tileRow: identifier of {y} matrix index
+ :param tileCol: identifier of {x} matrix index
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(
+ request,
+ "get_collection_tiles_metadata",
+ collection_id,
+ tileMatrixSetId,
+ tileMatrix,
+ tileRow,
+ tileCol,
+ )
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def processes(request: HttpRequest, process_id: str | None = None) -> HttpResponse:
+ """
+ OGC API - Processes description endpoint
+
+ :request Django HTTP Request
+ :param process_id: process identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "describe_processes", process_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def jobs(request: HttpRequest, job_id: str | None = None) -> HttpResponse:
+ """
+ OGC API - Jobs endpoint
+
+ :request Django HTTP Request
+ :param process_id: process identifier
+ :param job_id: job identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_jobs", job_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def job_results(request: HttpRequest, job_id: str | None = None) -> HttpResponse:
+ """
+ OGC API - Job result endpoint
+
+ :request Django HTTP Request
+ :param job_id: job identifier
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_job_result", job_id)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def job_results_resource(request: HttpRequest, process_id: str, job_id: str, resource: str) -> HttpResponse:
+ """
+ OGC API - Job result resource endpoint
+
+ :request Django HTTP Request
+ :param job_id: job identifier
+ :param resource: job resource
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_job_result_resource", job_id, resource)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def get_collection_edr_query(request: HttpRequest, collection_id: str, instance_id: str) -> HttpResponse:
+ """
+ OGC API - EDR endpoint
+
+ :request Django HTTP Request
+ :param job_id: job identifier
+ :param resource: job resource
+
+ :returns: Django HTTP response
+ """
+
+ query_type = request.path.split("/")[-1]
+ response_ = _feed_response(request, "get_collection_edr_query", collection_id, instance_id, query_type)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def stac_catalog_root(request: HttpRequest) -> HttpResponse:
+ """
+ STAC root endpoint
+
+ :request Django HTTP Request
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_stac_root")
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def stac_catalog_path(request: HttpRequest, path: str) -> HttpResponse:
+ """
+ STAC path endpoint
+
+ :request Django HTTP Request
+ :param path: path
+
+ :returns: Django HTTP response
+ """
+
+ response_ = _feed_response(request, "get_stac_path", path)
+ response = _to_django_response(*response_)
+
+ return response
+
+
+def stac_catalog_search(request: HttpRequest) -> HttpResponse:
+ pass
+
+
+def _feed_response(request: HttpRequest, api_definition: str, *args, **kwargs) -> tuple[dict, int, str]:
+ """Use pygeoapi api to process the input request"""
+
+ config = GeoAPIConfig.get_solo()
+ as_dict = config.get_config(request.scheme + "://" + request.get_host() + "/geoapi/")
+
+ api_ = API(as_dict, {})
+ api = getattr(api_, api_definition)
+ return api(request, *args, **kwargs)
+
+
+def _to_django_response(headers: Mapping, status_code: int, content: str) -> HttpResponse:
+ """Convert API payload to a django response"""
+
+ response = HttpResponse(content, status=status_code)
+
+ for key, value in headers.items():
+ response[key] = value
+ return response
diff --git a/metadata_catalogue/datasets/libs/geoapi/mapping.py b/metadata_catalogue/datasets/libs/geoapi/mapping.py
new file mode 100644
index 0000000..d34600c
--- /dev/null
+++ b/metadata_catalogue/datasets/libs/geoapi/mapping.py
@@ -0,0 +1,31 @@
+class ResourceMapping:
+ def __init__(self, dataset) -> None:
+ self.id = dataset.uuid
+ self.dataset = dataset
+
+ def as_resource(self):
+ return self.id, {
+ "type": "collection",
+ "visibility": "default",
+ "title": self.dataset.metadata.title,
+ "description": self.dataset.metadata.abstract,
+ "keywords": [],
+ "context": [],
+ "links": [
+ {"type": "application/zip", "rel": "canonical", "title": "Data", "href": self.dataset.fetch_url}
+ ],
+ "extents": {
+ "spatial": {
+ "bbox": self.dataset.metadata.bounding_box.extent,
+ "crs": self.dataset.metadata.bounding_box.srs.name,
+ }
+ },
+ "providers": [
+ {
+ "type": "feature",
+ "default": True,
+ "name": "CSV",
+ "editable": False,
+ }
+ ],
+ }
diff --git a/metadata_catalogue/datasets/managers.py b/metadata_catalogue/datasets/managers.py
index 93d9137..599f1c6 100644
--- a/metadata_catalogue/datasets/managers.py
+++ b/metadata_catalogue/datasets/managers.py
@@ -3,6 +3,7 @@
from . import logger
from .libs.csw.mapping import CSWMapping
from .libs.csw.query import Group
+from .libs.geoapi.mapping import ResourceMapping
SORT_CONFIG = {"title": "metadata__title", "csw_wkt_geometry": "metadata__bounding_box"}
@@ -30,6 +31,10 @@ def csw_sort(self, sort):
logger.warn(f"Not implemented! {sort}")
return self
+ def as_geoapi_resource(self, *args, warn=True, **kwargs):
+ logger.warn("DANGER: This method consumes the queryset and returns and array of items")
+ return [ResourceMapping(instance).as_resource() for instance in self]
+
class DatasetManager(models.Manager):
def get_queryset(self):
diff --git a/metadata_catalogue/datasets/migrations/0008_serviceinfo_language.py b/metadata_catalogue/datasets/migrations/0008_serviceinfo_language.py
new file mode 100644
index 0000000..31ff6a2
--- /dev/null
+++ b/metadata_catalogue/datasets/migrations/0008_serviceinfo_language.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.6 on 2023-11-13 12:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("datasets", "0007_serviceinfo_contact_hours_and_more"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="serviceinfo",
+ name="language",
+ field=models.CharField(blank=True, max_length=7, null=True),
+ ),
+ ]
diff --git a/metadata_catalogue/datasets/models.py b/metadata_catalogue/datasets/models.py
index 8644da4..2f9e680 100644
--- a/metadata_catalogue/datasets/models.py
+++ b/metadata_catalogue/datasets/models.py
@@ -388,3 +388,4 @@ class ServiceInfo(SingletonModel):
contact_instructions = models.TextField(null=True, blank=True, default="")
provider = models.ForeignKey("datasets.Organization", blank=True, null=True, on_delete=models.SET_NULL)
license = models.ForeignKey("datasets.License", on_delete=models.SET_NULL, null=True, blank=True)
+ language = models.CharField(max_length=7, null=True, blank=True)
diff --git a/metadata_catalogue/static/geoapi/css/default.css b/metadata_catalogue/static/geoapi/css/default.css
new file mode 100644
index 0000000..2f87fc9
--- /dev/null
+++ b/metadata_catalogue/static/geoapi/css/default.css
@@ -0,0 +1,66 @@
+.flat {
+ border: 0px;
+}
+
+header {
+ display: inline-block;
+}
+
+main {
+ background-color:white
+}
+
+.crumbs {
+ background-color:rgb(230, 230, 230);
+ padding: 6px;
+}
+
+.crumbs a {
+ padding: 0px 6px;
+ color:black;
+ text-decoration: none;
+/* text-transform: capitalize;*/
+}
+
+#items-map, #collection-map {
+ width: 100%;
+ height: 400px;
+}
+
+/* cancel mini-css header>button uppercase */
+header button, header [type="button"], header .button, header [role="button"] {
+ text-transform: none;
+}
+
+html, body {
+ background-color: #fff;
+}
+
+footer.sticky {
+ position: fixed;
+ width: 100%;
+}
+
+main {
+ padding-bottom: 65px; /* prevent from falling under the footer */
+}
+
+table:not(.horizontal) {
+ max-height: none;
+}
+
+mark.successful {
+ background-color: green;
+}
+
+mark.accepted {
+ background-color: default;
+}
+
+mark.failed {
+ background-color: red;
+}
+
+mark.running {
+ background-color: orange;
+}
diff --git a/metadata_catalogue/static/geoapi/img/favicon.ico b/metadata_catalogue/static/geoapi/img/favicon.ico
new file mode 100644
index 0000000..1e20f9c
Binary files /dev/null and b/metadata_catalogue/static/geoapi/img/favicon.ico differ
diff --git a/metadata_catalogue/static/geoapi/img/logo.png b/metadata_catalogue/static/geoapi/img/logo.png
new file mode 100644
index 0000000..0477111
Binary files /dev/null and b/metadata_catalogue/static/geoapi/img/logo.png differ
diff --git a/metadata_catalogue/static/geoapi/img/pygeoapi.png b/metadata_catalogue/static/geoapi/img/pygeoapi.png
new file mode 100644
index 0000000..0477111
Binary files /dev/null and b/metadata_catalogue/static/geoapi/img/pygeoapi.png differ
diff --git a/pdm.lock b/pdm.lock
index f8f69f1..6c49f8d 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -5,7 +5,27 @@
groups = ["default", "dev"]
strategy = ["cross_platform"]
lock_version = "4.4"
-content_hash = "sha256:2b38b66cdb8bc8b4c3cfa362a94690491ede742380b3b156460a1e60910e5c2b"
+content_hash = "sha256:77ac1138f398a6ab8b03d05cec2f24ec80ab70421c5b5f4832629d2d5bcb0337"
+
+[[package]]
+name = "affine"
+version = "2.4.0"
+requires_python = ">=3.7"
+summary = "Matrices describing affine transformation of the plane"
+files = [
+ {file = "affine-2.4.0-py3-none-any.whl", hash = "sha256:8a3df80e2b2378aef598a83c1392efd47967afec4242021a0b06b4c7cbc61a92"},
+ {file = "affine-2.4.0.tar.gz", hash = "sha256:a24d818d6a836c131976d22f8c27b8d3ca32d0af64c1d8d29deb7bafa4da1eea"},
+]
+
+[[package]]
+name = "annotated-types"
+version = "0.6.0"
+requires_python = ">=3.8"
+summary = "Reusable constraint types to use with typing.Annotated"
+files = [
+ {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
+ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
+]
[[package]]
name = "ansicon"
@@ -132,6 +152,19 @@ files = [
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
]
+[[package]]
+name = "babel"
+version = "2.13.1"
+requires_python = ">=3.7"
+summary = "Internationalization utilities"
+dependencies = [
+ "setuptools; python_version >= \"3.12\"",
+]
+files = [
+ {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"},
+ {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"},
+]
+
[[package]]
name = "backoff"
version = "2.2.1"
@@ -197,6 +230,16 @@ files = [
{file = "blessed-1.20.0.tar.gz", hash = "sha256:2cdd67f8746e048f00df47a2880f4d6acbcdb399031b604e34ba8f71d5787680"},
]
+[[package]]
+name = "blinker"
+version = "1.7.0"
+requires_python = ">=3.8"
+summary = "Fast, simple object-to-object and broadcast signaling"
+files = [
+ {file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9"},
+ {file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182"},
+]
+
[[package]]
name = "certifi"
version = "2023.7.22"
@@ -329,6 +372,31 @@ files = [
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
+[[package]]
+name = "click-plugins"
+version = "1.1.1"
+summary = "An extension module for click to enable registering CLI commands via setuptools entry-points."
+dependencies = [
+ "click>=4.0",
+]
+files = [
+ {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"},
+ {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"},
+]
+
+[[package]]
+name = "cligj"
+version = "0.7.2"
+requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4"
+summary = "Click params for commmand line interfaces to GeoJSON"
+dependencies = [
+ "click>=4.0",
+]
+files = [
+ {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"},
+ {file = "cligj-0.7.2.tar.gz", hash = "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27"},
+]
+
[[package]]
name = "colorama"
version = "0.4.6"
@@ -440,6 +508,22 @@ files = [
{file = "cssbeautifier-1.14.11.tar.gz", hash = "sha256:40544c2b62bbcb64caa5e7f37a02df95654e5ce1bcacadac4ca1f3dc89c31513"},
]
+[[package]]
+name = "dateparser"
+version = "1.1.8"
+requires_python = ">=3.7"
+summary = "Date parsing library designed to parse dates from HTML pages"
+dependencies = [
+ "python-dateutil",
+ "pytz",
+ "regex!=2019.02.19,!=2021.8.27",
+ "tzlocal",
+]
+files = [
+ {file = "dateparser-1.1.8-py2.py3-none-any.whl", hash = "sha256:070b29b5bbf4b1ec2cd51c96ea040dc68a614de703910a91ad1abba18f9f379f"},
+ {file = "dateparser-1.1.8.tar.gz", hash = "sha256:86b8b7517efcc558f085a142cdb7620f0921543fcabdb538c8a4c4001d8178e3"},
+]
+
[[package]]
name = "decorator"
version = "5.1.1"
@@ -884,6 +968,23 @@ files = [
{file = "flake8_isort-6.1.1.tar.gz", hash = "sha256:c1f82f3cf06a80c13e1d09bfae460e9666255d5c780b859f19f8318d420370b3"},
]
+[[package]]
+name = "flask"
+version = "3.0.0"
+requires_python = ">=3.8"
+summary = "A simple framework for building complex web applications."
+dependencies = [
+ "Jinja2>=3.1.2",
+ "Werkzeug>=3.0.0",
+ "blinker>=1.6.2",
+ "click>=8.1.3",
+ "itsdangerous>=2.1.2",
+]
+files = [
+ {file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"},
+ {file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"},
+]
+
[[package]]
name = "geolinks"
version = "0.2.3"
@@ -896,6 +997,42 @@ files = [
{file = "geolinks-0.2.3.tar.gz", hash = "sha256:1aacd55d0c0c349cbc8319b2eea70e98dbe34be688c7be14248fbbba0c7cf54e"},
]
+[[package]]
+name = "greenlet"
+version = "3.0.1"
+requires_python = ">=3.7"
+summary = "Lightweight in-process concurrent programming"
+files = [
+ {file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"},
+ {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"},
+ {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"},
+ {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"},
+ {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"},
+ {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"},
+ {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"},
+ {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"},
+ {file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"},
+ {file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"},
+ {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"},
+ {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"},
+ {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"},
+ {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"},
+ {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"},
+ {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"},
+ {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"},
+ {file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"},
+ {file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"},
+ {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"},
+ {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"},
+ {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"},
+ {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"},
+ {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"},
+ {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"},
+ {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"},
+ {file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"},
+ {file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"},
+]
+
[[package]]
name = "gunicorn"
version = "21.2.0"
@@ -1003,6 +1140,19 @@ files = [
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
+[[package]]
+name = "importlib-metadata"
+version = "6.8.0"
+requires_python = ">=3.8"
+summary = "Read metadata from Python packages"
+dependencies = [
+ "zipp>=0.5",
+]
+files = [
+ {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
+ {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
+]
+
[[package]]
name = "iniconfig"
version = "2.0.0"
@@ -1063,6 +1213,16 @@ files = [
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
]
+[[package]]
+name = "itsdangerous"
+version = "2.1.2"
+requires_python = ">=3.7"
+summary = "Safely pass data to untrusted environments and back."
+files = [
+ {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
+ {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
+]
+
[[package]]
name = "jedi"
version = "0.19.1"
@@ -1151,6 +1311,15 @@ files = [
{file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"},
]
+[[package]]
+name = "lark"
+version = "0.12.0"
+summary = "a modern parsing library"
+files = [
+ {file = "lark-0.12.0-py2.py3-none-any.whl", hash = "sha256:ed1d891cbcf5151ead1c1d14663bf542443e579e63a76ae175b01b899bd854ca"},
+ {file = "lark-0.12.0.tar.gz", hash = "sha256:7da76fcfddadabbbbfd949bbae221efd33938451d90b1fefbbc423c3cccf48ef"},
+]
+
[[package]]
name = "lxml"
version = "4.9.3"
@@ -1637,6 +1806,97 @@ files = [
{file = "pycsw-2.6.1.tar.gz", hash = "sha256:8d4763bfc0674018f0c825b2c533352c1edef161fd76e154c5b7a3dcc44434f0"},
]
+[[package]]
+name = "pydantic"
+version = "2.5.0"
+requires_python = ">=3.7"
+summary = "Data validation using Python type hints"
+dependencies = [
+ "annotated-types>=0.4.0",
+ "pydantic-core==2.14.1",
+ "typing-extensions>=4.6.1",
+]
+files = [
+ {file = "pydantic-2.5.0-py3-none-any.whl", hash = "sha256:7ce6e766c456ad026fe5712f7bcf036efc34bd5d107b3e669ef7ea01b3a9050c"},
+ {file = "pydantic-2.5.0.tar.gz", hash = "sha256:69bd6fb62d2d04b7055f59a396993486a2ee586c43a0b89231ce0000de07627c"},
+]
+
+[[package]]
+name = "pydantic-core"
+version = "2.14.1"
+requires_python = ">=3.7"
+summary = ""
+dependencies = [
+ "typing-extensions!=4.7.0,>=4.6.0",
+]
+files = [
+ {file = "pydantic_core-2.14.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:812beca1dcb2b722cccc7e9c620bd972cbc323321194ec2725eab3222e6ac573"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2ccdc53cb88e51c7d47d74c59630d7be844428f6b8d463055ffad6f0392d8da"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd937733bf2fe7d6a8bf208c12741f1f730b7bf5636033877767a75093c29b8a"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:581bb606a31749a00796f5257947a0968182d7fe91e1dada41f06aeb6bfbc91a"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aadf74a40a7ae49c3c1aa7d32334fe94f4f968e21dd948e301bb4ed431fb2412"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89821a2c77cc1b8f2c1fc3aacd6a3ecc5df8f7e518dc3f18aef8c4dcf66003d"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49ee28d65f506b2858a60745cc974ed005298ebab12693646b97641dd7c99c35"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97246f896b4df7fd84caa8a75a67abb95f94bc0b547665bf0889e3262b060399"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1185548665bc61bbab0dc78f10c8eafa0db0aa1e920fe9a451b77782b10a65cc"},
+ {file = "pydantic_core-2.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a7d08b39fac97540fba785fce3b21ee01a81f081a07a4d031efd791da6666f9"},
+ {file = "pydantic_core-2.14.1-cp310-none-win32.whl", hash = "sha256:0a8c8daf4e3aa3aeb98e3638fc3d58a359738f3d12590b2474c6bb64031a0764"},
+ {file = "pydantic_core-2.14.1-cp310-none-win_amd64.whl", hash = "sha256:4f0788699a92d604f348e9c1ac5e97e304e97127ba8325c7d0af88dcc7d35bd3"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:2be018a84995b6be1bbd40d6064395dbf71592a981169cf154c0885637f5f54a"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc3227408808ba7df8e95eb1d8389f4ba2203bed8240b308de1d7ae66d828f24"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42d5d0e9bbb50481a049bd0203224b339d4db04006b78564df2b782e2fd16ebc"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc6a4ea9f88a810cb65ccae14404da846e2a02dd5c0ad21dee712ff69d142638"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d312ad20e3c6d179cb97c42232b53111bcd8dcdd5c1136083db9d6bdd489bc73"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:679cc4e184f213c8227862e57340d12fd4d4d19dc0e3ddb0f653f86f01e90f94"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101df420e954966868b8bc992aefed5fa71dd1f2755104da62ee247abab28e2f"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c964c0cc443d6c08a2347c0e5c1fc2d85a272dc66c1a6f3cde4fc4843882ada4"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8276bbab68a9dbe721da92d19cbc061f76655248fe24fb63969d0c3e0e5755e7"},
+ {file = "pydantic_core-2.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12163197fec7c95751a3c71b36dcc1909eed9959f011ffc79cc8170a6a74c826"},
+ {file = "pydantic_core-2.14.1-cp311-none-win32.whl", hash = "sha256:b8ff0302518dcd001bd722bbe342919c29e5066c7eda86828fe08cdc112668b8"},
+ {file = "pydantic_core-2.14.1-cp311-none-win_amd64.whl", hash = "sha256:59fa83873223f856d898452c6162a390af4297756f6ba38493a67533387d85d9"},
+ {file = "pydantic_core-2.14.1-cp311-none-win_arm64.whl", hash = "sha256:798590d38c9381f07c48d13af1f1ef337cebf76ee452fcec5deb04aceced51c7"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:587d75aec9ae50d0d63788cec38bf13c5128b3fc1411aa4b9398ebac884ab179"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26242e3593d4929123615bd9365dd86ef79b7b0592d64a96cd11fd83c69c9f34"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5879ac4791508d8f0eb7dec71ff8521855180688dac0c55f8c99fc4d1a939845"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad9ea86f5fc50f1b62c31184767fe0cacaa13b54fe57d38898c3776d30602411"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:102ac85a775e77821943ae38da9634ddd774b37a8d407181b4f7b05cdfb36b55"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2459cc06572730e079ec1e694e8f68c99d977b40d98748ae72ff11ef21a56b0b"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:217dcbfaf429a9b8f1d54eb380908b9c778e78f31378283b30ba463c21e89d5d"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d59e0d7cdfe8ed1d4fcd28aad09625c715dc18976c7067e37d8a11b06f4be3e"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e2be646a5155d408e68b560c0553e8a83dc7b9f90ec6e5a2fc3ff216719385db"},
+ {file = "pydantic_core-2.14.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ffba979801e3931a19cd30ed2049450820effe8f152aaa317e2fd93795d318d7"},
+ {file = "pydantic_core-2.14.1-cp312-none-win32.whl", hash = "sha256:132b40e479cb5cebbbb681f77aaceabbc8355df16c9124cff1d4060ada83cde2"},
+ {file = "pydantic_core-2.14.1-cp312-none-win_amd64.whl", hash = "sha256:744b807fe2733b6da3b53e8ad93e8b3ea3ee3dfc3abece4dd2824cc1f39aa343"},
+ {file = "pydantic_core-2.14.1-cp312-none-win_arm64.whl", hash = "sha256:24ba48f9d0b8d64fc5e42e1600366c3d7db701201294989aebdaca23110c02ab"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:53efe03cc383a83660cfdda6a3cb40ee31372cedea0fde0b2a2e55e838873ab6"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f523e116879bc6714e61d447ce934676473b068069dce6563ea040381dc7a257"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85bb66d661be51b2cba9ca06759264b3469d2dbb53c3e6effb3f05fec6322be6"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f53a3ccdc30234cb4342cec541e3e6ed87799c7ca552f0b5f44e3967a5fed526"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1bfb63821ada76719ffcd703fc40dd57962e0d8c253e3c565252e6de6d3e0bc6"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e2c689439f262c29cf3fcd5364da1e64d8600facecf9eabea8643b8755d2f0de"},
+ {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a15f6e5588f7afb7f6fc4b0f4ff064749e515d34f34c666ed6e37933873d8ad8"},
+ {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f1a30eef060e21af22c7d23349f1028de0611f522941c80efa51c05a63142c62"},
+ {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16f4a7e1ec6b3ea98a1e108a2739710cd659d68b33fbbeaba066202cab69c7b6"},
+ {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd80a2d383940eec3db6a5b59d1820f947317acc5c75482ff8d79bf700f8ad6a"},
+ {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a68a36d71c7f638dda6c9e6b67f6aabf3fa1471b198d246457bfdc7c777cdeb7"},
+ {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ebc79120e105e4bcd7865f369e3b9dbabb0d492d221e1a7f62a3e8e292550278"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c8c466facec2ccdf025b0b1455b18f2c3d574d5f64d24df905d3d7b8f05d5f4e"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b91b5ec423e88caa16777094c4b2b97f11453283e7a837e5e5e1b886abba1251"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130e49aa0cb316f743bc7792c36aefa39fc2221312f1d4b333b19edbdd71f2b1"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f483467c046f549572f8aca3b7128829e09ae3a9fe933ea421f7cb7c58120edb"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dee4682bd7947afc682d342a8d65ad1834583132383f8e801601a8698cb8d17a"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8d927d042c0ef04607ee7822828b208ab045867d20477ec6593d612156798547"},
+ {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5a1570875eb0d1479fb2270ed80c88c231aaaf68b0c3f114f35e7fb610435e4f"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cb2fd3ab67558eb16aecfb4f2db4febb4d37dc74e6b8613dc2e7160fb58158a9"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a7991f25b98038252363a03e6a9fe92e60fe390fda2631d238dc3b0e396632f8"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b45b7be9f99991405ecd6f6172fb6798908a8097106ae78d5cc5cc15121bad9"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51506e7652a2ef1d1cf763c4b51b972ff4568d1dddc96ca83931a6941f5e6389"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:66dc0e63349ec39c1ea66622aa5c2c1f84382112afd3ab2fa0cca4fb01f7db39"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8e17f0c3ba4cb07faa0038a59ce162de584ed48ba645c8d05a5de1e40d4c21e7"},
+ {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d983222223f63e323a5f497f5b85e211557a5d8fb670dc88f343784502b466ba"},
+ {file = "pydantic_core-2.14.1.tar.gz", hash = "sha256:0d82a6ee815388a362885186e431fac84c7a06623bc136f508e9f88261d8cadb"},
+]
+
[[package]]
name = "pyflakes"
version = "3.1.0"
@@ -1647,6 +1907,64 @@ files = [
{file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"},
]
+[[package]]
+name = "pygeoapi"
+version = "0.16.dev0"
+git = "https://github.com/geopython/pygeoapi.git"
+ref = "de1a7d93eeb492c2b51908e9875a61074b7eab6b"
+revision = "de1a7d93eeb492c2b51908e9875a61074b7eab6b"
+summary = "pygeoapi provides an API to geospatial data"
+dependencies = [
+ "Babel",
+ "Flask",
+ "PyYAML",
+ "SQLAlchemy<2.0.0",
+ "click",
+ "filelock",
+ "importlib-metadata",
+ "jinja2",
+ "jsonschema",
+ "pydantic",
+ "pygeofilter",
+ "pygeoif",
+ "pyproj",
+ "python-dateutil",
+ "pytz",
+ "rasterio",
+ "requests",
+ "shapely<2.0",
+ "tinydb",
+ "typing-extensions",
+ "unicodecsv",
+]
+
+[[package]]
+name = "pygeofilter"
+version = "0.2.1"
+summary = "pygeofilter is a pure Python parser implementation of OGC filtering standards"
+dependencies = [
+ "dateparser",
+ "lark<1.0",
+ "pygeoif>=1.0.0",
+]
+files = [
+ {file = "pygeofilter-0.2.1-py2.py3-none-any.whl", hash = "sha256:6cbfd46edefee421cae6d338942a0f4f8bbb00f1a6d979914420a300aa0845a6"},
+ {file = "pygeofilter-0.2.1.tar.gz", hash = "sha256:cafc961a5cab5f2836605a43b82b05e799500223d19d2d8d8acb85ba263e954c"},
+]
+
+[[package]]
+name = "pygeoif"
+version = "1.1.1"
+requires_python = ">=3.7"
+summary = "A basic implementation of the __geo_interface__"
+dependencies = [
+ "typing-extensions",
+]
+files = [
+ {file = "pygeoif-1.1.1-py3-none-any.whl", hash = "sha256:c98dd9db1022c9002950d128a37b53bb17d972239f92871687e28958c4c088b0"},
+ {file = "pygeoif-1.1.1.tar.gz", hash = "sha256:5b3cc057adde1a0bf50a3dcb5b160172261861a4f4bdde6ee6eb663773c4fe33"},
+]
+
[[package]]
name = "pygeometa"
version = "0.15.3"
@@ -1748,6 +2066,16 @@ files = [
{file = "pylint_plugin_utils-0.8.2.tar.gz", hash = "sha256:d3cebf68a38ba3fba23a873809155562571386d4c1b03e5b4c4cc26c3eee93e4"},
]
+[[package]]
+name = "pyparsing"
+version = "3.1.1"
+requires_python = ">=3.6.8"
+summary = "pyparsing module - Classes and methods to define and execute parsing grammars"
+files = [
+ {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"},
+ {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"},
+]
+
[[package]]
name = "pyproj"
version = "3.6.1"
@@ -1903,6 +2231,38 @@ files = [
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
+[[package]]
+name = "rasterio"
+version = "1.3.9"
+requires_python = ">=3.8"
+summary = "Fast and direct raster I/O for use with Numpy and SciPy"
+dependencies = [
+ "affine",
+ "attrs",
+ "certifi",
+ "click-plugins",
+ "click>=4.0",
+ "cligj>=0.5",
+ "numpy",
+ "setuptools",
+ "snuggs>=1.4.1",
+]
+files = [
+ {file = "rasterio-1.3.9-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:04247da9f4002587ac2bec967c3a72f63fc0e6654101c06850bae3d8131b700d"},
+ {file = "rasterio-1.3.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c9edce37b70f4cd4be5d3f5d314877e3130aeebb612120405cd28f83fe200865"},
+ {file = "rasterio-1.3.9-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:fd6a850a37840ba590ddcf7ff90ba007b1e231b04434d8b4ac5ce0f746ada91a"},
+ {file = "rasterio-1.3.9-cp310-cp310-win_amd64.whl", hash = "sha256:0c83156a44f8fda11876ff9f2ff1b602d7e7434447f7d621353f2929cefb1bf1"},
+ {file = "rasterio-1.3.9-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:0172dbd80bd9adc105ec2c9bd207dbd5519ea06b438a4d965c6290ae8ed6ff9f"},
+ {file = "rasterio-1.3.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0ea5b42597d85868ee88c750cc33f2ae729e1b5e3fe28f99071f39e1417bf1c0"},
+ {file = "rasterio-1.3.9-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:be9b343bd08245df22115775dc9513c912afb4134d832662fa165d70cb805c34"},
+ {file = "rasterio-1.3.9-cp311-cp311-win_amd64.whl", hash = "sha256:06d53e2e0885f039f960beb7c861400b92ea3e0e5abc2c67483fb56b1e5cbc13"},
+ {file = "rasterio-1.3.9-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:a34bb9eef67b7896e2dfb39e10ba6372f9894226fb790bd7a46f5748f205b7d8"},
+ {file = "rasterio-1.3.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:67b144b9678f9ad4cf5f2c3f455cbc6a7166c0523179249cee8f2e2c57d76c5b"},
+ {file = "rasterio-1.3.9-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:99b72fccb702a921f43e56a4507b4cafe2a9196b478b993b98e82ec6851916d7"},
+ {file = "rasterio-1.3.9-cp312-cp312-win_amd64.whl", hash = "sha256:6777fad3c31eb3e5da0ccaa28a032ad07c20d003bcd14f8bc13e16ca2f62348c"},
+ {file = "rasterio-1.3.9.tar.gz", hash = "sha256:fc6d0d290492fa1a5068711cfebb21cc936968891b7ed9da0690c8a7388885c5"},
+]
+
[[package]]
name = "rcssmin"
version = "1.1.2"
@@ -2128,35 +2488,26 @@ files = [
[[package]]
name = "shapely"
-version = "2.0.2"
-requires_python = ">=3.7"
-summary = "Manipulation and analysis of geometric objects"
-dependencies = [
- "numpy>=1.14",
-]
-files = [
- {file = "shapely-2.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6ca8cffbe84ddde8f52b297b53f8e0687bd31141abb2c373fd8a9f032df415d6"},
- {file = "shapely-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:baa14fc27771e180c06b499a0a7ba697c7988c7b2b6cba9a929a19a4d2762de3"},
- {file = "shapely-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:36480e32c434d168cdf2f5e9862c84aaf4d714a43a8465ae3ce8ff327f0affb7"},
- {file = "shapely-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef753200cbffd4f652efb2c528c5474e5a14341a473994d90ad0606522a46a2"},
- {file = "shapely-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9a41ff4323fc9d6257759c26eb1cf3a61ebc7e611e024e6091f42977303fd3a"},
- {file = "shapely-2.0.2-cp310-cp310-win32.whl", hash = "sha256:72b5997272ae8c25f0fd5b3b967b3237e87fab7978b8d6cd5fa748770f0c5d68"},
- {file = "shapely-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:34eac2337cbd67650248761b140d2535855d21b969d76d76123317882d3a0c1a"},
- {file = "shapely-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b0c052709c8a257c93b0d4943b0b7a3035f87e2d6a8ac9407b6a992d206422f"},
- {file = "shapely-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d217e56ae067e87b4e1731d0dc62eebe887ced729ba5c2d4590e9e3e9fdbd88"},
- {file = "shapely-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94ac128ae2ab4edd0bffcd4e566411ea7bdc738aeaf92c32a8a836abad725f9f"},
- {file = "shapely-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa3ee28f5e63a130ec5af4dc3c4cb9c21c5788bb13c15e89190d163b14f9fb89"},
- {file = "shapely-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:737dba15011e5a9b54a8302f1748b62daa207c9bc06f820cd0ad32a041f1c6f2"},
- {file = "shapely-2.0.2-cp311-cp311-win32.whl", hash = "sha256:45ac6906cff0765455a7b49c1670af6e230c419507c13e2f75db638c8fc6f3bd"},
- {file = "shapely-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:dc9342fc82e374130db86a955c3c4525bfbf315a248af8277a913f30911bed9e"},
- {file = "shapely-2.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:06f193091a7c6112fc08dfd195a1e3846a64306f890b151fa8c63b3e3624202c"},
- {file = "shapely-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:eebe544df5c018134f3c23b6515877f7e4cd72851f88a8d0c18464f414d141a2"},
- {file = "shapely-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7e92e7c255f89f5cdf777690313311f422aa8ada9a3205b187113274e0135cd8"},
- {file = "shapely-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be46d5509b9251dd9087768eaf35a71360de6afac82ce87c636990a0871aa18b"},
- {file = "shapely-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5533a925d8e211d07636ffc2fdd9a7f9f13d54686d00577eeb11d16f00be9c4"},
- {file = "shapely-2.0.2-cp312-cp312-win32.whl", hash = "sha256:084b023dae8ad3d5b98acee9d3bf098fdf688eb0bb9b1401e8b075f6a627b611"},
- {file = "shapely-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:ea84d1cdbcf31e619d672b53c4532f06253894185ee7acb8ceb78f5f33cbe033"},
- {file = "shapely-2.0.2.tar.gz", hash = "sha256:1713cc04c171baffc5b259ba8531c58acc2a301707b7f021d88a15ed090649e7"},
+version = "1.8.5.post1"
+requires_python = ">=3.6"
+summary = "Geometric objects, predicates, and operations"
+files = [
+ {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d048f93e42ba578b82758c15d8ae037d08e69d91d9872bca5a1895b118f4e2b0"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99ab0ddc05e44acabdbe657c599fdb9b2d82e86c5493bdae216c0c4018a82dee"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a2f0da0109e81e0c101a2b4cd8412f73f5f299e7b5b2deaf64cd2a100ac118"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6fe855e7d45685926b6ba00aaeb5eba5862611f7465775dacd527e081a8ced6d"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec14ceca36f67cb48b34d02d7f65a9acae15cd72b48e303531893ba4a960f3ea"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a2b2a65fa7f97115c1cd989fe9d6f39281ca2a8a014f1d4904c1a6e34d7f25"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-win32.whl", hash = "sha256:21776184516a16bf82a0c3d6d6a312b3cd15a4cabafc61ee01cf2714a82e8396"},
+ {file = "Shapely-1.8.5.post1-cp310-cp310-win_amd64.whl", hash = "sha256:a354199219c8d836f280b88f2c5102c81bb044ccea45bd361dc38a79f3873714"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:783bad5f48e2708a0e2f695a34ed382e4162c795cb2f0368b39528ac1d6db7ed"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a23ef3882d6aa203dd3623a3d55d698f59bfbd9f8a3bfed52c2da05a7f0f8640"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab38f7b5196ace05725e407cb8cab9ff66edb8e6f7bb36a398e8f73f52a7aaa2"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d086591f744be483b34628b391d741e46f2645fe37594319e0a673cc2c26bcf"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4728666fff8cccc65a07448cae72c75a8773fea061c3f4f139c44adc429b18c3"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-win32.whl", hash = "sha256:84010db15eb364a52b74ea8804ef92a6a930dfc1981d17a369444b6ddec66efd"},
+ {file = "Shapely-1.8.5.post1-cp311-cp311-win_amd64.whl", hash = "sha256:48dcfffb9e225c0481120f4bdf622131c8c95f342b00b158cdbe220edbbe20b6"},
+ {file = "Shapely-1.8.5.post1.tar.gz", hash = "sha256:ef3be705c3eac282a28058e6c6e5503419b250f482320df2172abcbea642c831"},
]
[[package]]
@@ -2169,6 +2520,19 @@ files = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
+[[package]]
+name = "snuggs"
+version = "1.4.7"
+summary = "Snuggs are s-expressions for Numpy"
+dependencies = [
+ "numpy",
+ "pyparsing>=2.1.6",
+]
+files = [
+ {file = "snuggs-1.4.7-py3-none-any.whl", hash = "sha256:988dde5d4db88e9d71c99457404773dabcc7a1c45971bfbe81900999942d9f07"},
+ {file = "snuggs-1.4.7.tar.gz", hash = "sha256:501cf113fe3892e14e2fee76da5cd0606b7e149c411c271898e6259ebde2617b"},
+]
+
[[package]]
name = "soupsieve"
version = "2.5"
@@ -2179,6 +2543,26 @@ files = [
{file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"},
]
+[[package]]
+name = "sqlalchemy"
+version = "1.4.50"
+requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
+summary = "Database Abstraction Library"
+dependencies = [
+ "greenlet!=0.4.17; python_version >= \"3\" and (platform_machine == \"aarch64\" or (platform_machine == \"ppc64le\" or (platform_machine == \"x86_64\" or (platform_machine == \"amd64\" or (platform_machine == \"AMD64\" or (platform_machine == \"win32\" or platform_machine == \"WIN32\"))))))",
+]
+files = [
+ {file = "SQLAlchemy-1.4.50-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d00665725063692c42badfd521d0c4392e83c6c826795d38eb88fb108e5660e5"},
+ {file = "SQLAlchemy-1.4.50-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85292ff52ddf85a39367057c3d7968a12ee1fb84565331a36a8fead346f08796"},
+ {file = "SQLAlchemy-1.4.50-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d0fed0f791d78e7767c2db28d34068649dfeea027b83ed18c45a423f741425cb"},
+ {file = "SQLAlchemy-1.4.50-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db4db3c08ffbb18582f856545f058a7a5e4ab6f17f75795ca90b3c38ee0a8ba4"},
+ {file = "SQLAlchemy-1.4.50-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14b0cacdc8a4759a1e1bd47dc3ee3f5db997129eb091330beda1da5a0e9e5bd7"},
+ {file = "SQLAlchemy-1.4.50-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fb9cb60e0f33040e4f4681e6658a7eb03b5cb4643284172f91410d8c493dace"},
+ {file = "SQLAlchemy-1.4.50-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cb501d585aa74a0f86d0ea6263b9c5e1d1463f8f9071392477fd401bd3c7cc"},
+ {file = "SQLAlchemy-1.4.50-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a7a66297e46f85a04d68981917c75723e377d2e0599d15fbe7a56abed5e2d75"},
+ {file = "SQLAlchemy-1.4.50.tar.gz", hash = "sha256:3b97ddf509fc21e10b09403b5219b06c5b558b27fc2453150274fa4e70707dbf"},
+]
+
[[package]]
name = "sqlparse"
version = "0.4.4"
@@ -2222,6 +2606,16 @@ files = [
{file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
]
+[[package]]
+name = "tinydb"
+version = "4.8.0"
+requires_python = ">=3.7,<4.0"
+summary = "TinyDB is a tiny, document oriented database optimized for your happiness :)"
+files = [
+ {file = "tinydb-4.8.0-py3-none-any.whl", hash = "sha256:30c06d12383d7c332e404ca6a6103fb2b32cbf25712689648c39d9a6bd34bd3d"},
+ {file = "tinydb-4.8.0.tar.gz", hash = "sha256:6dd686a9c5a75dfa9280088fd79a419aefe19cd7f4bd85eba203540ef856d564"},
+]
+
[[package]]
name = "tomli"
version = "2.0.1"
@@ -2312,6 +2706,27 @@ files = [
{file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
]
+[[package]]
+name = "tzlocal"
+version = "5.2"
+requires_python = ">=3.8"
+summary = "tzinfo object for the local timezone"
+dependencies = [
+ "tzdata; platform_system == \"Windows\"",
+]
+files = [
+ {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"},
+ {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"},
+]
+
+[[package]]
+name = "unicodecsv"
+version = "0.14.1"
+summary = "Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*."
+files = [
+ {file = "unicodecsv-0.14.1.tar.gz", hash = "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc"},
+]
+
[[package]]
name = "urllib3"
version = "1.26.18"
@@ -2421,3 +2836,13 @@ files = [
{file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"},
{file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"},
]
+
+[[package]]
+name = "zipp"
+version = "3.17.0"
+requires_python = ">=3.8"
+summary = "Backport of pathlib-compatible object wrapper for zip files"
+files = [
+ {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
+ {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
+]
diff --git a/pyproject.toml b/pyproject.toml
index d4dbe57..2d4f8b5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -162,6 +162,7 @@ dependencies = [
"pygeometa",
"django-lifecycle",
"gunicorn>=21.2.0",
+ "pygeoapi @ git+https://github.com/geopython/pygeoapi.git@de1a7d93eeb492c2b51908e9875a61074b7eab6b",
]
requires-python = ">=3.10"
name = ""