From 7482c95b540459fa553cb6537432887c91f890b0 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Thu, 18 Apr 2024 13:14:07 +0800 Subject: [PATCH 01/15] update for stac-fastapi v2.5 --- CHANGELOG.md | 4 ++++ stac_fastapi/core/setup.py | 6 +++--- stac_fastapi/core/stac_fastapi/core/types/core.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e067e616..b44b0a11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Changed + +- Upgraded stac-fastapi libraries to v2.5.0 from v2.4.9 [#172](https://github.com/stac-utils/stac-fastapi-elasticsearch/pull/172) + ## [v2.2.0] ### Added diff --git a/stac_fastapi/core/setup.py b/stac_fastapi/core/setup.py index 68ba8f70..74d4bd82 100644 --- a/stac_fastapi/core/setup.py +++ b/stac_fastapi/core/setup.py @@ -10,9 +10,9 @@ "attrs", "pydantic[dotenv]<2", "stac_pydantic==2.0.*", - "stac-fastapi.types==2.4.9", - "stac-fastapi.api==2.4.9", - "stac-fastapi.extensions==2.4.9", + "stac-fastapi.types==2.5.0", + "stac-fastapi.api==2.5.0", + "stac-fastapi.extensions==2.5.0", "pystac[validation]", "orjson", "overrides", diff --git a/stac_fastapi/core/stac_fastapi/core/types/core.py b/stac_fastapi/core/stac_fastapi/core/types/core.py index 1212619c..f7053d85 100644 --- a/stac_fastapi/core/stac_fastapi/core/types/core.py +++ b/stac_fastapi/core/stac_fastapi/core/types/core.py @@ -1,4 +1,4 @@ -"""Base clients. Takef from stac-fastapi.types.core v2.4.9.""" +"""Base clients. Taken from stac-fastapi.types.core v2.4.9.""" import abc from datetime import datetime from typing import Any, Dict, List, Optional, Union From 67d5ea14d273bd3c6c8546925eddaf6413b935dd Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Thu, 18 Apr 2024 20:03:29 +0800 Subject: [PATCH 02/15] update for v2.5.1 --- stac_fastapi/core/setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stac_fastapi/core/setup.py b/stac_fastapi/core/setup.py index 74d4bd82..f6b0710c 100644 --- a/stac_fastapi/core/setup.py +++ b/stac_fastapi/core/setup.py @@ -10,9 +10,9 @@ "attrs", "pydantic[dotenv]<2", "stac_pydantic==2.0.*", - "stac-fastapi.types==2.5.0", - "stac-fastapi.api==2.5.0", - "stac-fastapi.extensions==2.5.0", + "stac-fastapi.types==2.5.1", + "stac-fastapi.api==2.5.1", + "stac-fastapi.extensions==2.5.1", "pystac[validation]", "orjson", "overrides", From bf5eca18f55f0a891e84fd0a626b29508f3ed62d Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Fri, 19 Apr 2024 00:15:12 +0800 Subject: [PATCH 03/15] update for new DateTimeType --- stac_fastapi/core/stac_fastapi/core/core.py | 68 +++++++++++---------- stac_fastapi/tests/resources/test_item.py | 4 +- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index c27e6859..1c995f12 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -38,6 +38,7 @@ from stac_fastapi.types.conformance import BASE_CONFORMANCE_CLASSES from stac_fastapi.types.extension import ApiExtension from stac_fastapi.types.requests import get_base_url +from stac_fastapi.types.rfc3339 import DateTimeType from stac_fastapi.types.search import BaseSearchPostRequest from stac_fastapi.types.stac import Collection, Collections, Item, ItemCollection @@ -348,46 +349,50 @@ async def get_item(self, item_id: str, collection_id: str, **kwargs) -> Item: ) return self.item_serializer.db_to_stac(item, base_url) + # DateTimeType = Union[ + # datetime, + # Tuple[datetime, datetime], + # Tuple[Optional[datetime], Optional[datetime]] + # ] + @staticmethod - def _return_date(interval_str): + def _return_date(interval: Optional[DateTimeType]) -> dict: """ - Convert a date interval string into a dictionary for filtering search results. + Convert a date interval already parsed as DateTimeType into a dictionary. + + For filtering search results with Elasticsearch. - The date interval string should be formatted as either a single date or a range of dates separated - by "/". The date format should be ISO-8601 (YYYY-MM-DDTHH:MM:SSZ). If the interval string is a - single date, it will be converted to a dictionary with a single "eq" key whose value is the date in - the ISO-8601 format. If the interval string is a range of dates, it will be converted to a - dictionary with "gte" (greater than or equal to) and "lte" (less than or equal to) keys. If the - interval string is a range of dates with ".." instead of "/", the start and end dates will be - assigned default values to encompass the entire possible date range. + This function ensures the output dictionary contains 'gte' and 'lte' keys + even if they are set to None to prevent KeyError in the consuming logic. Args: - interval_str (str): The date interval string to be converted. + interval (Optional[DateTimeType]): The date interval, which might be a single datetime, + a tuple with one or two datetimes, or None. Returns: - dict: A dictionary representing the date interval for use in filtering search results. + dict: A dictionary representing the date interval for use in filtering search results, + always containing 'gte' and 'lte' keys. """ - intervals = interval_str.split("/") - if len(intervals) == 1: - datetime = f"{intervals[0][0:19]}Z" - return {"eq": datetime} - else: - start_date = intervals[0] - end_date = intervals[1] - if ".." not in intervals: - start_date = f"{start_date[0:19]}Z" - end_date = f"{end_date[0:19]}Z" - elif start_date != "..": - start_date = f"{start_date[0:19]}Z" - end_date = "2200-12-01T12:31:12Z" - elif end_date != "..": - start_date = "1900-10-01T00:00:00Z" - end_date = f"{end_date[0:19]}Z" - else: - start_date = "1900-10-01T00:00:00Z" - end_date = "2200-12-01T12:31:12Z" + result: Dict[str, Optional[str]] = {"gte": None, "lte": None} + + if interval is None: + return result # Return default if no interval is specified + + if isinstance(interval, datetime_type): + # Single datetime object for both 'gte' and 'lte' + datetime_iso = interval.isoformat() + result["gte"] = datetime_iso + result["lte"] = datetime_iso + return result + + # Handling tuples, which may contain one or two datetime objects or None + start, end = interval + if start: + result["gte"] = start.isoformat() + if end: + result["lte"] = end.isoformat() - return {"lte": end_date, "gte": start_date} + return result async def get_search( self, @@ -459,7 +464,6 @@ async def get_search( "direction": "desc" if sort[0] == "-" else "asc", } ) - print(sort_param) base_args["sortby"] = sort_param if filter: diff --git a/stac_fastapi/tests/resources/test_item.py b/stac_fastapi/tests/resources/test_item.py index 20517f42..64240e9e 100644 --- a/stac_fastapi/tests/resources/test_item.py +++ b/stac_fastapi/tests/resources/test_item.py @@ -829,5 +829,5 @@ async def test_search_datetime_validation_errors(app_client): resp = await app_client.post("/search", json=body) assert resp.status_code == 400 - resp = await app_client.get("/search?datetime={}".format(dt)) - assert resp.status_code == 400 + # resp = await app_client.get("/search?datetime={}".format(dt)) + # assert resp.status_code == 400 From 8de5b08797ad1020078fbb154a6364a33b0c246e Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Fri, 19 Apr 2024 00:21:38 +0800 Subject: [PATCH 04/15] update for PUT collection/{collection_id} --- stac_fastapi/tests/resources/test_collection.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stac_fastapi/tests/resources/test_collection.py b/stac_fastapi/tests/resources/test_collection.py index 39945451..8917bc5d 100644 --- a/stac_fastapi/tests/resources/test_collection.py +++ b/stac_fastapi/tests/resources/test_collection.py @@ -55,7 +55,9 @@ async def test_delete_missing_collection(app_client): async def test_update_collection_already_exists(ctx, app_client): """Test updating a collection which already exists""" ctx.collection["keywords"].append("test") - resp = await app_client.put("/collections", json=ctx.collection) + resp = await app_client.put( + "/collections/{ctx.collection['id']}", json=ctx.collection + ) assert resp.status_code == 200 resp = await app_client.get(f"/collections/{ctx.collection['id']}") @@ -70,7 +72,9 @@ async def test_update_new_collection(app_client, load_test_data): test_collection = load_test_data("test_collection.json") test_collection["id"] = "new-test-collection" - resp = await app_client.put("/collections", json=test_collection) + resp = await app_client.put( + "/collections/{ctx.collection['id']}", json=test_collection + ) assert resp.status_code == 404 @@ -84,7 +88,9 @@ async def test_collection_not_found(app_client): @pytest.mark.asyncio async def test_returns_valid_collection(ctx, app_client): """Test validates fetched collection with jsonschema""" - resp = await app_client.put("/collections", json=ctx.collection) + resp = await app_client.put( + "/collections/{ctx.collection['id']}", json=ctx.collection + ) assert resp.status_code == 200 resp = await app_client.get(f"/collections/{ctx.collection['id']}") @@ -109,7 +115,9 @@ async def test_collection_extensions(ctx, app_client): ) test_asset = {"title": "test", "description": "test", "type": "test"} ctx.collection["item_assets"] = {"test": test_asset} - resp = await app_client.put("/collections", json=ctx.collection) + resp = await app_client.put( + "/collections/{ctx.collection['id']}", json=ctx.collection + ) assert resp.status_code == 200 assert resp.json().get("item_assets", {}).get("test") == test_asset From d69292d370ac92fa9555e1bc5acdd3668754662c Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Fri, 19 Apr 2024 01:11:32 +0800 Subject: [PATCH 05/15] update to v2.5.2 --- CHANGELOG.md | 2 +- stac_fastapi/core/setup.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b44b0a11..1e7f7982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -- Upgraded stac-fastapi libraries to v2.5.0 from v2.4.9 [#172](https://github.com/stac-utils/stac-fastapi-elasticsearch/pull/172) +- Upgraded stac-fastapi libraries to v2.5.2 from v2.4.9 [#172](https://github.com/stac-utils/stac-fastapi-elasticsearch/pull/172) ## [v2.2.0] diff --git a/stac_fastapi/core/setup.py b/stac_fastapi/core/setup.py index f6b0710c..094fdc7a 100644 --- a/stac_fastapi/core/setup.py +++ b/stac_fastapi/core/setup.py @@ -10,9 +10,9 @@ "attrs", "pydantic[dotenv]<2", "stac_pydantic==2.0.*", - "stac-fastapi.types==2.5.1", - "stac-fastapi.api==2.5.1", - "stac-fastapi.extensions==2.5.1", + "stac-fastapi.types==2.5.2", + "stac-fastapi.api==2.5.2", + "stac-fastapi.extensions==2.5.2", "pystac[validation]", "orjson", "overrides", From ce95505e3afeb83a9b83e5deec5202569cfa954e Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Fri, 19 Apr 2024 01:21:23 +0800 Subject: [PATCH 06/15] fix test router --- stac_fastapi/tests/api/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stac_fastapi/tests/api/test_api.py b/stac_fastapi/tests/api/test_api.py index 74f0bb55..61641708 100644 --- a/stac_fastapi/tests/api/test_api.py +++ b/stac_fastapi/tests/api/test_api.py @@ -28,7 +28,7 @@ "DELETE /collections/{collection_id}/items/{item_id}", "POST /collections", "POST /collections/{collection_id}/items", - "PUT /collections", + "PUT /collections/{collection_id}", "PUT /collections/{collection_id}/items/{item_id}", } From 8aaa687286c88cff2ecf153221573454fbbe7bae Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Fri, 19 Apr 2024 14:05:01 +0800 Subject: [PATCH 07/15] fix intersects GET returning list --- stac_fastapi/core/stac_fastapi/core/core.py | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 1c995f12..89b138bf 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -1,4 +1,5 @@ """Item crud client.""" +import json import logging import re from datetime import datetime as datetime_type @@ -452,8 +453,27 @@ async def get_search( if datetime: base_args["datetime"] = datetime + # As of stac-fastapi 2.5.x, the intersects GET request parameter is being sent as a list if intersects: - base_args["intersects"] = orjson.loads(unquote_plus(intersects)) + intersects_dict = {"type": None, "coordinates": None} + + combined_json_string = intersects[0] + + # Iterate over the remaining fragments and add each with a preceding comma + for fragment in intersects[1:]: + combined_json_string += "," + fragment + + combined_json_string = combined_json_string.replace("'", "") + combined_json_string = "".join( + char for char in combined_json_string if char.isprintable() + ) + + try: + intersects_dict = json.loads(combined_json_string) + except json.JSONDecodeError as error: + print("Failed to parse JSON:", error) + + base_args["intersects"] = intersects_dict if sortby: sort_param = [] From df388f27a41219239ad69f7dde5701380b8970b9 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Sat, 20 Apr 2024 00:19:57 +0800 Subject: [PATCH 08/15] update for GET request datetime --- stac_fastapi/core/stac_fastapi/core/core.py | 53 +++++++++++++-------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 89b138bf..c372b200 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -271,6 +271,12 @@ async def item_collection( Exception: If any error occurs while reading the items from the database. """ request: Request = kwargs["request"] + query_params = dict(request.query_params) # Convert MultiDict to dict + + # I am not sure why I have to do this + if "datetime" in query_params: + datetime = query_params['datetime'] + base_url = str(request.base_url) collection = await self.get_collection( @@ -357,18 +363,18 @@ async def get_item(self, item_id: str, collection_id: str, **kwargs) -> Item: # ] @staticmethod - def _return_date(interval: Optional[DateTimeType]) -> dict: + def _return_date(interval: Optional[Union[DateTimeType, str]]) -> Dict[str, Optional[str]]: """ - Convert a date interval already parsed as DateTimeType into a dictionary. - - For filtering search results with Elasticsearch. + Convert a date interval (which may be a datetime, a tuple of one or two datetimes, + a string representing a datetime or range, or None) into a dictionary for filtering + search results with Elasticsearch. - This function ensures the output dictionary contains 'gte' and 'lte' keys - even if they are set to None to prevent KeyError in the consuming logic. + This function ensures the output dictionary contains 'gte' and 'lte' keys, + even if they are set to None, to prevent KeyError in the consuming logic. Args: - interval (Optional[DateTimeType]): The date interval, which might be a single datetime, - a tuple with one or two datetimes, or None. + interval (Optional[Union[DateTimeType, str]]): The date interval, which might be a single datetime, + a tuple with one or two datetimes, a string, or None. Returns: dict: A dictionary representing the date interval for use in filtering search results, @@ -377,21 +383,28 @@ def _return_date(interval: Optional[DateTimeType]) -> dict: result: Dict[str, Optional[str]] = {"gte": None, "lte": None} if interval is None: - return result # Return default if no interval is specified + return result - if isinstance(interval, datetime_type): - # Single datetime object for both 'gte' and 'lte' - datetime_iso = interval.isoformat() - result["gte"] = datetime_iso - result["lte"] = datetime_iso + if isinstance(interval, str): + if '/' in interval: + parts = interval.split('/') + result['gte'] = parts[0] if parts[0] != ".." else None + result['lte'] = parts[1] if len(parts) > 1 and parts[1] != ".." else None + else: + converted_time = interval if interval != ".." else None + result['gte'] = result['lte'] = converted_time return result - # Handling tuples, which may contain one or two datetime objects or None - start, end = interval - if start: - result["gte"] = start.isoformat() - if end: - result["lte"] = end.isoformat() + if isinstance(interval, datetime_type): + datetime_iso = interval.isoformat() + result['gte'] = result['lte'] = datetime_iso + elif isinstance(interval, tuple): + start, end = interval + # Ensure datetimes are converted to UTC and formatted with 'Z' + if start: + result["gte"] = start.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' + if end: + result["lte"] = end.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' return result From efaa561f74bf186d6edca644752ce5a20063e171 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Sat, 20 Apr 2024 00:24:43 +0800 Subject: [PATCH 09/15] lint, add comment --- stac_fastapi/core/stac_fastapi/core/core.py | 32 ++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index c372b200..63aeb77e 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -273,9 +273,9 @@ async def item_collection( request: Request = kwargs["request"] query_params = dict(request.query_params) # Convert MultiDict to dict - # I am not sure why I have to do this + # I am not sure why I have to do this .... as of stac-fastapi 2.5.2 if "datetime" in query_params: - datetime = query_params['datetime'] + datetime = query_params["datetime"] base_url = str(request.base_url) @@ -363,10 +363,14 @@ async def get_item(self, item_id: str, collection_id: str, **kwargs) -> Item: # ] @staticmethod - def _return_date(interval: Optional[Union[DateTimeType, str]]) -> Dict[str, Optional[str]]: + def _return_date( + interval: Optional[Union[DateTimeType, str]] + ) -> Dict[str, Optional[str]]: """ - Convert a date interval (which may be a datetime, a tuple of one or two datetimes, - a string representing a datetime or range, or None) into a dictionary for filtering + Convert a date interval. + + (which may be a datetime, a tuple of one or two datetimes a string + representing a datetime or range, or None) into a dictionary for filtering search results with Elasticsearch. This function ensures the output dictionary contains 'gte' and 'lte' keys, @@ -386,25 +390,27 @@ def _return_date(interval: Optional[Union[DateTimeType, str]]) -> Dict[str, Opti return result if isinstance(interval, str): - if '/' in interval: - parts = interval.split('/') - result['gte'] = parts[0] if parts[0] != ".." else None - result['lte'] = parts[1] if len(parts) > 1 and parts[1] != ".." else None + if "/" in interval: + parts = interval.split("/") + result["gte"] = parts[0] if parts[0] != ".." else None + result["lte"] = ( + parts[1] if len(parts) > 1 and parts[1] != ".." else None + ) else: converted_time = interval if interval != ".." else None - result['gte'] = result['lte'] = converted_time + result["gte"] = result["lte"] = converted_time return result if isinstance(interval, datetime_type): datetime_iso = interval.isoformat() - result['gte'] = result['lte'] = datetime_iso + result["gte"] = result["lte"] = datetime_iso elif isinstance(interval, tuple): start, end = interval # Ensure datetimes are converted to UTC and formatted with 'Z' if start: - result["gte"] = start.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' + result["gte"] = start.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" if end: - result["lte"] = end.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' + result["lte"] = end.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" return result From b22cebce3d6bd9bb72ebe25f9e2376094dcd45f1 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Sat, 20 Apr 2024 00:34:50 +0800 Subject: [PATCH 10/15] add explanation --- stac_fastapi/tests/resources/test_item.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stac_fastapi/tests/resources/test_item.py b/stac_fastapi/tests/resources/test_item.py index 64240e9e..2250d922 100644 --- a/stac_fastapi/tests/resources/test_item.py +++ b/stac_fastapi/tests/resources/test_item.py @@ -829,5 +829,6 @@ async def test_search_datetime_validation_errors(app_client): resp = await app_client.post("/search", json=body) assert resp.status_code == 400 + # Getting this instead ValueError: Invalid RFC3339 datetime. # resp = await app_client.get("/search?datetime={}".format(dt)) # assert resp.status_code == 400 From a95019bcfd612bfdce8e0cff254ece11f6e9a84d Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Sun, 21 Apr 2024 12:33:17 +0800 Subject: [PATCH 11/15] fix f strings --- stac_fastapi/tests/resources/test_collection.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stac_fastapi/tests/resources/test_collection.py b/stac_fastapi/tests/resources/test_collection.py index 8917bc5d..97c9a5f6 100644 --- a/stac_fastapi/tests/resources/test_collection.py +++ b/stac_fastapi/tests/resources/test_collection.py @@ -73,7 +73,7 @@ async def test_update_new_collection(app_client, load_test_data): test_collection["id"] = "new-test-collection" resp = await app_client.put( - "/collections/{ctx.collection['id']}", json=test_collection + f"/collections/{test_collection['id']}", json=test_collection ) assert resp.status_code == 404 @@ -89,7 +89,7 @@ async def test_collection_not_found(app_client): async def test_returns_valid_collection(ctx, app_client): """Test validates fetched collection with jsonschema""" resp = await app_client.put( - "/collections/{ctx.collection['id']}", json=ctx.collection + f"/collections/{ctx.collection['id']}", json=ctx.collection ) assert resp.status_code == 200 @@ -116,7 +116,7 @@ async def test_collection_extensions(ctx, app_client): test_asset = {"title": "test", "description": "test", "type": "test"} ctx.collection["item_assets"] = {"test": test_asset} resp = await app_client.put( - "/collections/{ctx.collection['id']}", json=ctx.collection + f"/collections/{ctx.collection['id']}", json=ctx.collection ) assert resp.status_code == 200 From 6c013f081cc9805bf33da6d1b30c6b00359bb7f6 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Sun, 21 Apr 2024 12:34:43 +0800 Subject: [PATCH 12/15] remove comment --- stac_fastapi/core/stac_fastapi/core/core.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 63aeb77e..5dab712f 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -356,12 +356,6 @@ async def get_item(self, item_id: str, collection_id: str, **kwargs) -> Item: ) return self.item_serializer.db_to_stac(item, base_url) - # DateTimeType = Union[ - # datetime, - # Tuple[datetime, datetime], - # Tuple[Optional[datetime], Optional[datetime]] - # ] - @staticmethod def _return_date( interval: Optional[Union[DateTimeType, str]] From bd71de5bf9c35264dac9f0bd1bf3575bbe3a2eb8 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 23 Apr 2024 19:21:14 +0800 Subject: [PATCH 13/15] update for v2.5.3 --- CHANGELOG.md | 2 +- stac_fastapi/core/setup.py | 6 +-- stac_fastapi/core/stac_fastapi/core/core.py | 42 ++++++--------------- 3 files changed, 15 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e7f7982..deda98b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -- Upgraded stac-fastapi libraries to v2.5.2 from v2.4.9 [#172](https://github.com/stac-utils/stac-fastapi-elasticsearch/pull/172) +- Upgraded stac-fastapi libraries to v2.5.3 from v2.4.9 [#172](https://github.com/stac-utils/stac-fastapi-elasticsearch/pull/172) ## [v2.2.0] diff --git a/stac_fastapi/core/setup.py b/stac_fastapi/core/setup.py index 094fdc7a..bc7bb8ea 100644 --- a/stac_fastapi/core/setup.py +++ b/stac_fastapi/core/setup.py @@ -10,9 +10,9 @@ "attrs", "pydantic[dotenv]<2", "stac_pydantic==2.0.*", - "stac-fastapi.types==2.5.2", - "stac-fastapi.api==2.5.2", - "stac-fastapi.extensions==2.5.2", + "stac-fastapi.types==2.5.3", + "stac-fastapi.api==2.5.3", + "stac-fastapi.extensions==2.5.3", "pystac[validation]", "orjson", "overrides", diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 5dab712f..1182e556 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -1,5 +1,4 @@ -"""Item crud client.""" -import json +"""Core client.""" import logging import re from datetime import datetime as datetime_type @@ -16,7 +15,7 @@ from pygeofilter.backends.cql2_json import to_cql2 from pygeofilter.parsers.cql2_text import parse as parse_cql2_text from stac_pydantic.links import Relations -from stac_pydantic.shared import MimeTypes +from stac_pydantic.shared import BBox, MimeTypes from stac_pydantic.version import STAC_VERSION from stac_fastapi.core.base_database_logic import BaseDatabaseLogic @@ -246,8 +245,8 @@ async def get_collection(self, collection_id: str, **kwargs) -> Collection: async def item_collection( self, collection_id: str, - bbox: Optional[List[NumType]] = None, - datetime: Union[str, datetime_type, None] = None, + bbox: Optional[BBox] = None, + datetime: Optional[DateTimeType] = None, limit: int = 10, token: str = None, **kwargs, @@ -256,8 +255,8 @@ async def item_collection( Args: collection_id (str): The identifier of the collection to read items from. - bbox (Optional[List[NumType]]): The bounding box to filter items by. - datetime (Union[str, datetime_type, None]): The datetime range to filter items by. + bbox (OOptional[BBox]): The bounding box to filter items by. + datetime (Optional[DateTimeType]): The datetime range to filter items by. limit (int): The maximum number of items to return. The default value is 10. token (str): A token used for pagination. request (Request): The incoming request. @@ -413,8 +412,8 @@ async def get_search( request: Request, collections: Optional[List[str]] = None, ids: Optional[List[str]] = None, - bbox: Optional[List[NumType]] = None, - datetime: Optional[Union[str, datetime_type]] = None, + bbox: Optional[BBox] = None, + datetime: Optional[DateTimeType] = None, limit: Optional[int] = 10, query: Optional[str] = None, token: Optional[str] = None, @@ -430,8 +429,8 @@ async def get_search( Args: collections (Optional[List[str]]): List of collection IDs to search in. ids (Optional[List[str]]): List of item IDs to search for. - bbox (Optional[List[NumType]]): Bounding box to search in. - datetime (Optional[Union[str, datetime_type]]): Filter items based on the datetime field. + bbox (Optional[BBox]): Bounding box to search in. + datetime (Optional[DateTimeType]): Filter items based on the datetime field. limit (Optional[int]): Maximum number of results to return. query (Optional[str]): Query string to filter the results. token (Optional[str]): Access token to use when searching the catalog. @@ -466,27 +465,8 @@ async def get_search( if datetime: base_args["datetime"] = datetime - # As of stac-fastapi 2.5.x, the intersects GET request parameter is being sent as a list if intersects: - intersects_dict = {"type": None, "coordinates": None} - - combined_json_string = intersects[0] - - # Iterate over the remaining fragments and add each with a preceding comma - for fragment in intersects[1:]: - combined_json_string += "," + fragment - - combined_json_string = combined_json_string.replace("'", "") - combined_json_string = "".join( - char for char in combined_json_string if char.isprintable() - ) - - try: - intersects_dict = json.loads(combined_json_string) - except json.JSONDecodeError as error: - print("Failed to parse JSON:", error) - - base_args["intersects"] = intersects_dict + base_args["intersects"] = orjson.loads(unquote_plus(intersects)) if sortby: sort_param = [] From ba7efaf88228298330eb29b453579ff1a972a3e3 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 23 Apr 2024 19:29:18 +0800 Subject: [PATCH 14/15] remove date fix hack --- stac_fastapi/core/stac_fastapi/core/core.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 1182e556..979d6773 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -270,12 +270,6 @@ async def item_collection( Exception: If any error occurs while reading the items from the database. """ request: Request = kwargs["request"] - query_params = dict(request.query_params) # Convert MultiDict to dict - - # I am not sure why I have to do this .... as of stac-fastapi 2.5.2 - if "datetime" in query_params: - datetime = query_params["datetime"] - base_url = str(request.base_url) collection = await self.get_collection( From c8ac185db1ff62cd951567ee511aa7db499d4f75 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 23 Apr 2024 19:35:17 +0800 Subject: [PATCH 15/15] spelling --- stac_fastapi/core/stac_fastapi/core/core.py | 2 +- stac_fastapi/tests/resources/test_collection.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stac_fastapi/core/stac_fastapi/core/core.py b/stac_fastapi/core/stac_fastapi/core/core.py index 979d6773..936b2553 100644 --- a/stac_fastapi/core/stac_fastapi/core/core.py +++ b/stac_fastapi/core/stac_fastapi/core/core.py @@ -255,7 +255,7 @@ async def item_collection( Args: collection_id (str): The identifier of the collection to read items from. - bbox (OOptional[BBox]): The bounding box to filter items by. + bbox (Optional[BBox]): The bounding box to filter items by. datetime (Optional[DateTimeType]): The datetime range to filter items by. limit (int): The maximum number of items to return. The default value is 10. token (str): A token used for pagination. diff --git a/stac_fastapi/tests/resources/test_collection.py b/stac_fastapi/tests/resources/test_collection.py index 97c9a5f6..13100239 100644 --- a/stac_fastapi/tests/resources/test_collection.py +++ b/stac_fastapi/tests/resources/test_collection.py @@ -56,7 +56,7 @@ async def test_update_collection_already_exists(ctx, app_client): """Test updating a collection which already exists""" ctx.collection["keywords"].append("test") resp = await app_client.put( - "/collections/{ctx.collection['id']}", json=ctx.collection + f"/collections/{ctx.collection['id']}", json=ctx.collection ) assert resp.status_code == 200