From 396126eab9c2a1ec7fdec218e1b6d11cdb7bfa10 Mon Sep 17 00:00:00 2001 From: Lars Falk-Petersen Date: Mon, 25 Nov 2024 16:05:37 +0100 Subject: [PATCH] Update edr to 1.2, change links. Also split out ogc api common to separate file. --- .gitignore | 2 +- sedr/edreq12.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++ sedr/ogcapi10.py | 62 ++++++++++++++++++++++++++++++++ sedr/preflight.py | 5 +-- sedr/schemat.py | 4 +-- 5 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 sedr/edreq12.py create mode 100644 sedr/ogcapi10.py diff --git a/.gitignore b/.gitignore index 5374aed..0728a4b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,8 @@ venv .vscode __pycache__ venv -logs .tox old .*_cache .ropeproject +*.log diff --git a/sedr/edreq12.py b/sedr/edreq12.py new file mode 100644 index 0000000..c1d9c67 --- /dev/null +++ b/sedr/edreq12.py @@ -0,0 +1,90 @@ +"""EDR requirements.""" + +import util + +edr_version = "1.2" +edr_root_url = "https://docs.ogc.org/DRAFTS/19-086r7.html" +ogc_api_common_url = "https://docs.ogc.org/is/19-072/19-072.html" +conformance_urls = [ + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-common-2/1.0/conf/collections", + f"http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/core", # Assume this will be changed to edr_version +] +openapi_conformance_urls = [ + "http://www.opengis.net/spec/ogcapi-edr-1/1.1/req/oas30", # Assume this will be changed to oas31 + "http://www.opengis.net/spec/ogcapi-edr-1/1.2/req/oas31", +] + + +def requirementA2_2_A5(jsondata: dict, siteurl="") -> tuple[bool, str]: + """ + OGC API - Environmental Data Retrieval Standard + Version: 1.2 + Requirement Annex A2.2 A5 + + Check if the conformance page contains the required EDR classes. + jsondata should be the "conformsTo"-part of the conformance page. + """ + spec_url = f"{edr_root_url}#req_core_conformance" + if "conformsTo" not in jsondata: + return ( + False, + f"Conformance page <{siteurl}conformance> does not contain a conformsTo attribute. See <{spec_url}> for more info.", + ) + for url in conformance_urls: + if url not in jsondata["conformsTo"]: + return ( + False, + f"Conformance page <{siteurl}conformance> does not contain the core edr class {url}. See <{spec_url}> for more info.", + ) + + util.logger.debug( + "requirementA2_2_A5: conformance page contains the required EDR classes." + ) + return True, "" + + +def requirementA2_2_A7(version: int) -> tuple[bool, str]: + """ + OGC API - Environmental Data Retrieval Standard + Version: 1.2 + Requirement Annex A2.2 A7 + + Check if HTTP1.1 was used. + """ + spec_url = f"{edr_root_url}#_req_core_http" + if version == 11: + util.logger.debug("requirementA2_2_A7 HTTP version 1.1 was used.") + return True, "" + + return False, f"HTTP version 1.1 was not used. See <{spec_url}> for more info." + + +def requirementA11_1(jsondata: dict) -> tuple[bool, str]: + """ + OGC API - Environmental Data Retrieval Standard + Version: 1.1 + Requirement A11.1 + + Check if the conformance page contains openapi classes, and that they match our version.""" + spec_url = f"{edr_root_url}#_requirements_class_openapi_3_0" + + for url in jsondata["conformsTo"]: + if url in openapi_conformance_urls: + if ( + util.args.openapi_version == "3.1" + and "oas31" in url + or util.args.openapi_version == "3.0" + and "oas30" in url + ): + util.logger.debug("requirementA11_1 Found openapi class <%s>", url) + return True, url + return ( + False, + f"OpenAPI version {util.args.openapi_version} and version in conformance {url} doesn't match. See <{spec_url}> for more info.", + ) + + return ( + False, + f"Conformance page /conformance does not contain an openapi class. See <{spec_url}> for more info.", + ) diff --git a/sedr/ogcapi10.py b/sedr/ogcapi10.py new file mode 100644 index 0000000..104e3e2 --- /dev/null +++ b/sedr/ogcapi10.py @@ -0,0 +1,62 @@ +"""OGC API Common requirements.""" + +import util + +ogc_api_common_version = "1.0" +ogc_api_common_url = "https://docs.ogc.org/is/19-072/19-072.html" + + +def requirement9_1(jsondata: dict) -> tuple[bool, str]: + """ + OGC API - Common - Part 1: Core + Version: 1.0.0 + Requirement 9.1 + + Test that the landing page contains required elements. + + TODO: See https://github.com/metno/sedr/issues/6 + """ + spec_ref = f"{ogc_api_common_url}#_7c772474-7037-41c9-88ca-5c7e95235389" + + if "title" not in jsondata: + return ( + False, + "Landing page does not contain a title. See <{spec_ref}> for more info.", + ) + if "description" not in jsondata: + return ( + False, + "Landing page does not contain a description. See <{spec_ref}> for more info.", + ) + if "links" not in jsondata: + return ( + False, + "Landing page does not contain links. See <{spec_ref}> for more info.", + ) + + service_desc = "" + for link in jsondata["links"]: + if not isinstance(link, dict): + return ( + False, + f"Link {link} is not a dictionary. See <{spec_ref}> for more info.", + ) + if "href" not in link: + return ( + False, + f"Link {link} does not have a href attribute. See <{spec_ref}> for more info.", + ) + if "rel" not in link: + return ( + False, + f"Link {link} does not have a rel attribute. See <{spec_ref}> for more info.", + ) + if link["rel"] == "service-desc": + service_desc = link["href"] + if not service_desc: + return ( + False, + f"Landing page does not contain a service-desc link. See <{spec_ref}> for more info.", + ) + util.logger.debug("requirement9_1 Landing page contains required elements.") + return True, "" diff --git a/sedr/preflight.py b/sedr/preflight.py index 802e3f0..276920c 100644 --- a/sedr/preflight.py +++ b/sedr/preflight.py @@ -4,7 +4,8 @@ import requests import json from urllib.parse import urljoin -import edreq11 as edreq +import edreq12 as edreq +import ogcapi10 as ogcapi import rodeoprofile10 as rodeoprofile @@ -31,7 +32,7 @@ def parse_landing(url, timeout=10) -> tuple[bool, dict]: util.logger.warning("Landing page <%s> is not valid JSON.", url) return False, landing_json - landing, requirement9_1_message = edreq.requirement9_1(landing_json) + landing, requirement9_1_message = ogcapi.requirement9_1(landing_json) if not landing: util.logger.error(requirement9_1_message) return False, landing_json diff --git a/sedr/schemat.py b/sedr/schemat.py index ec60305..842b175 100644 --- a/sedr/schemat.py +++ b/sedr/schemat.py @@ -10,7 +10,7 @@ import requests import util -import edreq11 as edreq +import edreq12 as edreq import rodeoprofile10 as rodeoprofile @@ -38,7 +38,7 @@ def set_up_schemathesis(args) -> BaseOpenAPISchema: ) util.logger.info("Found openapi spec: %s", util.args.openapi) - util.logger.info("Using EDR version %s", edreq.__edr_version__) + util.logger.info("Using EDR version %s", edreq.edr_version) if args.openapi.startswith("http"): util.logger.info(