From 8ad2b85dfaef4e78ac8de7a1cde4e0bedf4325ed Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Sat, 18 Apr 2026 21:33:43 -0400 Subject: [PATCH] update distributed search functionality --- default-sample.yml | 17 ++- docker/compose/pycsw.yml | 7 +- docker/helm/values.yaml | 5 +- docker/kubernetes/pycsw-configmap.yaml | 7 +- docker/pycsw.yml | 7 +- docs/configuration.rst | 2 +- docs/distributedsearching.rst | 60 ++++++++- docs/introduction.rst | 8 +- pycsw/core/admin.py | 6 +- pycsw/ogc/api/oapi.py | 66 ++++++++- pycsw/ogc/api/records.py | 127 +++++++++++++++--- pycsw/ogc/csw/csw2.py | 17 ++- pycsw/ogc/csw/csw3.py | 17 ++- pycsw/server.py | 5 +- pycsw/stac/api.py | 87 +++++++++++- pycsw/templates/collection.html | 3 + pycsw/templates/collections.html | 3 + pycsw/templates/federatedcatalog.html | 38 ++++++ pycsw/templates/federatedcatalogs.html | 37 +++++ pycsw/wsgi_flask.py | 31 ++++- .../suites/apiso-inspire/default.yml | 11 +- .../expected/get_GetCapabilities-lang.xml | 2 +- .../expected/get_GetCapabilities.xml | 2 +- .../functionaltests/suites/apiso/default.yml | 11 +- .../apiso/expected/post_GetCapabilities.xml | 2 +- tests/functionaltests/suites/atom/default.yml | 11 +- .../atom/expected/post_GetCapabilities.xml | 2 +- tests/functionaltests/suites/cite/default.yml | 11 +- ...t_27e17158-c57a-4493-92ac-dba8934cf462.xml | 2 +- ...t_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml | 2 +- ...t_477b23a3-baa9-47c8-9541-5fe27735ed49.xml | 4 +- ...t_48f26761-3a9d-48db-bee1-da089f5fb857.xml | 2 +- ...t_55c38f00-2553-42c1-99ab-33edbb561ad7.xml | 4 +- ...t_80f31def-4185-48b9-983a-960566918eae.xml | 4 +- ...t_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml | 4 +- ...t_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml | 2 +- ...t_f4692ec5-9547-4a05-88ab-e6154af2640a.xml | 2 +- .../functionaltests/suites/csw30/default.yml | 7 +- .../suites/default/default.yml | 7 +- tests/functionaltests/suites/dif/default.yml | 11 +- .../dif/expected/post_GetCapabilities.xml | 2 +- .../suites/duplicatefileid/default.yml | 11 +- .../functionaltests/suites/ebrim/default.yml | 11 +- .../ebrim/expected/post_GetCapabilities.xml | 2 +- tests/functionaltests/suites/fgdc/default.yml | 11 +- .../fgdc/expected/post_GetCapabilities.xml | 2 +- tests/functionaltests/suites/gm03/default.yml | 11 +- .../gm03/expected/post_GetCapabilities.xml | 2 +- .../suites/harvesting/default.yml | 11 +- .../expected/post_GetCapabilities.xml | 2 +- .../suites/idswithpaths/default.yml | 11 +- .../suites/iso19115p3/default.yml | 11 +- .../expected/get_GetCapabilities.xml | 2 +- .../expected/post_GetCapabilities.xml | 2 +- .../suites/manager/default.yml | 11 +- .../manager/expected/post_GetCapabilities.xml | 2 +- .../functionaltests/suites/oaipmh/default.yml | 11 +- .../suites/opensearcheo/default.yml | 11 +- .../suites/repofilter/default.yml | 11 +- tests/functionaltests/suites/sru/default.yml | 11 +- .../suites/stablesort/default.yml | 11 +- .../functionaltests/suites/utf-8/default.yml | 11 +- .../utf-8/expected/post_GetCapabilities.xml | 2 +- tests/functionaltests/suites/xslt/default.yml | 11 +- 64 files changed, 700 insertions(+), 136 deletions(-) create mode 100644 pycsw/templates/federatedcatalog.html create mode 100644 pycsw/templates/federatedcatalogs.html diff --git a/default-sample.yml b/default-sample.yml index 770222e56..0a2c77fb2 100644 --- a/default-sample.yml +++ b/default-sample.yml @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2024 Angelos Tzotsos # # Permission is hereby granted, free of charge, to any person @@ -55,7 +55,20 @@ profiles: - apiso federatedcatalogues: - - http://catalog.data.gov/csw + - id: arctic-sdi-csw + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: pycsw-cite-demo + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + uresultsrl: https://demo.pycsw.org/cite + - id: fedcat03 + type: STAC-API + title: Copernicus Data Space Ecosystem (CDSE) asset-level STAC catalogue + url: https://stac.dataspace.copernicus.eu/v1 + collections: + - daymet-annual-pr manager: transactions: false diff --git a/docker/compose/pycsw.yml b/docker/compose/pycsw.yml index f9260812f..b3258f75c 100644 --- a/docker/compose/pycsw.yml +++ b/docker/compose/pycsw.yml @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Ricardo Garcia Silva # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2017 Ricardo Garcia Silva # # Permission is hereby granted, free of charge, to any person @@ -52,7 +52,10 @@ profiles: - apiso federatedcatalogues: - - http://catalog.data.gov/csw + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw manager: transactions: false diff --git a/docker/helm/values.yaml b/docker/helm/values.yaml index 8bb6aa90e..735172622 100644 --- a/docker/helm/values.yaml +++ b/docker/helm/values.yaml @@ -48,7 +48,10 @@ pycsw: profiles: - apiso # federatedcatalogues: - # - http://catalog.data.gov/csw + # - id: fedcat01 + # type: CSW + # title: Arctic SDI + # url: https://catalogue.arctic-sdi.org/csw manager: transactions: "false" allowed_ips: diff --git a/docker/kubernetes/pycsw-configmap.yaml b/docker/kubernetes/pycsw-configmap.yaml index 1b854fc42..0b0adc202 100644 --- a/docker/kubernetes/pycsw-configmap.yaml +++ b/docker/kubernetes/pycsw-configmap.yaml @@ -7,7 +7,7 @@ data: # Ricardo Garcia Silva # Angelos Tzotsos # - # Copyright (c) 2024 Tom Kralidis + # Copyright (c) 2026 Tom Kralidis # Copyright (c) 2017 Ricardo Garcia Silva # Copyright (c) 2024 Angelos Tzotsos # @@ -57,7 +57,10 @@ data: - apiso federatedcatalogues: - - http://catalog.data.gov/csw + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw manager: transactions: false diff --git a/docker/pycsw.yml b/docker/pycsw.yml index e30a7c5dc..607382964 100644 --- a/docker/pycsw.yml +++ b/docker/pycsw.yml @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Ricardo Garcia Silva # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2017 Ricardo Garcia Silva # # Permission is hereby granted, free of charge, to any person @@ -52,7 +52,10 @@ profiles: - apiso federatedcatalogues: - - http://catalog.data.gov/csw + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw manager: transactions: false diff --git a/docs/configuration.rst b/docs/configuration.rst index a2e0e9f0f..506fedb71 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -16,7 +16,7 @@ pycsw's runtime configuration is defined by ``default.yml``. pycsw ships with a - **level**: the logging level (see https://docs.python.org/library/logging.html#logging-levels) - **logfile**: the full file path to the logfile - **ogc_schemas_base**: base URL of OGC XML schemas tree file structure (default is http://schemas.opengis.net) -- **federatedcatalogues**: comma delimited list of CSW endpoints to be used for distributed searching, if requested by the client (see :ref:`distributedsearching`) +- **federatedcatalogues**: arrray of distributed catalogue endpoints to be used for distributed searching, if requested by the client (see :ref:`distributedsearching`) - **pretty_print**: whether to pretty print the output (``true`` or ``false``). Default is ``false`` - **gzip_compresslevel**: gzip compression level, lowest is ``1``, highest is ``9``. Default is off. **NOTE**: if gzip compression is already enabled via your web server, do not enable this directive (or else the server will try to compress the response twice, resulting in degraded performance) - **domainquerytype**: for GetDomain operations, how to output domain values. Accepted values are ``list`` and ``range`` (min/max). Default is ``list`` diff --git a/docs/distributedsearching.rst b/docs/distributedsearching.rst index 4c671cb02..10b6f3a2d 100644 --- a/docs/distributedsearching.rst +++ b/docs/distributedsearching.rst @@ -57,9 +57,18 @@ in the CSW-all configuration: .. code-block:: yaml federatedcatalogues: - - http://localhost/pycsw/csw.py?config=CSW-1.yml - - http://localhost/pycsw/csw.py?config=CSW-2.yml - - http://localhost/pycsw/csw.py?config=CSW-3.yml + - id: fedcat01 + type: CSW + title: Federated catalogue 1 + url: http://localhost/pycsw/csw.py?config=CSW-1.yml + - id: fedcat02 + type: CSW + title: Federated catalogue 2 + url: http://localhost/pycsw/csw.py?config=CSW-2.yml + - id: fedcat03 + type: CSW + title: Federated catalogue 3 + url: http://localhost/pycsw/csw.py?config=CSW-3.yml At which point a CSW client request to CSW-all with ``distributedsearch=TRUE``, while specifying an optional ``hopCount``. Query network topology: @@ -88,7 +97,7 @@ A very important facet of distributed search is as per Annex B of OGC:CSW 2.0.2. OGC API - Records ----------------- -Experimental support for distibuted searching is available in pycsw's OGC API - Records support to allow for searching remote services. The implementation uses the same approach as described above, operating in OGC API - Records mode. +Experimental support for distibuted searching is available in pycsw's OGC API - Records support to allow for searching remote services. The implementation uses the same approach as described above, operating in OGC API - Records mode as per `OGC API - Records - Part 4: Federated Search`_ (draft). .. note:: @@ -97,9 +106,46 @@ Experimental support for distibuted searching is available in pycsw's OGC API - .. code-block:: yaml federatedcatalogues: - - https://example.org/collections/collection1 - - https://example.org/collections/collection2 + - id: fedcat01 + type: OARec + title: Federated catalogue 1 + url: https://example.org/collections/collection1 + - id: fedcat02 + type: OARec + title: Federated catalogue 2 + url: https://example.org/collections/collection2 With the above configured, a distributed search can be invoked as follows: -http://localhost/collections/metadata:main/items?distributed=true +http://localhost/collections/metadata:main/items?distributedSearch=true + +STAC API +-------- + +Experimental support for distibuted searching is available in pycsw's STAC API support to allow for searching remote services. The implementation uses the same approach as described above. + +.. note:: + + The ``federatedcatalogues`` directives must point to a STAC API endpoint. + +.. code-block:: yaml + + federatedcatalogues: + - id: fedcat03 + type: STAC-API + title: Copernicus Data Space Ecosystem (CDSE) asset-level STAC catalogue + url: https://stac.dataspace.copernicus.eu/v1 + collections: + - daymet-annual-pr + + +.. note:: + + To constrain STAC API distributed search to specific collections, define one to many in the `collections` (array) directive. + + +With the above configured, a distributed search can be invoked as follows: + +http://localhost/stac/search?distributedSearch=true + +.. _`OGC API - Records - Part 4: Federated Search`: https://github.com/opengeospatial/ogcapi-records/blob/master/extensions/federated-search/document.adoc diff --git a/docs/introduction.rst b/docs/introduction.rst index d3bc168b0..8beced119 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -9,6 +9,9 @@ Features ======== - implements `OGC API - Records - Part 1: Core`_ +- implements `OGC API - Records - Part 2: Facets`_ +- implements `OGC API - Records - Part 3: Create, Replace, Update, Delete, Harvest`_ +- implements `OGC API - Records - Part 4: Federated Search`_ - implements `OGC API - Features - Part 3: Filtering`_ - implements `STAC API`_ - implements `Common Query Language (CQL2)`_ @@ -235,7 +238,10 @@ Paging - resumptionToken -.. _`OGC API - Records - Part 1: Core`: https://ogcapi.ogc.org/records +.. _`OGC API - Records - Part 1: Core`: https://docs.ogc.org/is/20-004r1/20-004r1.html +.. _`OGC API - Records - Part 2: Facets`: https://docs.ogc.org/DRAFTS/25-013.html +.. _`OGC API - Records - Part 3: Create, Replace, Update, Delete, Harvest`: https://docs.ogc.org/DRAFTS/25-015.html +.. _`OGC API - Records - Part 4: Federated Search`: https://github.com/opengeospatial/ogcapi-records/blob/master/extensions/federated-search/document.adoc .. _`OGC API - Features - Part 3: Filtering`: http://docs.ogc.org/DRAFTS/19-079.html .. _`Common Query Language (CQL2)`: https://docs.ogc.org/DRAFTS/21-065.html .. _`OGC CSW`: https://www.ogc.org/standards/cat diff --git a/pycsw/core/admin.py b/pycsw/core/admin.py index 6d19ab9d4..6dec5812c 100644 --- a/pycsw/core/admin.py +++ b/pycsw/core/admin.py @@ -4,7 +4,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2015 Angelos Tzotsos # # Permission is hereby granted, free of charge, to any person @@ -632,7 +632,9 @@ def cli_migrate_config(ctx, config, verbosity): elif name == 'profiles': dict_[name] = value.split(',') elif name == 'federatedcatalogues': - dict_[name] = value.split(',') + dict_[name] = [] + for count, fc in enumerate(value.split(',')): + dict_[name].append({'id': f'fedcat{count}', 'url': fc}) else: dict_['server'][name] = get_typed_value(value) diff --git a/pycsw/ogc/api/oapi.py b/pycsw/ogc/api/oapi.py index be3503f2f..f38ca3775 100644 --- a/pycsw/ogc/api/oapi.py +++ b/pycsw/ogc/api/oapi.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -199,10 +199,10 @@ def gen_oapi(config, oapi_filepath, mode='ogcapi-records'): 'style': 'form', 'explode': False } - oapi['components']['parameters']['distributed'] = { - 'name': 'distributed', + oapi['components']['parameters']['distributedSearch'] = { + 'name': 'distributedSearch', 'in': 'query', - 'description': 'Whether to invoke distributed mode', + 'description': 'Whether to invoke distributed search', 'schema': { 'type': 'boolean', 'default': False @@ -390,6 +390,60 @@ def gen_oapi(config, oapi_filepath, mode='ogcapi-records'): oapi['paths']['/collections/{collectionId}/queryables'] = path2 oapi['components']['parameters']['collectionId']['default'] = 'metadata:main' # noqa + path = { + 'get': { + 'tags': ['Federated catalogs'], + 'summary': 'Federated catalogs page', + 'description': 'Federated catalogs page', + 'operationId': 'getFederatedCatalogs', + 'parameters': [ + {'$ref': '#/components/parameters/collectionId'}, + {'$ref': '#/components/parameters/f'} + ], + 'responses': { + '200': { + '$ref': '#/components/responses/FederatedCatalogs' + }, + '500': { + '$ref': '#/components/responses/ServerError' + } + } + } + } + + oapi['paths']['/collections/{collectionId}/federatedCatalogs'] = path + + path = { + 'get': { + 'tags': ['Federated catalogs'], + 'summary': 'Federated catalogs page', + 'description': 'Federated catalogs page', + 'operationId': 'getFederatedCatalog', + 'parameters': [ + {'$ref': '#/components/parameters/collectionId'}, + {'name': 'catalogId', + 'in': 'path', + 'description': 'catalog ID', + 'required': True, + 'schema': { + 'type': 'string' + } + }, + {'$ref': '#/components/parameters/f'} + ], + 'responses': { + '200': { + '$ref': '#/components/responses/FederatedCatalog' + }, + '500': { + '$ref': '#/components/responses/ServerError' + } + } + } + } + + oapi['paths']['/collections/{collectionId}/federatedCatalogs/{catalogId}'] = path + path = { 'get': { 'tags': ['metadata'], @@ -411,7 +465,7 @@ def gen_oapi(config, oapi_filepath, mode='ogcapi-records'): {'$ref': '#/components/parameters/f'}, {'$ref': '#/components/parameters/offset'}, {'$ref': '#/components/parameters/facets'}, - {'$ref': '#/components/parameters/distributed'}, + {'$ref': '#/components/parameters/distributedSearch'}, {'$ref': '#/components/parameters/vendorSpecificParameters'} ], 'responses': { @@ -488,7 +542,7 @@ def gen_oapi(config, oapi_filepath, mode='ogcapi-records'): 'parameters': [ {'$ref': '#/components/parameters/collectionId'}, {'$ref': '#/components/parameters/recordId'}, - {'$ref': '#/components/parameters/distributed'}, + {'$ref': '#/components/parameters/distributedSearch'}, f ], 'responses': { diff --git a/pycsw/ogc/api/records.py b/pycsw/ogc/api/records.py index 8cce622a0..d944b802b 100644 --- a/pycsw/ogc/api/records.py +++ b/pycsw/ogc/api/records.py @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2025 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2021 Angelos Tzotsos # # Permission is hereby granted, free of charge, to any person @@ -483,6 +483,23 @@ def collection(self, headers_, args, collection='metadata:main'): 'hreflang': self.config['server']['language'] }] + if collection == 'metadata:main' and 'federatedcatalogues' in self.config: + LOGGER.debug('Adding federated catalogues') + response['links'].append({ + 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/federatedCatalogues', + 'type': 'application/json', + 'title': 'Federated catalogs as JSON', + 'href': f"{url_base}/federatedCatalogs?f=json", + 'hreflang': self.config['server']['language'] + }) + response['links'].append({ + 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/federatedCatalogues', + 'type': 'text/html', + 'title': 'Federated catalogs as HTML', + 'href': f"{url_base}/federatedCatalogs?f=html", + 'hreflang': self.config['server']['language'] + }) + return self.get_response(200, headers_, response, 'collection.html') def queryables(self, headers_, args, collection='metadata:main'): @@ -550,7 +567,7 @@ def items(self, headers_, json_post_data, args, collection='metadata:main'): headers_['Content-Type'] = self.get_content_type(headers_, args) reserved_query_params = [ - 'distributed', + 'distributedsearch', 'f', 'facets', 'filter', @@ -796,19 +813,27 @@ def items(self, headers_, json_post_data, args, collection='metadata:main'): for record in records: response['features'].append(record2json(record, self.config['server']['url'], collection, self.mode)) - response['distributedFeatures'] = [] + response['federatedSearchResults'] = {} - distributed = str2bool(args.get('distributed', False)) + distributed = str2bool(args.get('distributedsearch', False)) if distributed: for fc in self.config.get('federatedcatalogues', []): - LOGGER.debug(f'Running distributed search against {fc}') - fc_url, _, fc_collection = fc.rsplit('/', 2) + if fc['type'] != 'OARec': + LOGGER.debug(f"Federated catalogue type {fc['type']} not supported; skipping") + continue + LOGGER.debug(f"Running distributed search against {fc['url']}") + fc_url, _, fc_collection = fc['url'].rsplit('/', 2) + response['federatedSearchResults'][fc['id']] = { + 'type': 'FeatureCollection', + 'features': [] + } try: w = Records(fc_url) + args.pop('distributedsearch') fc_results = w.collection_items(fc_collection, **args) for feature in fc_results['features']: - response['distributedFeatures'].append(feature) + response['federatedSearchResults'][fc['id']]['features'].append(feature) except Exception as err: LOGGER.warning(err) @@ -946,7 +971,10 @@ def item(self, headers_, args, collection, item): if distributed: for fc in self.config.get('federatedcatalogues', []): - LOGGER.debug(f'Running distributed item search against {fc}') + if fc['type'] != 'OARec': + LOGGER.debug(f"Federated catalogue type {fc['type']} not supported; skipping") + continue + LOGGER.debug(f"Running distributed item search against {fc['url']}") fc_url, _, fc_collection = fc.rsplit('/', 2) try: w = Records(fc_url) @@ -1133,19 +1161,80 @@ def get_collection_info(self, collection_name: str = 'metadata:main', }] } - if collection_name == 'metadata:main': - if 'federatedcatalogues' in self.config: - LOGGER.debug('Adding federated catalogues') - collection_info['federatedCatalogues'] = [] - if self.config.get('federatedcatalogues') not in [None, '']: # if empty in config - for fc in self.config.get('federatedcatalogues'): - collection_info['federatedCatalogues'].append({ - 'type': 'OGC API - Records', - 'url': fc - }) - return collection_info + def federated_catalogues(self, headers_, args, collection): + """ + Provide federated catalogues + + :param headers_: copy of HEADERS object + :param args: request parameters + :param collection: name of collection + + :returns: tuple of headers, status code, content + """ + + headers_['Content-Type'] = self.get_content_type(headers_, args) + + response = {} + fedcats = [] + + if collection == 'metadata:main': + for fedcat_ in self.config.get('federatedcatalogues', []): + if fedcat_ == 'OARec': + fedcats.append(fedcat_) + + if headers_['Content-Type'] == 'text/html': + response['title'] = self.config['metadata']['identification']['title'] + response['collection'] = collection + response['fedcats'] = fedcats + else: + response = fedcats + + template = 'federatedcatalogs.html' + + return self.get_response(200, headers_, response, template) + + def federated_catalogue(self, headers_, args, collection, catalogue): + """ + Provide federated catalogue + + :param headers_: copy of HEADERS object + :param args: request parameters + :param collection: name of collection + :param catalogue: id of catalogue + + :returns: tuple of headers, status code, content + """ + + headers_['Content-Type'] = self.get_content_type(headers_, args) + + response = {} + fedcat = None + + if collection == 'metadata:main': + fedcats = self.config.get('federatedcatalogues') + for fedcat_ in fedcats: + if fedcat_['id'] == catalogue and fedcat_['type'] == 'OARec': + fedcat = fedcat_ + break + + if fedcat is None: + msg = 'Federated catalogue does not exist' + LOGGER.exception(msg) + return self.get_exception(404, headers_, 'InvalidParameterValue', msg) + + if headers_['Content-Type'] == 'text/html': + response['title'] = self.config['metadata']['identification']['title'] + response['collection'] = collection + response['fedcat'] = fedcat + else: + response = fedcat + + template = 'federatedcatalog.html' + + return self.get_response(200, headers_, response, template) + def get_all_collections(self) -> list: """ Get all collections diff --git a/pycsw/ogc/csw/csw2.py b/pycsw/ogc/csw/csw2.py index 43e2f5718..914bab052 100644 --- a/pycsw/ogc/csw/csw2.py +++ b/pycsw/ogc/csw/csw2.py @@ -4,7 +4,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2015 Angelos Tzotsos # # Permission is hereby granted, free of charge, to any person @@ -834,9 +834,12 @@ def getrecords(self): from owslib.csw import CatalogueServiceWeb from owslib.ows import ExceptionReport for fedcat in self.parent.config.get('federatedcatalogues', []): + if fedcat['type'] != 'CSW': + LOGGER.debug(f"Federated catalogue type {fc['type']} not supported; skipping") + continue LOGGER.debug('Performing distributed search on federated \ - catalogue: %s.', fedcat) - remotecsw = CatalogueServiceWeb(fedcat, version='2.0.2', skip_caps=True) + catalogue: %s.', fedcat['url']) + remotecsw = CatalogueServiceWeb(fedcat['url'], version='2.0.2', skip_caps=True) try: if str(self.parent.request).startswith('http'): self.parent.request = self.parent.request.split('?')[-1] @@ -847,7 +850,7 @@ def getrecords(self): if hasattr(remotecsw, 'results'): LOGGER.debug( 'Distributed search results from catalogue \ - %s: %s.', fedcat, remotecsw.results) + %s: %s.', fedcat['url'], remotecsw.results) remotecsw_matches = int(remotecsw.results['matches']) plural = 's' if remotecsw_matches != 1 else '' @@ -855,16 +858,16 @@ def getrecords(self): matched = str(int(matched) + remotecsw_matches) dsresults.append(etree.Comment( ' %d result%s from %s ' % - (remotecsw_matches, plural, fedcat))) + (remotecsw_matches, plural, fedcat['url']))) dsresults.append(remotecsw.records) except ExceptionReport as err: - error_string = 'remote CSW %s returned exception: ' % fedcat + error_string = 'remote CSW %s returned exception: ' % fedcat['url'] dsresults.append(etree.Comment( ' %s\n\n%s ' % (error_string, err))) LOGGER.exception(error_string) except Exception as err: - error_string = 'remote CSW %s returned error: ' % fedcat + error_string = 'remote CSW %s returned error: ' % fedcat['url'] dsresults.append(etree.Comment( ' %s\n\n%s ' % (error_string, err))) LOGGER.exception(error_string) diff --git a/pycsw/ogc/csw/csw3.py b/pycsw/ogc/csw/csw3.py index e62524acc..6e33074e3 100644 --- a/pycsw/ogc/csw/csw3.py +++ b/pycsw/ogc/csw/csw3.py @@ -3,7 +3,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -983,12 +983,15 @@ def getrecords(self): from owslib.csw import CatalogueServiceWeb from owslib.ows import ExceptionReport for fedcat in self.parent.config.get('federatedcatalogues', []): + if fedcat['type'] != 'CSW': + LOGGER.debug(f"Federated catalogue type {fc['type']} not supported; skipping") + continue LOGGER.info('Performing distributed search on federated \ - catalogue: %s', fedcat) + catalogue: %s', fedcat['url']) try: start_time = time() - remotecsw = CatalogueServiceWeb(fedcat, version='3.0.0', skip_caps=True) + remotecsw = CatalogueServiceWeb(fedcat['url'], version='3.0.0', skip_caps=True) if str(self.parent.request).startswith('http'): self.parent.request = self.parent.request.split('?')[-1] self.parent.request = self.parent.request.replace('mode=opensearch', '') @@ -999,9 +1002,9 @@ def getrecords(self): fsr = etree.SubElement(searchresults, util.nspath_eval( 'csw30:FederatedSearchResult', self.parent.context.namespaces), - catalogueURL=fedcat) + catalogueURL=fedcat['url']) - msg = 'Distributed search results from catalogue %s: %s.' % (fedcat, remotecsw.results) + msg = 'Distributed search results from catalogue %s: %s.' % (fedcat['url'], remotecsw.results) LOGGER.debug(msg) fsr.append(etree.Comment(msg)) @@ -1021,12 +1024,12 @@ def getrecords(self): search_result.append(etree.fromstring(result.xml, self.parent.context.parser)) except ExceptionReport as err: - error_string = 'remote CSW %s returned exception: ' % fedcat + error_string = 'remote CSW %s returned exception: ' % fedcat['url'] searchresults.append(etree.Comment( ' %s\n\n%s ' % (error_string, err))) LOGGER.exception(error_string) except Exception as err: - error_string = 'remote CSW %s returned error: ' % fedcat + error_string = 'remote CSW %s returned error: ' % fedcat['url'] searchresults.append(etree.Comment( ' %s\n\n%s ' % (error_string, err))) LOGGER.exception(error_string) diff --git a/pycsw/server.py b/pycsw/server.py index 49fba5e99..f3c2b0631 100644 --- a/pycsw/server.py +++ b/pycsw/server.py @@ -4,7 +4,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2015 Angelos Tzotsos # Copyright (c) 2016 James Dickens # Copyright (c) 2016 Ricardo Silva @@ -330,7 +330,8 @@ def dispatch(self, writer=sys.stdout, write_headers=True): for fedcat in self.config['federatedcatalogues']: LOGGER.debug('federated catalogue: %s', fedcat) - constraints['FederatedCatalogues']['values'].append(fedcat) + if fedcat['type'] == 'CSW': + constraints['FederatedCatalogues']['values'].append(fedcat['url']) for key, value in self.outputschemas.items(): get_records_params = ops['GetRecords']['parameters'] diff --git a/pycsw/stac/api.py b/pycsw/stac/api.py index 8a8c85efa..cd7efd72f 100644 --- a/pycsw/stac/api.py +++ b/pycsw/stac/api.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2025 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -33,16 +33,17 @@ import os from pygeofilter.parsers.ecql import parse as parse_ecql +import requests from pycsw import __version__ from pycsw.core.pygeofilter_evaluate import to_filter from pycsw.ogc.api.oapi import gen_oapi from pycsw.ogc.api.records import API, build_anytext -from pycsw.core.util import geojson_geometry2bbox, wkt2geom +from pycsw.core.util import geojson_geometry2bbox, str2bool, wkt2geom LOGGER = logging.getLogger(__name__) -#: Return headers for requests (e.g:X-Powered-By) +# Return headers for requests (e.g:X-Powered-By) HEADERS = { 'Content-Type': 'application/json', 'X-Powered-By': f'pycsw {__version__}' @@ -421,6 +422,15 @@ def items(self, headers_, json_post_data, args, collection='metadata:main'): cql_ops = [] json_post_data2 = {} + distributed_search_args = {} + + distributed = str2bool(args.get('distributedSearch', False)) + + if distributed: + LOGGER.debug('Setting distributed search args') + args.pop('distributedSearch', None) + distributed_search_args = deepcopy(args) + distributed_search_args.pop('type', None) if collection not in self.get_all_collections(): msg = 'Invalid collection' @@ -608,6 +618,39 @@ def items(self, headers_, json_post_data, args, collection='metadata:main'): link['href'] = link['href'].replace('collections/metadata:main/items', 'search') links2.append(link) + if distributed: + for fc in self.config.get('federatedcatalogues', []): + distributed_search_args2 = deepcopy(distributed_search_args) + if 'collections' in fc: + if 'collections' in distributed_search_args2: + distributed_search_args2['collections'] += ','.join(fc['collections']) + else: + distributed_search_args2['collections'] = ','.join(fc['collections']) + + if fc['type'] != 'STAC-API': + LOGGER.debug(f"Federated catalogue type {fc['type']} not supported; skipping") + continue + + LOGGER.debug(f"Running distributed search against {fc['url']}") + url = get_stac_search_url(fc['url']) + if url is None: + LOGGER.debug('Unable to detect STAC API search URL; skipping') + continue + + response2['federatedSearchResults'][fc['id']] = { + 'type': 'FeatureCollection', + 'features': [] + } + + try: + LOGGER.debug(f'Querying STAC API search: {url}') + stac_search_results = requests.get(url, params=distributed_search_args2).json() + for feature in stac_search_results['features']: + response2['federatedSearchResults'][fc['id']]['features'].append(feature) + except Exception as err: + LOGGER.warning(err) + + response2['links'] = links2 response2['links'].extend([{ @@ -748,7 +791,16 @@ def manage_collection_item(self, headers_, action='create', item=None, data=None headers_=headers_, action=action, item=item, data=data) -def links2stacassets(collection, record): +def links2stacassets(collection: str, record: dict) -> dict: + """ + Transform record enclosure links to STAC assets + + :param collection: `str` of collection + :param record: `dict` of record + + :returns: `dict` of updated record with link assets + """ + LOGGER.debug('Transforming enclosure links to STAC assets') if 'stac_version' not in record: @@ -775,3 +827,30 @@ def links2stacassets(collection, record): record['assets'][asset_key] = asset return record + + +def get_stac_search_url(url: str) -> str: + """ + Get STAC search URL from a STAC API + + :param url: `str` of STAC API landing page + + :returns: `str` of STAC API search URL + """ + + stac_search_url = None + + LOGGER.debug(f'Deriving STAC API search URL from {url}') + stac_root = requests.get(url).json() + + for link in stac_root['links']: + if all([ + link['rel'] == 'search', + link['type'] == 'application/geo+json', + link.get('method', 'GET') == 'GET' + ]): + LOGGER.debug(f"Found STAC search URL at {link['href']}") + stac_search_url = link['href'] + break + + return stac_search_url diff --git a/pycsw/templates/collection.html b/pycsw/templates/collection.html index bdffbc212..866710960 100644 --- a/pycsw/templates/collection.html +++ b/pycsw/templates/collection.html @@ -35,6 +35,9 @@

{{ data['title'] }}

items queryables + {% if data.id == 'metadata:main' and config['federatedcatalogues'] %} + federated catalogs + {% endif %} diff --git a/pycsw/templates/collections.html b/pycsw/templates/collections.html index f1d692aa8..48fb7881a 100644 --- a/pycsw/templates/collections.html +++ b/pycsw/templates/collections.html @@ -34,6 +34,9 @@

Collections

items queryables + {% if col.id == 'metadata:main' and config['federatedcatalogues'] %} + federated catalogs + {% endif %} {% endfor %} diff --git a/pycsw/templates/federatedcatalog.html b/pycsw/templates/federatedcatalog.html new file mode 100644 index 000000000..823665892 --- /dev/null +++ b/pycsw/templates/federatedcatalog.html @@ -0,0 +1,38 @@ +{% extends "_base.html" %} +{% block title %}{{ super() }} Federated catalog {% endblock %} + +{% block crumbs %} +{{ super() }} / +Collections / +{{ data['title'] }} / +Federated catalogs / +{{ data['fedcat']['title'] }} +{% endblock %} + +{% block body %} + +
+

Federated catalog

+

{{ data['title'] }}

+ + + + + + + + + + + + + + + + + + +
IdTypeTitleURL
{{ data['fedcat']['id'] }}{{ data['fedcat']['type'] }}{{ data['fedcat']['title'] }}{{ data['fedcat']['url'] }}
+
+ +{% endblock %} diff --git a/pycsw/templates/federatedcatalogs.html b/pycsw/templates/federatedcatalogs.html new file mode 100644 index 000000000..645ff6f37 --- /dev/null +++ b/pycsw/templates/federatedcatalogs.html @@ -0,0 +1,37 @@ +{% extends "_base.html" %} +{% block title %}{{ super() }} Federated catalogs {% endblock %} + +{% block crumbs %} +{{ super() }} / +Collections / +{{ data['title'] }} / +Federated catalogs +{% endblock %} + +{% block body %} + +
+

Federated catalogs

+

{{ data['title'] }}

+ + + + + + + + + + + {% for fc in data['fedcats'] %} + + + + + + {% endfor %} + +
IdTypeTitle
{{ fc['id'] }}{{ fc['type'] }}{{ fc['title'] }}
+
+ +{% endblock %} diff --git a/pycsw/wsgi_flask.py b/pycsw/wsgi_flask.py index 9674f1452..a41c5ea4d 100644 --- a/pycsw/wsgi_flask.py +++ b/pycsw/wsgi_flask.py @@ -3,7 +3,7 @@ # Authors: Tom Kralidis # Angelos Tzotsos # -# Copyright (c) 2025 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # Copyright (c) 2021 Angelos Tzotsos # # Permission is hereby granted, free of charge, to any person @@ -204,6 +204,35 @@ def queryables(collection='metadata:main'): collection)) +@BLUEPRINT.route('/collections//federatedCatalogs') +def federated_catalogues(collection='metadata:main'): + """ + OGC API collection federated catalogues endpoint + + :param collection: collection name + + :returns: HTTP response + """ + + return get_response(api_.federated_catalogues(dict(request.headers), request.args, + collection)) + + +@BLUEPRINT.route('/collections//federatedCatalogs/') +def federated_catalogue(collection='metadata:main', catalogue=None): + """ + OGC API collection federated catalogue endpoint + + :param collection: collection name + :param catalogue: catalogue + + :returns: HTTP response + """ + + return get_response(api_.federated_catalogue(dict(request.headers), request.args, + collection, catalogue)) + + @BLUEPRINT.route('/collections//items', methods=['GET', 'POST']) @BLUEPRINT.route('/stac/search', methods=['GET', 'POST']) @BLUEPRINT.route('/stac/collections//items', methods=['GET', 'POST']) diff --git a/tests/functionaltests/suites/apiso-inspire/default.yml b/tests/functionaltests/suites/apiso-inspire/default.yml index d917a278c..e890dda9e 100644 --- a/tests/functionaltests/suites/apiso-inspire/default.yml +++ b/tests/functionaltests/suites/apiso-inspire/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml index 0753db51e..999767974 100644 --- a/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml +++ b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml @@ -260,7 +260,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml index 0753db51e..999767974 100644 --- a/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml +++ b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml @@ -260,7 +260,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/apiso/default.yml b/tests/functionaltests/suites/apiso/default.yml index 4ebe7f21e..e1e8b480a 100644 --- a/tests/functionaltests/suites/apiso/default.yml +++ b/tests/functionaltests/suites/apiso/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml index 71ab4b5c7..cd17d59d7 100644 --- a/tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml @@ -260,7 +260,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/atom/default.yml b/tests/functionaltests/suites/atom/default.yml index 8841b6b56..a8a8b7d7f 100644 --- a/tests/functionaltests/suites/atom/default.yml +++ b/tests/functionaltests/suites/atom/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml index b86da8535..3a2c22acf 100644 --- a/tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml @@ -197,7 +197,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/cite/default.yml b/tests/functionaltests/suites/cite/default.yml index 7e8747d23..463d3ac2e 100644 --- a/tests/functionaltests/suites/cite/default.yml +++ b/tests/functionaltests/suites/cite/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: true diff --git a/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml b/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml index a904e54d0..ef7ea1507 100644 --- a/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml +++ b/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml @@ -246,7 +246,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml b/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml index a904e54d0..ef7ea1507 100644 --- a/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml +++ b/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml @@ -246,7 +246,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml b/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml index a6f5bb1e1..9206d9253 100644 --- a/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml +++ b/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml @@ -151,7 +151,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw @@ -281,7 +281,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw diff --git a/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml b/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml index a904e54d0..ef7ea1507 100644 --- a/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml +++ b/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml @@ -246,7 +246,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml b/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml index 3c742d21c..cef30e06a 100644 --- a/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml +++ b/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml @@ -125,7 +125,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw @@ -255,7 +255,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw diff --git a/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml b/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml index a6f5bb1e1..9206d9253 100644 --- a/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml +++ b/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml @@ -151,7 +151,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw @@ -281,7 +281,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw diff --git a/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml b/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml index a6f5bb1e1..9206d9253 100644 --- a/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml +++ b/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml @@ -151,7 +151,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw @@ -281,7 +281,7 @@ - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw diff --git a/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml b/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml index a904e54d0..ef7ea1507 100644 --- a/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml +++ b/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml @@ -246,7 +246,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml b/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml index a904e54d0..ef7ea1507 100644 --- a/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml +++ b/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml @@ -246,7 +246,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/csw30/default.yml b/tests/functionaltests/suites/csw30/default.yml index 43cd0286b..fd51d7c04 100644 --- a/tests/functionaltests/suites/csw30/default.yml +++ b/tests/functionaltests/suites/csw30/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,10 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - https://demo.pycsw.org/gisdata/csw + - id: fedcat01 + type: CSW + title: Demo of gisdata GitHub repository + url: https://demo.pycsw.org/gisdata/csw manager: transactions: false diff --git a/tests/functionaltests/suites/default/default.yml b/tests/functionaltests/suites/default/default.yml index 72553aa4d..3a6f6acf6 100644 --- a/tests/functionaltests/suites/default/default.yml +++ b/tests/functionaltests/suites/default/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,10 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - https://demo.pycsw.org/gisdata/csw + - id: fedcat01 + type: CSW + title: Demo of gisdata GitHub repository + url: https://demo.pycsw.org/gisdata/csw manager: transactions: false diff --git a/tests/functionaltests/suites/dif/default.yml b/tests/functionaltests/suites/dif/default.yml index ef9c063b5..84c16c0f6 100644 --- a/tests/functionaltests/suites/dif/default.yml +++ b/tests/functionaltests/suites/dif/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml index b211f3de9..814ef5137 100644 --- a/tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml @@ -197,7 +197,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/duplicatefileid/default.yml b/tests/functionaltests/suites/duplicatefileid/default.yml index 13de579b0..50c426621 100644 --- a/tests/functionaltests/suites/duplicatefileid/default.yml +++ b/tests/functionaltests/suites/duplicatefileid/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log #federatedcatalogues: -# - http://geo.data.gov/geoportal/csw/discovery +# - id: fedcat01 +# type: CSW +# title: Arctic SDI +# url: https://catalogue.arctic-sdi.org/csw +# - id: fedcat02 +# type: OARec +# title: pycsw OGC CITE demo and Reference Implementation +# url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/ebrim/default.yml b/tests/functionaltests/suites/ebrim/default.yml index 4ab7a149e..541b69d74 100644 --- a/tests/functionaltests/suites/ebrim/default.yml +++ b/tests/functionaltests/suites/ebrim/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml index 50c8fbb35..56e0c9586 100644 --- a/tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml @@ -201,7 +201,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/fgdc/default.yml b/tests/functionaltests/suites/fgdc/default.yml index 79412cfd5..f44df1f6f 100644 --- a/tests/functionaltests/suites/fgdc/default.yml +++ b/tests/functionaltests/suites/fgdc/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml index 93746b8c4..d94ec9001 100644 --- a/tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml @@ -197,7 +197,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/gm03/default.yml b/tests/functionaltests/suites/gm03/default.yml index 4bb3f4719..34435ab47 100644 --- a/tests/functionaltests/suites/gm03/default.yml +++ b/tests/functionaltests/suites/gm03/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml index 697e93a5d..603782c1c 100644 --- a/tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml @@ -197,7 +197,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/harvesting/default.yml b/tests/functionaltests/suites/harvesting/default.yml index d54a94a20..2294f7a1f 100644 --- a/tests/functionaltests/suites/harvesting/default.yml +++ b/tests/functionaltests/suites/harvesting/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: true diff --git a/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml index 73d52afe3..5cce1cf4e 100644 --- a/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml @@ -305,7 +305,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/idswithpaths/default.yml b/tests/functionaltests/suites/idswithpaths/default.yml index 1e7ca45aa..101be1c2b 100644 --- a/tests/functionaltests/suites/idswithpaths/default.yml +++ b/tests/functionaltests/suites/idswithpaths/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log #federatedcatalogues: -# - http://geo.data.gov/geoportal/csw/discovery +# - id: fedcat01 +# type: CSW +# title: Arctic SDI +# url: https://catalogue.arctic-sdi.org/csw +# - id: fedcat02 +# type: OARec +# title: pycsw OGC CITE demo and Reference Implementation +# url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/iso19115p3/default.yml b/tests/functionaltests/suites/iso19115p3/default.yml index 4f25dc28c..b0b15e293 100644 --- a/tests/functionaltests/suites/iso19115p3/default.yml +++ b/tests/functionaltests/suites/iso19115p3/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/iso19115p3/expected/get_GetCapabilities.xml b/tests/functionaltests/suites/iso19115p3/expected/get_GetCapabilities.xml index 9182ff3cd..ff5646e55 100644 --- a/tests/functionaltests/suites/iso19115p3/expected/get_GetCapabilities.xml +++ b/tests/functionaltests/suites/iso19115p3/expected/get_GetCapabilities.xml @@ -261,7 +261,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/iso19115p3/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/iso19115p3/expected/post_GetCapabilities.xml index 9182ff3cd..ff5646e55 100644 --- a/tests/functionaltests/suites/iso19115p3/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/iso19115p3/expected/post_GetCapabilities.xml @@ -261,7 +261,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/manager/default.yml b/tests/functionaltests/suites/manager/default.yml index 37dbf50b3..6da9cf0db 100644 --- a/tests/functionaltests/suites/manager/default.yml +++ b/tests/functionaltests/suites/manager/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: true diff --git a/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml index 2dcb4c01f..bdbb50b29 100644 --- a/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml @@ -311,7 +311,7 @@ 3.0.0 - http://geo.data.gov/geoportal/csw/discovery + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/oaipmh/default.yml b/tests/functionaltests/suites/oaipmh/default.yml index 929bf2c85..ae0456403 100644 --- a/tests/functionaltests/suites/oaipmh/default.yml +++ b/tests/functionaltests/suites/oaipmh/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/opensearcheo/default.yml b/tests/functionaltests/suites/opensearcheo/default.yml index d55d5d680..e43844224 100644 --- a/tests/functionaltests/suites/opensearcheo/default.yml +++ b/tests/functionaltests/suites/opensearcheo/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log #federatedcatalogues: -# - http://geo.data.gov/geoportal/csw/discovery +# - id: fedcat01 +# type: CSW +# title: Arctic SDI +# url: https://catalogue.arctic-sdi.org/csw +# - id: fedcat02 +# type: OARec +# title: pycsw OGC CITE demo and Reference Implementation +# url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/repofilter/default.yml b/tests/functionaltests/suites/repofilter/default.yml index 6a4afcbdf..6eebec331 100644 --- a/tests/functionaltests/suites/repofilter/default.yml +++ b/tests/functionaltests/suites/repofilter/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/sru/default.yml b/tests/functionaltests/suites/sru/default.yml index 0a41b461d..fd34d2618 100644 --- a/tests/functionaltests/suites/sru/default.yml +++ b/tests/functionaltests/suites/sru/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/stablesort/default.yml b/tests/functionaltests/suites/stablesort/default.yml index 8ac161a6e..22e9d8321 100644 --- a/tests/functionaltests/suites/stablesort/default.yml +++ b/tests/functionaltests/suites/stablesort/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -39,7 +39,14 @@ logging: level: DEBUG federatedcatalogues: - - http://geo.data.gov/geoportal/csw/discovery + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/utf-8/default.yml b/tests/functionaltests/suites/utf-8/default.yml index 799c19aa2..3266b426e 100644 --- a/tests/functionaltests/suites/utf-8/default.yml +++ b/tests/functionaltests/suites/utf-8/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -42,7 +42,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - https://demo.pycsw.org/gisdata/csw + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false diff --git a/tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml b/tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml index 326c383fe..117e68da9 100644 --- a/tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml +++ b/tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml @@ -197,7 +197,7 @@ 3.0.0 - https://demo.pycsw.org/gisdata/csw + https://catalogue.arctic-sdi.org/csw 10 diff --git a/tests/functionaltests/suites/xslt/default.yml b/tests/functionaltests/suites/xslt/default.yml index 76f663204..3a0d4a4f8 100644 --- a/tests/functionaltests/suites/xslt/default.yml +++ b/tests/functionaltests/suites/xslt/default.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2026 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -45,7 +45,14 @@ logging: # logfile: /tmp/pycsw.log federatedcatalogues: - - https://demo.pycsw.org/gisdata/csw + - id: fedcat01 + type: CSW + title: Arctic SDI + url: https://catalogue.arctic-sdi.org/csw + - id: fedcat02 + type: OARec + title: pycsw OGC CITE demo and Reference Implementation + url: https://demo.pycsw.org/cite/collections/metadata:main manager: transactions: false