Skip to content

Commit 233df6f

Browse files
committed
validate /collections endpoint
1 parent 5ff4944 commit 233df6f

File tree

5 files changed

+119
-3
lines changed

5 files changed

+119
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ Options:
106106
-m, --max-depth INTEGER Maximum depth to traverse when recursing. Omit this
107107
argument to get full recursion. Ignored if
108108
`recursive == False`.
109+
--collections Validate /collections response.
109110
--item-collection Validate item collection response. Can be combined
110111
with --pages. Defaults to one page.
111112
-p, --pages INTEGER Maximum number of pages to validate via --item-

stac_validator/stac_validator.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,25 @@ def item_collection_summary(message: List[Dict[str, Any]]) -> None:
4646
click.secho(f"valid_items: {valid_count}")
4747

4848

49+
def collections_summary(message: List[Dict[str, Any]]) -> None:
50+
"""Prints a summary of the validation results for an item collection response.
51+
52+
Args:
53+
message (List[Dict[str, Any]]): The validation results for the item collection.
54+
55+
Returns:
56+
None
57+
"""
58+
valid_count = 0
59+
for collection in message:
60+
if "valid_stac" in collection and collection["valid_stac"] is True:
61+
valid_count = valid_count + 1
62+
click.secho()
63+
click.secho("--collections summary", bold=True)
64+
click.secho(f"collections_validated: {len(message)}")
65+
click.secho(f"valid_collections: {valid_count}")
66+
67+
4968
@click.command()
5069
@click.argument("stac_file")
5170
@click.option(
@@ -80,6 +99,11 @@ def item_collection_summary(message: List[Dict[str, Any]]) -> None:
8099
type=int,
81100
help="Maximum depth to traverse when recursing. Omit this argument to get full recursion. Ignored if `recursive == False`.",
82101
)
102+
@click.option(
103+
"--collections",
104+
is_flag=True,
105+
help="Validate /collections response.",
106+
)
83107
@click.option(
84108
"--item-collection",
85109
is_flag=True,
@@ -102,6 +126,7 @@ def item_collection_summary(message: List[Dict[str, Any]]) -> None:
102126
)
103127
def main(
104128
stac_file: str,
129+
collections: bool,
105130
item_collection: bool,
106131
pages: int,
107132
recursive: bool,
@@ -120,6 +145,7 @@ def main(
120145
121146
Args:
122147
stac_file (str): Path to the STAC file to be validated.
148+
collections (bool): Validate response from /collections endpoint.
123149
item_collection (bool): Whether to validate item collection responses.
124150
pages (int): Maximum number of pages to validate via `item_collection`.
125151
recursive (bool): Whether to recursively validate all related STAC objects.
@@ -143,6 +169,7 @@ def main(
143169
valid = True
144170
stac = StacValidate(
145171
stac_file=stac_file,
172+
collections=collections,
146173
item_collection=item_collection,
147174
pages=pages,
148175
recursive=recursive,
@@ -155,8 +182,10 @@ def main(
155182
verbose=verbose,
156183
log=log_file,
157184
)
158-
if not item_collection:
185+
if not item_collection and not collections:
159186
valid = stac.run()
187+
elif collections:
188+
stac.validate_collections()
160189
else:
161190
stac.validate_item_collection()
162191

@@ -169,6 +198,8 @@ def main(
169198

170199
if item_collection:
171200
item_collection_summary(message)
201+
elif collections:
202+
collections_summary(message)
172203

173204
sys.exit(0 if valid else 1)
174205

stac_validator/validate.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class StacValidate:
2525
2626
Attributes:
2727
stac_file (str): The path or URL to the STAC object to be validated.
28+
collections (bool): Validate response from a /collections endpoint.
2829
item_collection (bool): Whether the STAC object to be validated is an item collection.
2930
pages (int): The maximum number of pages to validate if `item_collection` is True.
3031
recursive (bool): Whether to recursively validate related STAC objects.
@@ -45,6 +46,7 @@ class StacValidate:
4546
def __init__(
4647
self,
4748
stac_file: Optional[str] = None,
49+
collections: bool = False,
4850
item_collection: bool = False,
4951
pages: Optional[int] = None,
5052
recursive: bool = False,
@@ -58,6 +60,7 @@ def __init__(
5860
log: str = "",
5961
):
6062
self.stac_file = stac_file
63+
self.collections = collections
6164
self.item_collection = item_collection
6265
self.pages = pages
6366
self.message: List = []
@@ -392,6 +395,27 @@ def validate_item_collection_dict(self, item_collection: Dict) -> None:
392395
self.schema = ""
393396
self.validate_dict(item)
394397

398+
def validate_collections(self) -> None:
399+
""" "Validate STAC collections from a /collections endpoint.
400+
401+
Raises:
402+
URLError: If there is an issue with the URL used to fetch the item collection.
403+
JSONDecodeError: If the item collection content cannot be parsed as JSON.
404+
ValueError: If the item collection does not conform to the STAC specification.
405+
TypeError: If the item collection content is not a dictionary or JSON object.
406+
FileNotFoundError: If the item collection file cannot be found.
407+
ConnectionError: If there is an issue with the internet connection used to fetch the item collection.
408+
exceptions.SSLError: If there is an issue with the SSL connection used to fetch the item collection.
409+
OSError: If there is an issue with the file system (e.g., read/write permissions) while trying to write to the log file.
410+
411+
Returns:
412+
None
413+
"""
414+
collections = fetch_and_parse_file(str(self.stac_file))
415+
for collection in collections["collections"]:
416+
self.schema = ""
417+
self.validate_dict(collection)
418+
395419
def validate_item_collection(self) -> None:
396420
"""Validate a STAC item collection.
397421
@@ -457,7 +481,11 @@ def run(self) -> bool:
457481
"""
458482
message = {}
459483
try:
460-
if self.stac_file is not None and not self.item_collection:
484+
if (
485+
self.stac_file is not None
486+
and not self.item_collection
487+
and not self.collections
488+
):
461489
self.stac_content = fetch_and_parse_file(self.stac_file)
462490

463491
stac_type = get_stac_type(self.stac_content).upper()

tests/test_validate_collections.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Description: Test stac-validator on --collections (/collections validation).
3+
4+
"""
5+
6+
7+
from stac_validator import stac_validator
8+
9+
10+
def test_validate_collections_remote():
11+
stac_file = "https://earth-search.aws.element84.com/v0/collections"
12+
stac = stac_validator.StacValidate(stac_file, collections=True)
13+
stac.validate_collections()
14+
15+
assert stac.message == [
16+
{
17+
"version": "1.0.0-beta.2",
18+
"path": "https://earth-search.aws.element84.com/v0/collections",
19+
"schema": [
20+
"https://schemas.stacspec.org/v1.0.0-beta.2/collection-spec/json-schema/collection.json"
21+
],
22+
"valid_stac": True,
23+
"asset_type": "COLLECTION",
24+
"validation_method": "default",
25+
},
26+
{
27+
"version": "1.0.0-beta.2",
28+
"path": "https://earth-search.aws.element84.com/v0/collections",
29+
"schema": [
30+
"https://schemas.stacspec.org/v1.0.0-beta.2/collection-spec/json-schema/collection.json"
31+
],
32+
"valid_stac": True,
33+
"asset_type": "COLLECTION",
34+
"validation_method": "default",
35+
},
36+
{
37+
"version": "1.0.0-beta.2",
38+
"path": "https://earth-search.aws.element84.com/v0/collections",
39+
"schema": [
40+
"https://schemas.stacspec.org/v1.0.0-beta.2/collection-spec/json-schema/collection.json"
41+
],
42+
"valid_stac": True,
43+
"asset_type": "COLLECTION",
44+
"validation_method": "default",
45+
},
46+
{
47+
"version": "1.0.0-beta.2",
48+
"path": "https://earth-search.aws.element84.com/v0/collections",
49+
"schema": [
50+
"https://schemas.stacspec.org/v1.0.0-beta.2/collection-spec/json-schema/collection.json"
51+
],
52+
"valid_stac": True,
53+
"asset_type": "COLLECTION",
54+
"validation_method": "default",
55+
},
56+
]

tests/test_validate_item_collection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Description: Test the validator
2+
Description: Test stac-validator on item-collection validation.
33
44
"""
55

0 commit comments

Comments
 (0)