diff --git a/.clabot b/.clabot index 641129a5885..3c433292143 100644 --- a/.clabot +++ b/.clabot @@ -77,6 +77,6 @@ "ahmdthr", "fvicent", "RegisSinjari", - "Gpetrak", + "Gpetrak" ] } diff --git a/geonode/catalogue/backends/pycsw_local.py b/geonode/catalogue/backends/pycsw_local.py index 75c66e96498..2fdc8a123b8 100644 --- a/geonode/catalogue/backends/pycsw_local.py +++ b/geonode/catalogue/backends/pycsw_local.py @@ -52,13 +52,14 @@ "pretty_print": "true", "domainquerytype": "range", "domaincounts": "true", - "profiles": "apiso,ebrim", }, + "profiles": {"apiso", "ebrim"}, "repository": { "source": "geonode.catalogue.backends.pycsw_plugin.GeoNodeRepository", "filter": "uuid IS NOT NULL", "mappings": os.path.join(os.path.dirname(__file__), "pycsw_local_mappings.py"), }, + "logging": {"level": "ERROR"}, } diff --git a/geonode/catalogue/backends/pycsw_local_mappings.py b/geonode/catalogue/backends/pycsw_local_mappings.py index 4bbb8648b88..303906937c1 100644 --- a/geonode/catalogue/backends/pycsw_local_mappings.py +++ b/geonode/catalogue/backends/pycsw_local_mappings.py @@ -28,12 +28,16 @@ "pycsw:MdSource": "csw_mdsource", "pycsw:InsertDate": "csw_insert_date", "pycsw:XML": "metadata_xml", + "pycsw:Metadata": "metadata", + "pycsw:MetadataType": "metadata_type", "pycsw:AnyText": "csw_anytext", "pycsw:Language": "language", "pycsw:Title": "title", "pycsw:Abstract": "raw_abstract", + "pycsw:Edition": "csw_edition", "pycsw:Keywords": "keyword_csv", "pycsw:KeywordType": "keywordstype", + "pycsw:Themes": "csw_themes", "pycsw:Format": "spatial_representation_type_string", "pycsw:Source": "source", "pycsw:Date": "date", @@ -45,7 +49,6 @@ "pycsw:RevisionDate": "date", "pycsw:CreationDate": "date", "pycsw:PublicationDate": "date", - "pycsw:Organization": "organizationname", "pycsw:OrganizationName": "organizationname", "pycsw:SecurityConstraints": "securityconstraints", "pycsw:ParentIdentifier": "parentidentifier", @@ -78,6 +81,12 @@ "pycsw:Publisher": "publisher", "pycsw:Contributor": "contributor", "pycsw:Relation": "relation", + "pycsw:Platform": "platform", + "pycsw:Instrument": "instrument", + "pycsw:SensorType": "sensortype", + "pycsw:CloudCover": "cloudcover", + "pycsw:Bands": "bands", "pycsw:Links": "download_links", + "pycsw:Contacts": "contacts", }, } diff --git a/geonode/catalogue/tests.py b/geonode/catalogue/tests.py index 49988818af5..deeade4d877 100644 --- a/geonode/catalogue/tests.py +++ b/geonode/catalogue/tests.py @@ -111,7 +111,7 @@ def test_given_a_request_for_multiple_dataset_should_return_multiple_value_in_xm request = self.__request_factory_multiple() response = csw_global_dispatch(request, self.dataset_filter_multiple) root = ET.fromstring(response.content) - actual = root.find("{http://www.opengis.net/cat/csw/2.0.2}SearchResults").attrib["numberOfRecordsReturned"] + actual = root.find("{http://www.opengis.net/cat/csw/2.0.2}SearchResults").attrib["numberOfRecordsMatched"] self.assertEqual(2, int(actual)) @staticmethod diff --git a/geonode/catalogue/views.py b/geonode/catalogue/views.py index 8e64559f8c1..a5b52f4f30f 100644 --- a/geonode/catalogue/views.py +++ b/geonode/catalogue/views.py @@ -164,12 +164,12 @@ def opensearch_dispatch(request): """OpenSearch wrapper""" ctx = { - "shortname": settings.PYCSW["CONFIGURATION"]["metadata:main"]["identification_title"], - "description": settings.PYCSW["CONFIGURATION"]["metadata:main"]["identification_abstract"], - "developer": settings.PYCSW["CONFIGURATION"]["metadata:main"]["contact_name"], - "contact": settings.PYCSW["CONFIGURATION"]["metadata:main"]["contact_email"], - "attribution": settings.PYCSW["CONFIGURATION"]["metadata:main"]["provider_name"], - "tags": settings.PYCSW["CONFIGURATION"]["metadata:main"]["identification_keywords"].replace(",", " "), + "shortname": settings.PYCSW["CONFIGURATION"]["metadata"]["identification"]["title"], + "description": settings.PYCSW["CONFIGURATION"]["metadata"]["identification"]["description"], + "developer": settings.PYCSW["CONFIGURATION"]["metadata"]["contact"]["name"], + "contact": settings.PYCSW["CONFIGURATION"]["metadata"]["contact"]["email"], + "attribution": settings.PYCSW["CONFIGURATION"]["metadata"]["provider"]["name"], + "tags": settings.PYCSW["CONFIGURATION"]["metadata"]["identification"]["keywords"].replace(",", " "), "url": settings.SITEURL.rstrip("/") if settings.SITEURL.startswith("http") else settings.SITEURL, } diff --git a/geonode/layers/views.py b/geonode/layers/views.py index 776085235e0..04425be41d9 100644 --- a/geonode/layers/views.py +++ b/geonode/layers/views.py @@ -204,7 +204,7 @@ def dataset_feature_catalogue(request, layername, template="../../catalogue/temp context_dict = { "dataset": layer, "attributes": attributes, - "metadata": settings.PYCSW["CONFIGURATION"]["metadata:main"], + "metadata": settings.PYCSW["CONFIGURATION"]["metadata"], } register_event(request, "view", layer) return render(request, template, context=context_dict, content_type="application/xml") diff --git a/geonode/local_settings.py.geoserver.sample b/geonode/local_settings.py.geoserver.sample index d7ea4c9bc9d..8805b48530a 100644 --- a/geonode/local_settings.py.geoserver.sample +++ b/geonode/local_settings.py.geoserver.sample @@ -178,7 +178,7 @@ PYCSW = { "home": ".", "url": CATALOGUE["default"]["URL"], "encoding": "UTF-8", - "language": LANGUAGE_CODE, + "language": LANGUAGE_CODE if LANGUAGE_CODE in ("en", "fr", "el") else "en", "maxrecords": "20", "pretty_print": "true", # 'domainquerytype': 'range', @@ -191,34 +191,9 @@ PYCSW = { "allowed_ips": "*", # 'csw_harvest_pagesize': '10', }, - "metadata:main": { - "identification_title": "GeoNode Catalogue", - "identification_abstract": "GeoNode is an open source platform" - " that facilitates the creation, sharing, and collaborative use" - " of geospatial data", - "identification_keywords": "sdi, catalogue, discovery, metadata," " GeoNode", - "identification_keywords_type": "theme", - "identification_fees": "None", - "identification_accessconstraints": "None", - "provider_name": "Organization Name", - "provider_url": SITEURL, - "contact_name": "Lastname, Firstname", - "contact_position": "Position Title", - "contact_address": "Mailing Address", - "contact_city": "City", - "contact_stateorprovince": "Administrative Area", - "contact_postalcode": "Zip or Postal Code", - "contact_country": "Country", - "contact_phone": "+xx-xxx-xxx-xxxx", - "contact_fax": "+xx-xxx-xxx-xxxx", - "contact_email": "Email Address", - "contact_url": "Contact URL", - "contact_hours": "Hours of Service", - "contact_instructions": "During hours of service. Off on " "weekends.", - "contact_role": "pointOfContact", - }, - "metadata:inspire": { - "enabled": "true", + "metadata": { + "inspire": { + "enabled": True, "languages_supported": "eng,gre", "default_language": "eng", "date": "YYYY-MM-DD", @@ -226,8 +201,42 @@ PYCSW = { "conformity_service": "notEvaluated", "contact_name": "Organization Name", "contact_email": "Email Address", - "temp_extent": "YYYY-MM-DD/YYYY-MM-DD", - }, + "temp_extent": { + "begin": "YYYY-MM-DD", + "end": "YYYY-MM-DD" + }, + }, + "identification": { + "title": "GeoNode Catalogue", + "description": "GeoNode is an open source platform" + " that facilitates the creation, sharing, and collaborative use" + " of geospatial data", + "keywords": "sdi, catalogue, discovery, metadata," " GeoNode", + "keywords_type": "theme", + "fees": "None", + "accessconstraints": "None", + }, + "provider": { + "name": "Organization Name", + "url": SITEURL, + }, + "contact": { + "name": "Lastname, Firstname", + "position": "Position Title", + "address": "Mailing Address", + "city": "City", + "stateorprovince": "Administrative Area", + "postalcode": "Zip or Postal Code", + "country": "Country", + "phone": "+xx-xxx-xxx-xxxx", + "fax": "+xx-xxx-xxx-xxxx", + "email": "Email Address", + "url": "Contact URL", + "hours": "Hours of Service", + "instructions": "During hours of service. Off on " "weekends.", + "role": "pointOfContact", + } + } } } @@ -274,10 +283,10 @@ if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == "mapstore": pycsw_config = PYCSW["CONFIGURATION"] if pycsw_config: pycsw_catalogue = { - ("%s" % pycsw_config["metadata:main"]["identification_title"]): { + ("%s" % pycsw_config["metadata"]["identification"]): { "url": CATALOGUE["default"]["URL"], "type": "csw", - "title": pycsw_config["metadata:main"]["identification_title"], + "title": pycsw_config["metadata"]["identification"]["title"], "autoload": True, } } diff --git a/geonode/settings.py b/geonode/settings.py index 119844bbe02..d4afe3053b4 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -1141,42 +1141,51 @@ "allowed_ips": "*", # 'csw_harvest_pagesize': '10', }, - "metadata:main": { - "identification_title": "GeoNode Catalogue", - "identification_abstract": "GeoNode is an open source platform" - " that facilitates the creation, sharing, and collaborative use" - " of geospatial data", - "identification_keywords": "sdi, catalogue, discovery, metadata," " GeoNode", - "identification_keywords_type": "theme", - "identification_fees": "None", - "identification_accessconstraints": "None", - "provider_name": "Organization Name", - "provider_url": SITEURL, - "contact_name": "Lastname, Firstname", - "contact_position": "Position Title", - "contact_address": "Mailing Address", - "contact_city": "City", - "contact_stateorprovince": "Administrative Area", - "contact_postalcode": "Zip or Postal Code", - "contact_country": "Country", - "contact_phone": "+xx-xxx-xxx-xxxx", - "contact_fax": "+xx-xxx-xxx-xxxx", - "contact_email": "Email Address", - "contact_url": "Contact URL", - "contact_hours": "Hours of Service", - "contact_instructions": "During hours of service. Off on " "weekends.", - "contact_role": "pointOfContact", - }, - "metadata:inspire": { - "enabled": "true", - "languages_supported": "eng,gre", - "default_language": "eng", - "date": "YYYY-MM-DD", - "gemet_keywords": "Utility and governmental services", - "conformity_service": "notEvaluated", - "contact_name": "Organization Name", - "contact_email": "Email Address", - "temp_extent": "YYYY-MM-DD/YYYY-MM-DD", + "metadata": { + "inspire": { + "enabled": True, + "languages_supported": "eng,gre", + "default_language": "eng", + "date": "YYYY-MM-DD", + "gemet_keywords": "Utility and governmental services", + "conformity_service": "notEvaluated", + "contact_name": "Organization Name", + "contact_email": "Email Address", + "temp_extent": { + "begin": "YYYY-MM-DD", + "end": "YYYY-MM-DD", + }, + }, + "identification": { + "title": "GeoNode Catalogue", + "description": "GeoNode is an open source platform" + " that facilitates the creation, sharing, and collaborative use" + " of geospatial data", + "keywords": "sdi, catalogue, discovery, metadata," " GeoNode", + "keywords_type": "theme", + "fees": "None", + "accessconstraints": "None", + }, + "provider": { + "name": "Organization Name", + "url": SITEURL, + }, + "contact": { + "name": "Lastname, Firstname", + "position": "Position Title", + "address": "Mailing Address", + "city": "City", + "stateorprovince": "Administrative Area", + "postalcode": "Zip or Postal Code", + "country": "Country", + "phone": "+xx-xxx-xxx-xxxx", + "fax": "+xx-xxx-xxx-xxxx", + "email": "Email Address", + "url": "Contact URL", + "hours": "Hours of Service", + "instructions": "During hours of service. Off on " "weekends.", + "role": "pointOfContact", + }, }, } } @@ -1460,10 +1469,10 @@ def get_geonode_catalogue_service(): pycsw_config = PYCSW["CONFIGURATION"] if pycsw_config: pycsw_catalogue = { - f"{pycsw_config['metadata:main']['identification_title']}": { + f"{pycsw_config['metadata']['identification']}": { "url": CATALOGUE["default"]["URL"], "type": "csw", - "title": pycsw_config["metadata:main"]["identification_title"], + "title": pycsw_config["metadata"]["identification"]["title"], "autoload": True, "layerOptions": {"tileSize": DEFAULT_TILE_SIZE}, } diff --git a/geonode/views.py b/geonode/views.py index 8dc0dbe8bef..649478aff09 100644 --- a/geonode/views.py +++ b/geonode/views.py @@ -116,11 +116,11 @@ def ident_json(request): site_url = settings.SITEURL.rstrip("/") if settings.SITEURL.startswith("http") else settings.SITEURL json_data = {} json_data["siteurl"] = site_url - json_data["name"] = settings.PYCSW["CONFIGURATION"]["metadata:main"]["identification_title"] + json_data["name"] = settings.PYCSW["CONFIGURATION"]["metadata"]["identification"]["title"] json_data["poc"] = { - "name": settings.PYCSW["CONFIGURATION"]["metadata:main"]["contact_name"], - "email": settings.PYCSW["CONFIGURATION"]["metadata:main"]["contact_email"], + "name": settings.PYCSW["CONFIGURATION"]["metadata"]["contact"]["name"], + "email": settings.PYCSW["CONFIGURATION"]["metadata"]["contact"]["email"], "twitter": f"https://twitter.com/{settings.TWITTER_SITE}", } diff --git a/package/support/geonode.local_settings b/package/support/geonode.local_settings index 6530b168322..ea7313cda09 100644 --- a/package/support/geonode.local_settings +++ b/package/support/geonode.local_settings @@ -196,51 +196,75 @@ CATALOGUE = { # pycsw settings PYCSW = { # pycsw configuration - 'CONFIGURATION': { + "CONFIGURATION": { # uncomment / adjust to override server config system defaults # 'server': { # 'maxrecords': '10', # 'pretty_print': 'true', # 'federatedcatalogues': 'http://catalog.data.gov/csw' # }, - 'metadata:main': { - 'identification_title': 'GeoNode Catalogue', - 'identification_abstract': 'GeoNode is an open source platform' \ - ' that facilitates the creation, sharing, and collaborative use' \ - ' of geospatial data', - 'identification_keywords': 'sdi, catalogue, discovery, metadata,' \ - ' GeoNode', - 'identification_keywords_type': 'theme', - 'identification_fees': 'None', - 'identification_accessconstraints': 'None', - 'provider_name': 'Organization Name', - 'provider_url': SITEURL, - 'contact_name': 'Lastname, Firstname', - 'contact_position': 'Position Title', - 'contact_address': 'Mailing Address', - 'contact_city': 'City', - 'contact_stateorprovince': 'Administrative Area', - 'contact_postalcode': 'Zip or Postal Code', - 'contact_country': 'Country', - 'contact_phone': '+xx-xxx-xxx-xxxx', - 'contact_fax': '+xx-xxx-xxx-xxxx', - 'contact_email': 'Email Address', - 'contact_url': 'Contact URL', - 'contact_hours': 'Hours of Service', - 'contact_instructions': 'During hours of service. Off on ' \ - 'weekends.', - 'contact_role': 'pointOfContact', + "server": { + "home": ".", + "url": CATALOGUE["default"]["URL"], + "encoding": "UTF-8", + "language": LANGUAGE_CODE if LANGUAGE_CODE in ("en", "fr", "el") else "en", + "maxrecords": "20", + "pretty_print": "true", + # 'domainquerytype': 'range', + "domaincounts": "true", + "profiles": "apiso,ebrim", }, - 'metadata:inspire': { - 'enabled': 'true', - 'languages_supported': 'eng,gre', - 'default_language': 'eng', - 'date': 'YYYY-MM-DD', - 'gemet_keywords': 'Utility and governmental services', - 'conformity_service': 'notEvaluated', - 'contact_name': 'Organization Name', - 'contact_email': 'Email Address', - 'temp_extent': 'YYYY-MM-DD/YYYY-MM-DD', + "manager": { + # authentication/authorization is handled by Django + "transactions": "false", + "allowed_ips": "*", + # 'csw_harvest_pagesize': '10', + }, + "metadata": { + "inspire": { + "enabled": True, + "languages_supported": "eng,gre", + "default_language": "eng", + "date": "YYYY-MM-DD", + "gemet_keywords": "Utility and governmental services", + "conformity_service": "notEvaluated", + "contact_name": "Organization Name", + "contact_email": "Email Address", + "temp_extent": { + "begin": "YYYY-MM-DD", + "end": "YYYY-MM-DD", + }, + }, + "identification": { + "title": "GeoNode Catalogue", + "description": "GeoNode is an open source platform" + " that facilitates the creation, sharing, and collaborative use" + " of geospatial data", + "keywords": "sdi, catalogue, discovery, metadata," " GeoNode", + "keywords_type": "theme", + "fees": "None", + "accessconstraints": "None", + }, + "provider": { + "name": "Organization Name", + "url": SITEURL, + }, + "contact": { + "name": "Lastname, Firstname", + "position": "Position Title", + "address": "Mailing Address", + "city": "City", + "stateorprovince": "Administrative Area", + "postalcode": "Zip or Postal Code", + "country": "Country", + "phone": "+xx-xxx-xxx-xxxx", + "fax": "+xx-xxx-xxx-xxxx", + "email": "Email Address", + "url": "Contact URL", + "hours": "Hours of Service", + "instructions": "During hours of service. Off on " "weekends.", + "role": "pointOfContact", + } } } } diff --git a/requirements.txt b/requirements.txt index b21407db133..e8166a19fd1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -53,13 +53,14 @@ pyopenssl==24.1.0 pyjwt==2.8.0 # geopython dependencies +git+https://github.com/geopython/pycsw.git@master#egg=pycsw pyproj<3.7.0 OWSLib==0.31.0 -pycsw==2.6.1 SQLAlchemy==2.0.30 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 numpy==1.26.* +Jinja2==3.1.4 # # Apps with packages provided in GeoNode's PPA on Launchpad. diff --git a/setup.cfg b/setup.cfg index 94b5c655a11..6e4890f41e5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -81,11 +81,12 @@ install_requires = # geopython dependencies pyproj<3.7.0 OWSLib==0.31.0 - pycsw==2.6.1 + pycsw @ git+https://github.com/geopython/pycsw.git@master#egg=pycsw SQLAlchemy==2.0.30 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 numpy==1.26.* + Jinja2==3.1.4 # # Apps with packages provided in GeoNode's PPA on Launchpad.