Skip to content

Commit 6f3e47b

Browse files
committed
Implementations of inspire checks have been removed.
See docstrings in both checks. Unusable inspire tests have been removed. Tests have been adapted to inspire check always returning cancelled. The code of test_raster_products has been unified. The code of test_vector_products has been unified. Nonfunctional skip_inspire_check has been removed from ProductTestCase.
1 parent 045bea6 commit 6f3e47b

7 files changed

Lines changed: 121 additions & 260 deletions

File tree

src/qc_tool/raster/inspire.py

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,20 @@
22
# -*- coding: utf-8 -*-
33

44

5-
import json
6-
import socket
7-
from urllib.error import HTTPError
8-
from urllib.error import URLError
9-
from urllib.request import Request
10-
from urllib.request import urlopen
11-
from xml.etree import ElementTree
5+
"""
6+
The last implementation used external inspire validation service at `<http://inspire-geoportal.ec.europa.eu/GeoportalProxyWebServices/resources/INSPIREResourceTester>`_.
7+
Such service has been discontinued.
8+
9+
Until new implementation come, the check always results in cancelled.
10+
Cancelled result does not prevent later submittion of the delivery.
11+
This way it may be avoided adapting and hampering already stable product definitions.
12+
"""
1213

1314

1415
DESCRIPTION = "Metadata are in accord with INSPIRE specification."
1516
IS_SYSTEM = False
1617

17-
INSPIRE_SERVICE_URL = "http://inspire-geoportal.ec.europa.eu/GeoportalProxyWebServices/resources/INSPIREResourceTester"
18-
1918

2019
def run_check(params, status):
21-
from qc_tool.raster.helper import do_raster_layers
22-
23-
for layer_def in do_raster_layers(params):
24-
# Find the xml metadata file, it can be .xml or .tif.xml.
25-
for xml_filepath in [layer_def["src_filepath"].with_suffix(".xml"),
26-
layer_def["src_filepath"].with_suffix(".tif.xml")]:
27-
if xml_filepath.exists():
28-
break
29-
else:
30-
status.failed("Metadata file for {:s} has not been found.".format(layer_def["src_filepath"].name))
31-
continue
32-
33-
# Check if the metadata file is a valid xml document.
34-
try:
35-
ElementTree.parse(str(xml_filepath))
36-
except ElementTree.ParseError:
37-
status.failed("Metadata file {:s} is not a valid XML document.".format(xml_filepath.name))
38-
continue
39-
40-
# Post the metadata file content to INSPIRE validator service.
41-
try:
42-
req = Request(INSPIRE_SERVICE_URL,
43-
data=xml_filepath.read_bytes(),
44-
headers={"Accept": "application/json", "Content-Type": "text/plain"})
45-
with urlopen(req, timeout=60) as resp:
46-
json_data = json.loads(resp.read().decode("utf-8"))
47-
except HTTPError as ex:
48-
status.cancelled("Unable to validate metadata of {:s}: {:s}."
49-
.format(xml_filepath.name, str(ex)))
50-
continue
51-
except URLError:
52-
status.cancelled("Unable to validate metadata of {:s}: Service not available."
53-
.format(xml_filepath.name))
54-
continue
55-
except socket.timeout:
56-
status.cancelled("Unable to validate metadata of {:s}: Connection timeout."
57-
.format(xml_filepath.name))
58-
continue
59-
except Exception as ex:
60-
status.cancelled("Unable to validate metadata of {:s}: {:s}"
61-
.format(xml_filepath.name, repr(ex)))
62-
63-
# The metadata content is valid if the completeness indicator is equal to 100.0.
64-
# Warnings are ignored.
65-
try:
66-
inspire_ok = json_data["value"]["CompletenessIndicator"] == 100
67-
except:
68-
inspire_ok = False
69-
70-
if not inspire_ok:
71-
status.failed("Metadata file {:s} is not valid.".format(xml_filepath.name))
72-
error_filename = "s{:02d}_{:s}_metadata_error.json".format(params["step_nr"], layer_def["src_filepath"].stem)
73-
error_filepath = params["output_dir"].joinpath(error_filename)
74-
error_filepath.write_text(json.dumps(json_data, indent=4, sort_keys=True))
75-
status.add_attachment(error_filepath.name)
20+
"""The check always results in cancelled."""
21+
status.cancelled("The check is not implemented yet.")

src/qc_tool/test/helper.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ def setUp(self):
2222
# Set up boundary dir to testing sources.
2323
CONFIG["boundary_dir"] = TEST_DATA_DIR.joinpath("boundaries")
2424

25-
# online INSPIRE validator is skipped in tests.
26-
CONFIG["skip_inspire_check"] = True
27-
2825

2926
class RasterCheckTestCase(TestCase):
3027
def setUp(self):

src/qc_tool/test/test_raster_check.py

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -298,44 +298,6 @@ def test_fail(self):
298298
self.assertIn("s01_mmu_raster_incorrect_lessmmu_error.gpkg", status.attachment_filenames)
299299

300300

301-
@skipIf(CONFIG["skip_inspire_check"], "INSPIRE check has been disabled.")
302-
class Test_inspire(RasterCheckTestCase):
303-
def setUp(self):
304-
super().setUp()
305-
xml_dir = TEST_DATA_DIR.joinpath("metadata")
306-
filepath_good = xml_dir.joinpath("inspire-good.tif")
307-
filepath_missing = xml_dir.joinpath("inspire-missing-metadata.tif")
308-
filepath_bad = xml_dir.joinpath("inspire-bad.tif")
309-
layer_defs = {"layer_good": {"src_filepath": filepath_good, "src_layer_name": filepath_good.name},
310-
"layer_missing": {"src_filepath": filepath_missing, "src_layer_name": filepath_missing.name},
311-
"layer_bad": {"src_filepath": filepath_bad, "src_layer_name": filepath_bad.name}}
312-
self.params.update({"raster_layer_defs": layer_defs,
313-
"step_nr": 1,
314-
"output_dir": self.jobdir_manager.output_dir})
315-
316-
def test(self):
317-
from qc_tool.raster.inspire import run_check
318-
self.params.update({"layers":["layer_good"]})
319-
status = self.status_class()
320-
run_check(self.params, status)
321-
self.assertEqual("ok", status.status, "INSPIRE raster check should pass for raster with valid metadata file.")
322-
323-
def test_missing_xml_fail(self):
324-
from qc_tool.raster.inspire import run_check
325-
self.params.update({"layers": ["layer_missing"]})
326-
status = self.status_class()
327-
run_check(self.params, status)
328-
self.assertEqual("failed", status.status, "INSPIRE raster check should fail for raster with missing xml file.")
329-
330-
def test_fail(self):
331-
from qc_tool.raster.inspire import run_check
332-
self.params.update({"layers": ["layer_bad"]})
333-
self.params["skip_inspire_check"] = False
334-
status = self.status_class()
335-
run_check(self.params, status)
336-
self.assertEqual("failed", status.status, "INSPIRE raster check should fail for raster with non-compliant xml file.")
337-
338-
339301
class Test_color(RasterCheckTestCase):
340302
def setUp(self):
341303
super().setUp()

src/qc_tool/test/test_raster_product.py

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,138 +21,173 @@ def show_messages(self, job_result):
2121

2222
def setUp(self):
2323
super().setUp()
24-
2524
self.maxDiff = None
2625
self.raster_data_dir = TEST_DATA_DIR.joinpath("raster")
2726
self.username = "test_username"
2827

29-
# All steps are expected to finish with ok status by default.
30-
self.expected_step_statuses = ["ok"] * 13
31-
32-
# High resolution forest type (FTY) - 10m
3328
def test_fty_2018_010m(self):
29+
"""High resolution forest type (FTY) - 10m"""
3430
product_ident = "fty_2018_010m"
3531
filepath = self.raster_data_dir.joinpath("fty_010m", "FTY_2018_010m_eu_03035_clip.zip")
32+
33+
expected_step_results = ["ok"] * 15
3634
# fty_010m has extra checks raster.tile and raster.mmu
37-
self.expected_step_statuses = ["ok"] * 15
38-
self.expected_step_statuses[12] = "failed"
35+
expected_step_results[12] = "failed"
36+
expected_step_results[14] = "cancelled"
37+
3938
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
4039
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
41-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
40+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
4241

43-
# High resolution forest type (FTY) - 100m
4442
def test_fty_2018_100m(self):
43+
"""High resolution forest type (FTY) - 100m"""
4544
product_ident = "fty_2018_100m"
4645
filepath = self.raster_data_dir.joinpath("fty_100m", "fty_2018_100m_eu_03035_d02_clip.zip")
46+
47+
expected_step_results = ["ok"] * 13
48+
expected_step_results[12] = "cancelled"
49+
4750
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
4851
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
49-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
52+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
5053

51-
# High resolution grassland (GRA) - 10m
5254
def test_gra_2018_010m(self):
55+
"""High resolution grassland (GRA) - 10m"""
5356
product_ident = "gra_2018_010m"
5457
filepath = self.raster_data_dir.joinpath("gra_010m", "GRA_2018_010m_eu_03035_V1_clip.zip")
5558

59+
expected_step_results = ["ok"] * 13
5660
# gra_010m has mismatching attributes and color table
57-
self.expected_step_statuses[3] = "failed"
58-
self.expected_step_statuses[10] = "failed"
61+
expected_step_results[3] = "failed"
62+
expected_step_results[10] = "failed"
63+
expected_step_results[12] = "cancelled"
64+
5965
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
6066
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
61-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
67+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
6268

63-
# High resolution grassland (GRA) - 100m
6469
def test_gra_2018_100m(self):
70+
"""High resolution grassland (GRA) - 100m"""
6571
product_ident = "gra_2018_100m"
6672
filepath = self.raster_data_dir.joinpath("gra_100m", "GRA_2018_100m_eu_03035_V1_clip.zip")
73+
74+
expected_step_results = ["ok"] * 13
6775
# gra_2018_100m has mismatching attributes and color table
68-
self.expected_step_statuses[3] = "failed"
69-
self.expected_step_statuses[10] = "failed"
76+
expected_step_results[3] = "failed"
77+
expected_step_results[10] = "failed"
78+
expected_step_results[12] = "cancelled"
79+
7080
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
7181
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
72-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
82+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
7383

74-
# High resolution imperviousness change (IMC) - 20m
7584
def test_imc_1518_020m(self):
85+
"""High resolution imperviousness change (IMC) - 20m"""
7686
product_ident = "imc_1518_020m"
7787
filepath = self.raster_data_dir.joinpath("imc_020m", "IMC_1518_020m_eu_03035_d02_clip.zip")
7888

89+
expected_step_results = ["ok"] * 13
7990
# imc_1518_020m has mismatching attributes and color table
80-
self.expected_step_statuses[3] = "failed"
81-
self.expected_step_statuses[10] = "failed"
91+
expected_step_results[3] = "failed"
92+
expected_step_results[10] = "failed"
93+
expected_step_results[12] = "cancelled"
94+
8295
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
8396
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
84-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
97+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
8598

86-
# High resolution imperviousness change (IMC) - 100m
8799
def test_imc_1518_100m(self):
100+
"""High resolution imperviousness change (IMC) - 100m"""
88101
product_ident = "imc_1518_100m"
89102
filepath = self.raster_data_dir.joinpath("imc_100m", "IMC_1518_100m_eu_03035_d02_clip.zip")
90103

104+
expected_step_results = ["ok"] * 13
91105
# imc_1518_020m has mismatching attributes, values and color table
92-
self.expected_step_statuses[3] = "failed"
93-
self.expected_step_statuses[9] = "failed"
94-
self.expected_step_statuses[10] = "failed"
106+
expected_step_results[3] = "failed"
107+
expected_step_results[9] = "failed"
108+
expected_step_results[10] = "failed"
109+
expected_step_results[12] = "cancelled"
110+
95111
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
96112
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
97-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
113+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
98114

99-
# High resolution imperviousness density (IMD) - 10m
100115
def test_imd_2018_010m(self):
116+
"""High resolution imperviousness density (IMD) - 10m"""
101117
product_ident = "imd_2018_010m"
102118
filepath = self.raster_data_dir.joinpath("imd_010m", "IMD_2018_010m_eu_03035_d04_clip.zip")
103119

120+
expected_step_results = ["ok"] * 13
104121
# imd_2018_010m has mismatching attributes
105-
self.expected_step_statuses[3] = "failed"
122+
expected_step_results[3] = "failed"
123+
expected_step_results[12] = "cancelled"
124+
106125
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
107126
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
108-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
127+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
109128

110-
# High resolution imperviousness density (IMD) - 100m
111129
def test_imd_2018_100m(self):
130+
"""High resolution imperviousness density (IMD) - 100m"""
112131
product_ident = "imd_2018_100m"
113132
filepath = self.raster_data_dir.joinpath("imd_100m", "IMD_2018_100m_eu_03035_d02_clip.zip")
114133

134+
expected_step_results = ["ok"] * 13
115135
# imd_2018_100m has mismatching attributes
116-
self.expected_step_statuses[3] = "failed"
136+
expected_step_results[3] = "failed"
137+
expected_step_results[12] = "cancelled"
138+
117139
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
118140
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
119-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
141+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
120142

121-
# High resolution tree cover density (TCD) - 10m
122143
def test_tcd_2018_010m(self):
144+
"""High resolution tree cover density (TCD) - 10m"""
123145
product_ident = "tcd_2018_010m"
146+
filepath = self.raster_data_dir.joinpath("tcd_010m", "TCD_2018_010m_eu_03035_d04_clip.zip")
124147

148+
expected_step_results = ["ok"] * 13
125149
# tcd_2018_010m has mismatching colors
126-
self.expected_step_statuses[10] = "failed"
127-
filepath = self.raster_data_dir.joinpath("tcd_010m", "TCD_2018_010m_eu_03035_d04_clip.zip")
150+
expected_step_results[10] = "failed"
151+
expected_step_results[12] = "cancelled"
152+
128153
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
129154
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
130-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
155+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
131156

132-
# High resolution tree cover density (TCD) - 100m
133157
def test_tcd_2018_100m(self):
158+
"""High resolution tree cover density (TCD) - 100m"""
134159
product_ident = "tcd_2018_100m"
135160
filepath = self.raster_data_dir.joinpath("tcd_100m", "TCD_2018_100m_eu_03035_d03_clip.zip")
136161

162+
expected_step_results = ["ok"] * 13
137163
# tcd_2018_010m has mismatching colors
138-
self.expected_step_statuses[10] = "failed"
164+
expected_step_results[10] = "failed"
165+
expected_step_results[12] = "cancelled"
166+
139167
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
140168
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
141-
self.assertListEqual(self.expected_step_statuses, step_statuses, self.show_messages(job_result))
169+
self.assertListEqual(expected_step_results, step_statuses, self.show_messages(job_result))
142170

143-
# High resolution small woody features - 5m raster + vector
144171
def test_swf_2015_100m(self):
172+
"""High resolution small woody features - 5m raster + vector"""
173+
product_ident = "swf_2015_100m"
145174
filepath = TEST_DATA_DIR.joinpath("raster", "swf_100m", "swf_2015_100m_eu_03035_v1_1.zip")
175+
146176
expected_step_results = ["ok"] * 11
147-
job_result = dispatch(self.job_uuid, "user_name", filepath, "swf_2015_100m")
177+
expected_step_results[10] = "cancelled"
178+
179+
job_result = dispatch(self.job_uuid, "user_name", filepath, product_ident)
148180
step_results = [step_result["status"] for step_result in job_result["steps"]]
149181
self.assertListEqual(expected_step_results, step_results)
150182

151-
# General raster product
152183
def test_general_raster(self):
184+
"""General raster product"""
153185
product_ident = "general_raster"
154186
filepath = self.raster_data_dir.joinpath("general_raster", "general_raster.zip")
155-
expected_step_statuses = ["ok"] * 9
187+
188+
expected_step_results = ["ok"] * 9
189+
expected_step_results[8] = "cancelled"
190+
156191
job_result = dispatch(self.job_uuid, self.username, filepath, product_ident)
157192
step_statuses = [step_result["status"] for step_result in job_result["steps"]]
158-
self.assertListEqual(expected_step_statuses, step_statuses)
193+
self.assertListEqual(expected_step_results, step_statuses)

src/qc_tool/test/test_vector_check.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,36 +1711,3 @@ def test_warning(self):
17111711
# We expect ok status and one warning message.
17121712
self.assertEqual("ok", status.status)
17131713
self.assertEqual(1, len(status.messages))
1714-
1715-
1716-
@skipIf(CONFIG["skip_inspire_check"], "INSPIRE check has been disabled.")
1717-
class Test_inspire(VectorCheckTestCase):
1718-
def setUp(self):
1719-
super().setUp()
1720-
self.xml_dir = TEST_DATA_DIR.joinpath("metadata")
1721-
self.params["tmp_dir"] = self.params["jobdir_manager"].tmp_dir
1722-
self.params["output_dir"] = self.params["jobdir_manager"].output_dir
1723-
self.params["layers"] = ["layer0"]
1724-
1725-
1726-
def test(self):
1727-
from qc_tool.vector.inspire import run_check
1728-
self.params["layer_defs"] = {"layer0": {"src_filepath": self.xml_dir.joinpath("inspire-good.shp")}}
1729-
status = self.status_class()
1730-
run_check(self.params, status)
1731-
self.assertEqual("ok", status.status)
1732-
1733-
def test_missing_xml_fail(self):
1734-
from qc_tool.vector.inspire import run_check
1735-
self.params["layer_defs"] = {"layer0": {"src_filepath": self.xml_dir.joinpath("inspire-missing-metadata.gdb")}}
1736-
status = self.status_class()
1737-
run_check(self.params, status)
1738-
self.assertEqual("failed", status.status)
1739-
1740-
def test_fail(self):
1741-
from qc_tool.vector.inspire import run_check
1742-
self.params["layer_defs"] = {"layer0": {"src_filepath": self.xml_dir.joinpath("inspire-bad.shp")}}
1743-
status = self.status_class()
1744-
run_check(self.params, status)
1745-
self.assertEqual("failed", status.status)
1746-
self.assertIn("inspire-bad_metadata_error.json", status.attachment_filenames)

0 commit comments

Comments
 (0)