Skip to content

Commit 627ab00

Browse files
authored
feat: implement sortby for /items (#28)
This MR implements support for the sortby parameter on the /items endpoint. The sortby parameter was previously only available on /search and the legacy implementation. This change brings consistency across endpoints by enabling sorting on /items as well.
1 parent 701c9e6 commit 627ab00

3 files changed

Lines changed: 44 additions & 1 deletion

File tree

stac_fastapi/eodag/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
157157
item_collection_model = create_request_model(
158158
"ItemsRequest",
159159
base_model=ItemCollectionUri,
160-
extensions=[e for e in extensions if isinstance(e, PaginationExtension)],
160+
extensions=[e for e in extensions if isinstance(e, PaginationExtension) or isinstance(e, SortExtension)],
161161
request_type="GET",
162162
)
163163

stac_fastapi/eodag/core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ async def item_collection(
323323
datetime: Optional[Union[str, datetime]] = None,
324324
limit: Optional[int] = None,
325325
page: Optional[str] = None,
326+
sortby: Optional[list[str]] = None,
326327
**kwargs: Any,
327328
) -> ItemCollection:
328329
"""
@@ -351,6 +352,10 @@ async def item_collection(
351352
"page": page,
352353
}
353354

355+
if sortby:
356+
sortby_converted = get_sortby_to_post(sortby)
357+
base_args["sortby"] = cast(Any, sortby_converted)
358+
354359
clean = {}
355360
for k, v in base_args.items():
356361
if v is not None and v != []:

tests/test_search.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,44 @@ async def test_date_search_from_items(request_valid, defaults, use_dates):
219219
)
220220

221221

222+
@pytest.mark.parametrize(
223+
"sortby,expected_sort_by",
224+
[
225+
("-datetime", [("startTimeFromAscendingNode", "desc")]),
226+
("datetime", [("startTimeFromAscendingNode", "asc")]),
227+
("-start", [("startTimeFromAscendingNode", "desc")]),
228+
("start", [("startTimeFromAscendingNode", "asc")]),
229+
("-end", [("completionTimeFromAscendingNode", "desc")]),
230+
("end", [("completionTimeFromAscendingNode", "asc")]),
231+
],
232+
)
233+
async def test_sortby_items_parametrize(request_valid, defaults, sortby, expected_sort_by):
234+
"""Test sortby param with various values."""
235+
await request_valid(
236+
f"collections/{defaults.product_type}/items?sortby={sortby}",
237+
expected_search_kwargs={
238+
"productType": defaults.product_type,
239+
"sort_by": expected_sort_by,
240+
"page": 1,
241+
"items_per_page": 10,
242+
"raise_errors": False,
243+
"count": True,
244+
},
245+
check_links=False,
246+
)
247+
248+
249+
async def test_sortby_invalid_field_returns_400(app_client, defaults):
250+
"""Test sortby with an invalid field returns a 400 error and expected error structure."""
251+
sortby = "-unknownfield"
252+
response = await app_client.get(f"/collections/{defaults.product_type}/items?sortby={sortby}")
253+
assert response.status_code == 400
254+
resp_json = response.json()
255+
assert resp_json["code"] == "400"
256+
assert "ticket" in resp_json
257+
assert resp_json["description"] == "Something went wrong"
258+
259+
222260
async def test_search_item_id_from_collection(request_valid, defaults):
223261
"""Search by id through eodag server /collection endpoint should return a valid response"""
224262
await request_valid(

0 commit comments

Comments
 (0)