Skip to content

Commit 2bc527c

Browse files
authored
Merge pull request #26 from sparkgeo/dev
Fixes broken geojson resolver for child items
2 parents 6b87c39 + e81c01d commit 2bc527c

File tree

3 files changed

+125
-17
lines changed

3 files changed

+125
-17
lines changed

stac_validator.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def __init__(self, stac_file, version="master"):
6868

6969
self.stac_version = version
7070
self.stac_file = stac_file.strip()
71-
self.dirpath = ""
71+
self.dirpath = ''
7272
self.fetch_specs(self.stac_version)
7373
self.fpath = Path(stac_file)
7474
self.message = {}
@@ -89,6 +89,9 @@ def fetch_specs(self, version):
8989
catalog_key = "catalog-{}".format(self.stac_version)
9090

9191
if item_key in cache and catalog_key in cache:
92+
self.geojson_resolver = RefResolver(
93+
base_uri="file://{}/".format(self.dirpath), referrer="geojson.json"
94+
)
9295
return cache[item_key], cache[geojson_key], cache[catalog_key]
9396

9497
# need to make a temp local file for geojson.
@@ -140,19 +143,21 @@ def validate_stac(self, stac_file, schema):
140143
# See https://github.com/Julian/jsonschema/issues/313
141144
# See https://github.com/Julian/jsonschema/issues/98
142145
try:
143-
geojson_resolver = cache["geojson_resolver"]
146+
self.geojson_resolver = RefResolver(
147+
base_uri="file://{}/".format(cache["geojson_resolver"]), referrer="geojson.json"
148+
)
144149
validate(stac_file, stac_schema, resolver=self.geojson_resolver)
145150
self.message["valid_stac"] = True
146151
except Exception as error:
147152
self.message["valid_stac"] = False
148-
self.message["error"] = f"{error.args}"
153+
self.message["error_message"] = f"{error.args}"
149154
except ValidationError as error:
150155
self.message["valid_stac"] = False
151-
self.message["error"] = f"{error.message} of {list(error.path)}"
156+
self.message["error_message"] = f"{error.message} of {list(error.path)}"
152157

153158
except Exception as error:
154159
self.message["valid_stac"] = False
155-
self.message["error"] = f"{error}"
160+
self.message["error_message"] = f"{error}"
156161

157162
async def _validate_child(self, child_url, messages):
158163
stac = StacValidate(child_url.replace("///", "//"), self.stac_version)
@@ -161,8 +166,7 @@ async def _validate_child(self, child_url, messages):
161166
messages.append(stac.message)
162167

163168
if "error_type" in stac.message:
164-
stac.message.pop("error_type", None)
165-
stac.status.pop("error_type", None)
169+
pass
166170
else:
167171
self.status["catalogs"]["valid"] += stac.status["catalogs"]["valid"]
168172
self.status["catalogs"]["invalid"] += stac.status["catalogs"]["invalid"]
@@ -221,13 +225,13 @@ async def run(self):
221225
except JSONDecodeError as e:
222226
self.message["valid_stac"] = False
223227
self.message["error_type"] = "InvalidJSON"
224-
self.message["error"] = f"{self.stac_file} is not Valid JSON"
228+
self.message["error_message"] = f"{self.stac_file} is not Valid JSON"
225229
self.status = self.message
226230
# return json.dumps(self.message)
227231
except FileNotFoundError as e:
228232
self.message["valid_stac"] = False
229233
self.message["error_type"] = "FileNotFoundError"
230-
self.message["error"] = f"{self.stac_file} cannot be found"
234+
self.message["error_message"] = f"{self.stac_file} cannot be found"
231235
self.status = self.message
232236

233237
# Check STAC Type
@@ -243,7 +247,7 @@ async def run(self):
243247
else:
244248
self.status["catalogs"]["invalid"] += 1
245249
self.message["children"] = await self.validate_catalog_contents()
246-
elif (self.stac_file) is dict and (
250+
elif type(self.stac_file) is dict and any(
247251
field in Collections_Fields for field in self.stac_file.keys()
248252
):
249253
# Congratulations, It's a Collection!
@@ -259,8 +263,7 @@ async def run(self):
259263
self.status["collections"]["invalid"] += 1
260264
self.message["children"] = await self.validate_catalog_contents()
261265
elif "error_type" in self.message:
262-
self.message.pop("error_type", None)
263-
self.status.pop("error_type", None)
266+
pass
264267

265268
else:
266269
# Congratulations, It's an Item!
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"type": "Feature",
3+
"id" : "CS3-20160503_132131_05",
4+
"bbox": [-122.59750209, 37.48803556, -122.2880486, 37.613537207],
5+
"geometry": {
6+
"type": "Polygon",
7+
"coordinates": [
8+
[
9+
[-122.308150179, 37.488035566],
10+
[-122.597502109, 37.538869539],
11+
[-122.576687533, 37.613537207],
12+
[-122.288048600, 37.562818007],
13+
[-122.308150179, 37.488035566]
14+
]
15+
]
16+
},
17+
"properties": {
18+
"datetime": "2016-05-03T13:22:30.040Z",
19+
"eo:sun_azimuth": 168.7,
20+
"eo:cloud_cover": 0.12,
21+
"eo:off_nadir": 1.4,
22+
"eo:platform": "COOLSAT2",
23+
"eo:sun_elevation": 33.4,
24+
"eo:gsd": 0.512,
25+
"cs:type": "scene",
26+
"cs:anomalous_pixels": 0.14,
27+
"cs:earth_sun_distance": 1.0141560,
28+
"cs:sat_id": "CS3",
29+
"cs:product_level": "LV1B"
30+
},
31+
"links": [
32+
{"rel": "self", "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.json"},
33+
{"rel": "thumbnail", "href":"thumbnail.png"},
34+
{"rel": "root", "href": "http://cool-sat.com/catalog/catalog.json"},
35+
{"rel": "parent", "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/catalog.json"},
36+
{"rel": "collection", "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/catalog.json"},
37+
{"rel": "acquisition", "href": "http://cool-sat.com/catalog/acquisitions/20160503_56"}
38+
],
39+
"assets": {
40+
"analytic": {
41+
"href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/analytic.tif",
42+
"title": "4-Band Analytic",
43+
"product": "http://cool-sat.com/catalog/products/analytic.json"
44+
},
45+
"thumbnail": {
46+
"href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/thumbnail.png",
47+
"title": "Thumbnail"
48+
},
49+
"udm": {
50+
"href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/UDM.tif",
51+
"title": "Unusable Data Mask",
52+
"product": "http://cool-sat.com/catalog/products/udm.json"
53+
},
54+
"json-metadata": {
55+
"href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/extended-metadata.json",
56+
"title": "Extended Metadata",
57+
"product": "http://cool-sat.com/catalog/products/extended-metadata.json"
58+
},
59+
"ephemeris": {
60+
"href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/S3-20160503_132130_04.EPH",
61+
"title": "Satellite Ephemeris Metadata",
62+
"product": "http://cool-sat.com/catalog/products/satellite-ephemeris.json"
63+
}
64+
}
65+
66+
}

tests/test_stac_validator.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
__author__ = "James Banting"
66
import stac_validator
77
import trio
8-
import json
8+
import pytest
99

1010

1111
def _run_validate(url, version="master"):
@@ -41,6 +41,7 @@ def test_good_catalog_validation_v052():
4141
"children": [],
4242
}
4343

44+
4445
# Need to fix test around async return - output is valid, but dict is out of order
4546
# def test_nested_catalog_v052():
4647
# stac = _run_validate(
@@ -138,11 +139,49 @@ def test_bad_url():
138139
)
139140
assert stac.status == {
140141
"valid_stac": False,
141-
"error": "https://s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud is not Valid JSON",
142-
"path": "https:/s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud"
142+
"error_type": "InvalidJSON",
143+
"error_message": "https://s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud is not Valid JSON",
144+
"path": "https:/s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud",
143145
}
144146
assert stac.message == {
145147
"valid_stac": False,
146-
"error": "https://s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud is not Valid JSON",
147-
"path": "https:/s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud"
148+
"error_type": "InvalidJSON",
149+
"error_message": "https://s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud is not Valid JSON",
150+
"path": "https:/s3.amazonaws.com/spacenet-stac/spacenet-dataset/AOI_4_Shanghai_MUL-PanSharpen_Cloud",
151+
}
152+
153+
154+
@pytest.mark.stac_spec
155+
def test_catalog_master():
156+
stac = _run_validate(
157+
"https://raw.githubusercontent.com/radiantearth/stac-spec/master/catalog-spec/examples/catalog.json"
158+
)
159+
assert stac.status == {
160+
"catalogs": {"valid": 1, "invalid": 0},
161+
"collections": {"valid": 0, "invalid": 0},
162+
"items": {"valid": 0, "invalid": 0},
163+
}
164+
165+
@pytest.mark.stac_spec
166+
def test_collection_master():
167+
stac = _run_validate(
168+
"https://raw.githubusercontent.com/radiantearth/stac-spec/master/collection-spec/examples/sentinel2.json"
169+
)
170+
assert stac.status == {
171+
"catalogs": {"valid": 0, "invalid": 0},
172+
"collections": {"valid": 1, "invalid": 0},
173+
"items": {"valid": 0, "invalid": 0},
174+
}
175+
176+
@pytest.mark.item_spec
177+
@pytest.mark.stac_spec
178+
def test_item_master():
179+
stac = _run_validate(
180+
"https://raw.githubusercontent.com/radiantearth/stac-spec/master/item-spec/examples/sample-full.json"
181+
)
182+
assert stac.status == {
183+
"catalogs": {"valid": 0, "invalid": 0},
184+
"collections": {"valid": 0, "invalid": 0},
185+
"items": {"valid": 1, "invalid": 0},
148186
}
187+

0 commit comments

Comments
 (0)