Skip to content

Commit cbe7e88

Browse files
committed
handle case where intersects returns no features
1 parent bf44c9f commit cbe7e88

File tree

2 files changed

+27
-21
lines changed

2 files changed

+27
-21
lines changed

src/stac_api_validator/__main__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Command-line interface."""
22
import logging
33
import sys
4+
import traceback
45
from typing import List
56
from typing import Optional
67

@@ -78,7 +79,10 @@ def main(
7879
auth_query_parameter=auth_query_parameter,
7980
)
8081
except Exception as e:
81-
click.secho(f"Failed.\nError {root_url}: {type(e)} {str(e)}", fg="red")
82+
click.secho(
83+
f"Failed.\nError {root_url}: {type(e)} {str(e)} {traceback.format_exc()}",
84+
fg="red",
85+
)
8286
return 1
8387

8488
if warnings:

src/stac_api_validator/validations.py

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,10 @@ def stac_check(
333333
errors += (
334334
f"[{context}] {method} {url} is not a valid STAC object: {linter.error_msg}"
335335
)
336-
if linter.best_practices_msg:
337-
warnings += f"[{context}] {method} {url} has these stac-check recommendations: {linter.best_practices_msg}"
336+
if msgs := linter.best_practices_msg[1:]: # first msg is a header
337+
warnings += (
338+
f"[{context}] {method} {url} has these stac-check recommendations: {msgs}"
339+
)
338340

339341

340342
def retrieve(
@@ -373,7 +375,9 @@ def retrieve(
373375
elif not has_content_type(resp.headers, content_type):
374376
errors += f"[{context}] {method} {url} params={params} body={body} content-type header is not '{content_type}'"
375377

376-
if resp.headers.get("content-type", "").split(";")[0].endswith("json"):
378+
if has_json_content_type(resp.headers) or has_geojson_content_type(
379+
resp.headers
380+
):
377381
try:
378382
return resp.status_code, resp.json(), resp.headers
379383
except json.decoder.JSONDecodeError:
@@ -391,7 +395,7 @@ def validate_core_landing_page_body(
391395
collection: Optional[str],
392396
geometry: Optional[str],
393397
) -> bool:
394-
if not has_content_type(headers, "application/json"):
398+
if not has_json_content_type(headers):
395399
errors += (
396400
"CORE-1",
397401
"[Core] : Landing Page (/) response Content-Type header is not application/json",
@@ -728,7 +732,7 @@ def validate_collections(
728732
if not body:
729733
errors += f"[{Context.COLLECTIONS}] /collections body was empty"
730734
else:
731-
if not resp_headers or not is_json_type(resp_headers.get("content-type")):
735+
if not resp_headers or not has_json_content_type(resp_headers):
732736
errors += f"[{Context.COLLECTIONS}] /collections content-type header was not application/json"
733737

734738
if not (self_link := link_by_rel(body.get("links", []), "self")):
@@ -766,11 +770,7 @@ def validate_collections(
766770
if not body:
767771
errors += f"[{Context.COLLECTIONS}] {collection_url} body was empty"
768772
else:
769-
if (
770-
not resp_headers
771-
or resp_headers.get("content-type", "").split(";")[0]
772-
!= "application/json"
773-
):
773+
if not resp_headers or not has_json_content_type(resp_headers):
774774
errors += f"[{Context.COLLECTIONS}] {collection_url} content-type header was not application/json"
775775

776776
if not (self_link := link_by_rel(body.get("links", []), "self")):
@@ -1749,13 +1749,14 @@ def validate_item_search_intersects(
17491749
)
17501750

17511751
if body:
1752-
if not len(body["features"]):
1752+
if not body.get("features"):
17531753
errors += f"[{Context.ITEM_SEARCH}] GET {search_url} Search result for intersects={geometry} returned no results"
1754-
if any(
1755-
not intersects_shape.intersects(shape(item["geometry"]))
1756-
for item in body["features"]
1757-
):
1758-
errors += f"[{Context.ITEM_SEARCH}] GET {search_url} Search results for intersects={geometry} do not all intersect"
1754+
else:
1755+
if any(
1756+
not intersects_shape.intersects(shape(item.get("geometry", None)))
1757+
for item in body.get("features", [])
1758+
):
1759+
errors += f"[{Context.ITEM_SEARCH}] GET {search_url} Search results for intersects={geometry} do not all intersect"
17591760

17601761
if Method.POST in methods:
17611762
_, item_collection, _ = retrieve(
@@ -1766,11 +1767,12 @@ def validate_item_search_intersects(
17661767
body={"collections": [collection], "intersects": geometry},
17671768
r_session=r_session,
17681769
)
1769-
if not (item_collection and len(item_collection["features"])):
1770+
if not item_collection or not item_collection.get("features"):
17701771
errors += f"[{Context.ITEM_SEARCH}] POST Search result for intersects={geometry} returned no results"
1771-
for item in item_collection["features"]: # type: ignore
1772-
if not intersects_shape.intersects(shape(item["geometry"])):
1773-
errors += f"[{Context.ITEM_SEARCH}] POST Search result for intersects={geometry}, does not intersect {item['geometry']}"
1772+
else:
1773+
for item in item_collection.get("features", []):
1774+
if not intersects_shape.intersects(shape(item.get("geometry"))):
1775+
errors += f"[{Context.ITEM_SEARCH}] POST Search result for intersects={geometry}, does not intersect {item.get('geometry')}"
17741776

17751777

17761778
def validate_item_search_bbox(

0 commit comments

Comments
 (0)