Skip to content

Commit

Permalink
add sort for item-search (#330)
Browse files Browse the repository at this point in the history
* add sort for item-search

* rename sorted datetimes
  • Loading branch information
philvarner authored Apr 23, 2023
1 parent 004ee97 commit 1cc4804
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add parameter set `--validate-pagination/--no-validate-pagination` to conditionally run the pagination tests, which may take a while to run.
- Added support for Query Extension validation of Item Search
- Added support for Transaction Extension validation
- Added support for Sort Extension validation of Item Search

## [0.5.0] - 2023-02-21

Expand Down
1 change: 1 addition & 0 deletions COMPLIANCE_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ poetry run stac-api-validator --root-url https://earth-search.aws.element84.com/
--conformance item-search \
--conformance item-search#fields \
--conformance item-search#query \
--conformance item-search#sort \
--collection sentinel-2-l2a \
--fields-nested-property properties.eo:cloud_cover \
--geometry '{"type": "Polygon", "coordinates": [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]]}' \
Expand Down
131 changes: 130 additions & 1 deletion src/stac_api_validator/validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,15 @@ def validate_api(

if "item-search#sort" in ccs_to_validate:
logger.info("STAC API - Item Search - Sort extension conformance class found.")
logger.info("STAC API - Item Search - Sort extension is not yet supported.")
validate_sort(
context=Context.ITEM_SEARCH_SORT,
landing_page_body=landing_page_body,
collection=collection,
errors=errors,
warnings=warnings,
r_session=r_session,
query_config=query_config,
)

if "item-search#query" in ccs_to_validate:
logger.info("STAC API - Item Search - Query extension conformance class found.")
Expand Down Expand Up @@ -3532,3 +3540,124 @@ def validate_transaction(
context=context,
r_session=r_session,
)


def validate_sort(
landing_page_body: Dict[str, Any],
collection: str,
errors: Errors,
warnings: Warnings,
r_session: Session,
context: Context,
query_config: QueryConfig,
) -> None:
limit = 100

search_method_to_url: dict[Method, str] = {
Method[x.get("method", "GET")]: x.get("href")
for x in links_by_rel(landing_page_body.get("links"), "search")
}

# ascending
if Method.GET in search_method_to_url:
for sortby in ["properties.datetime", "+properties.datetime"]:
_, body, _ = retrieve(
Method.GET,
search_method_to_url[Method.GET],
params={
"sortby": sortby,
"limit": limit,
"collections": collection,
},
errors=errors,
context=context,
r_session=r_session,
)

if not len(body["features"]):
errors += (
f"[{context}] : GET search with Sort '{sortby}' had no results"
)

datetimes = [f["properties"]["datetime"] for f in body["features"]]
sorted_datetimes = copy.deepcopy(datetimes)
sorted_datetimes.sort()

if datetimes != sorted_datetimes:
errors += f"[{context}] : GET search with Sort '{sortby}' was not sorted in ascending order {datetimes} {sorted_datetimes}"

if Method.POST in search_method_to_url:
sortby_json = [{"field": "properties.datetime", "direction": "asc"}]
retrieve(
Method.POST,
search_method_to_url[Method.POST],
body={
"sortby": sortby_json,
"limit": limit,
"collections": collection,
},
errors=errors,
context=context,
r_session=r_session,
)

if not len(body["features"]):
errors += f"[{context}] : POST search with Sort '{json.dumps(sortby_json)}' had no results"

datetimes = [f["properties"]["datetime"] for f in body["features"]]
sorted_datetimes = copy.deepcopy(datetimes)
sorted_datetimes.sort()

if datetimes != sorted_datetimes:
errors += f"[{context}] : POST search with Sort '{json.dumps(sortby_json)}' was not sorted in ascending order"

# descending
if Method.GET in search_method_to_url:
sortby = "-properties.datetime"
_, body, _ = retrieve(
Method.GET,
search_method_to_url[Method.GET],
params={
"sortby": sortby,
"limit": limit,
"collections": collection,
},
errors=errors,
context=context,
r_session=r_session,
)

if not len(body["features"]):
errors += f"[{context}] : GET search with Sort '{sortby}' had no results"

datetimes = [f["properties"]["datetime"] for f in body["features"]]
sorted_datetimes = copy.deepcopy(datetimes)
sorted_datetimes.sort(reverse=True)

if datetimes != sorted_datetimes:
errors += f"[{context}] : GET search with Sort '{sortby}' was not sorted in descending order {datetimes} {sorted_datetimes}"

if Method.POST in search_method_to_url:
sortby_json = [{"field": "properties.datetime", "direction": "desc"}]
retrieve(
Method.POST,
search_method_to_url[Method.POST],
body={
"sortby": sortby_json,
"limit": limit,
"collections": collection,
},
errors=errors,
context=context,
r_session=r_session,
)

if not len(body["features"]):
errors += f"[{context}] : POST search with Sort '{json.dumps(sortby_json)}' had no results"

datetimes = [f["properties"]["datetime"] for f in body["features"]]
sorted_datetimes = copy.deepcopy(datetimes)
sorted_datetimes.sort(reverse=True)

if datetimes != sorted_datetimes:
errors += f"[{context}] : POST search with Sort '{json.dumps(sortby_json)}' was not sorted in descending order"

0 comments on commit 1cc4804

Please sign in to comment.