From 1726a623b8948afc842985192f0eb03ebf655e9f Mon Sep 17 00:00:00 2001 From: vincentsarago Date: Fri, 17 Jan 2025 09:50:30 +0100 Subject: [PATCH] rename filter to filter_expr to avoid python method conflict --- CHANGES.md | 1 + stac_fastapi/api/tests/test_app.py | 19 ++++---------- stac_fastapi/api/tests/test_models.py | 26 ++++++++++++------- .../extensions/core/filter/request.py | 6 +++-- .../tests/test_collection_search.py | 14 +++++----- stac_fastapi/extensions/tests/test_filter.py | 6 +++-- 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0d23d55cf..67cee3ea3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ ## Changed * use `string` type instead of python `datetime.datetime` for datetime parameter in `BaseSearchGetRequest`, `ItemCollectionUri` and `BaseCollectionSearchGetRequest` GET models +* rename `filter` to `filter_expr` for `FilterExtensionGetRequest` and `FilterExtensionPostRequest` attributes to avoid conflict with python filter method ## [3.0.5] - 2025-01-10 diff --git a/stac_fastapi/api/tests/test_app.py b/stac_fastapi/api/tests/test_app.py index 106bde389..59b09d9fc 100644 --- a/stac_fastapi/api/tests/test_app.py +++ b/stac_fastapi/api/tests/test_app.py @@ -126,7 +126,7 @@ def post_search( self, search_request: BaseSearchPostRequest, **kwargs ) -> stac.ItemCollection: search_request.collections = ["test"] - search_request.filter = {} + search_request.filter_expr = {} search_request.filter_crs = "EPSG:4326" search_request.filter_lang = "cql2-text" @@ -142,23 +142,14 @@ def get_search( intersects: Optional[str] = None, datetime: Optional[str] = None, limit: Optional[int] = 10, - filter: Optional[str] = None, + filter_expr: Optional[str] = None, filter_crs: Optional[str] = None, filter_lang: Optional[str] = None, **kwargs, ) -> stac.ItemCollection: - # Check if all filter parameters are passed correctly - - assert filter == "TEST" - - # FIXME: https://github.com/stac-utils/stac-fastapi/issues/638 - # hyphen alias for filter_crs and filter_lang are currently not working - # Query parameters `filter-crs` and `filter-lang` - # should be recognized by the API - # They are present in the `request.query_params` but not in the `kwargs` - - # assert filter_crs == "EPSG:4326" - # assert filter_lang == "cql2-text" + assert filter_expr == "TEST" + assert filter_crs == "EPSG:4326" + assert filter_lang == "cql2-text" return stac.ItemCollection( type="FeatureCollection", features=[stac.Item(**item_dict)] diff --git a/stac_fastapi/api/tests/test_models.py b/stac_fastapi/api/tests/test_models.py index 0c25e7f3d..283c79f7e 100644 --- a/stac_fastapi/api/tests/test_models.py +++ b/stac_fastapi/api/tests/test_models.py @@ -28,12 +28,13 @@ def test_create_get_request_model(): ), datetime="2020-01-01T00:00:00.00001Z", limit=10, - filter="test==test", + filter_expr="test==test", filter_crs="epsg:4326", filter_lang="cql2-text", ) assert model.collections == ["test1", "test2"] + assert model.filter_expr == "test==test" assert model.filter_crs == "epsg:4326" d = model.start_date assert d.microsecond == 10 @@ -64,6 +65,7 @@ def route(model=Depends(request_model)): "/test", params={ "collections": "test1,test2", + "filter": "test=test", "filter-crs": "epsg:4326", "filter-lang": "cql2-text", }, @@ -71,6 +73,7 @@ def route(model=Depends(request_model)): assert resp.status_code == 200 response_dict = resp.json() assert response_dict["collections"] == ["test1", "test2"] + assert response_dict["filter_expr"] == "test=test" assert response_dict["filter_crs"] == "epsg:4326" assert response_dict["filter_lang"] == "cql2-text" @@ -89,19 +92,22 @@ def test_create_post_request_model(filter_val, passes): with pytest.raises(ValidationError): model = request_model(filter=filter_val) else: - model = request_model( - collections=["test1", "test2"], - ids=["test1", "test2"], - bbox=[0, 0, 1, 1], - datetime="2020-01-01T00:00:00.00001Z", - limit=10, - filter=filter_val, - **{"filter-crs": "epsg:4326", "filter-lang": "cql2-json"}, + model = request_model.model_validate( + { + "collections": ["test1", "test2"], + "ids": ["test1", "test2"], + "bbox": [0, 0, 1, 1], + "datetime": "2020-01-01T00:00:00.00001Z", + "limit": 10, + "filter": filter_val, + "filter-crs": "epsg:4326", + "filter-lang": "cql2-json", + } ) assert model.collections == ["test1", "test2"] + assert model.filter_expr == filter_val assert model.filter_crs == "epsg:4326" - assert model.filter == filter_val assert model.datetime == "2020-01-01T00:00:00.00001Z" with pytest.raises(ValidationError): diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/core/filter/request.py b/stac_fastapi/extensions/stac_fastapi/extensions/core/filter/request.py index dae56a51c..b87c63b88 100644 --- a/stac_fastapi/extensions/stac_fastapi/extensions/core/filter/request.py +++ b/stac_fastapi/extensions/stac_fastapi/extensions/core/filter/request.py @@ -16,9 +16,10 @@ class FilterExtensionGetRequest(APIRequest): """Filter extension GET request model.""" - filter: Annotated[ + filter_expr: Annotated[ Optional[str], Query( + alias="filter", description="""A CQL filter expression for filtering items.\n Supports `CQL-JSON` as defined in https://portal.ogc.org/files/96288\n Remember to URL encode the CQL-JSON if using GET""", @@ -46,8 +47,9 @@ class FilterExtensionGetRequest(APIRequest): class FilterExtensionPostRequest(BaseModel): """Filter extension POST request model.""" - filter: Optional[Dict[str, Any]] = Field( + filter_expr: Optional[Dict[str, Any]] = Field( default=None, + alias="filter", description="A CQL filter expression for filtering items.", json_schema_extra={ "example": { diff --git a/stac_fastapi/extensions/tests/test_collection_search.py b/stac_fastapi/extensions/tests/test_collection_search.py index 3b7bcfc2a..83de85eba 100644 --- a/stac_fastapi/extensions/tests/test_collection_search.py +++ b/stac_fastapi/extensions/tests/test_collection_search.py @@ -185,7 +185,7 @@ def test_collection_search_extension_models(): assert "datetime" in response_dict assert "limit" in response_dict assert "q" in response_dict - assert "filter" in response_dict + assert "filter_expr" in response_dict assert "query" in response_dict assert "sortby" in response_dict assert "fields" in response_dict @@ -211,7 +211,9 @@ def test_collection_search_extension_models(): assert "2020-06-13T13:00:00Z/2020-06-13T14:00:00Z" == response_dict["datetime"] assert 100 == response_dict["limit"] assert ["EO", "Earth Observation"] == response_dict["q"] - assert "id='item_id' AND collection='collection_id'" == response_dict["filter"] + assert ( + "id='item_id' AND collection='collection_id'" == response_dict["filter_expr"] + ) assert "filter_crs" in response_dict assert "cql2-text" in response_dict["filter_lang"] assert "query" in response_dict @@ -347,7 +349,7 @@ def test_collection_search_extension_post_models(): assert "datetime" in response_dict assert "limit" in response_dict assert "q" in response_dict - assert "filter" in response_dict + assert "filter_expr" in response_dict assert "query" in response_dict assert "sortby" in response_dict assert "fields" in response_dict @@ -388,7 +390,7 @@ def test_collection_search_extension_post_models(): assert "2020-06-13T13:00:00Z/2020-06-13T14:00:00Z" == response_dict["datetime"] assert 10_000 == response_dict["limit"] assert ["EO", "Earth Observation"] == response_dict["q"] - assert response_dict["filter"] + assert response_dict["filter_expr"] assert "filter_crs" in response_dict assert "cql2-json" in response_dict["filter_lang"] assert response_dict["query"] @@ -433,7 +435,7 @@ def test_from_extensions_methods(extensions): assert hasattr(collection_search, "fields") assert hasattr(collection_search, "q") assert hasattr(collection_search, "sortby") - assert hasattr(collection_search, "filter") + assert hasattr(collection_search, "filter_expr") assert ext.conformance_classes == [ ConformanceClasses.COLLECTIONSEARCH, ConformanceClasses.BASIS, @@ -457,7 +459,7 @@ def test_from_extensions_methods(extensions): assert hasattr(collection_search, "fields") assert hasattr(collection_search, "q") assert hasattr(collection_search, "sortby") - assert hasattr(collection_search, "filter") + assert hasattr(collection_search, "filter_expr") assert ext.conformance_classes == [ ConformanceClasses.COLLECTIONSEARCH, ConformanceClasses.BASIS, diff --git a/stac_fastapi/extensions/tests/test_filter.py b/stac_fastapi/extensions/tests/test_filter.py index 85db52611..32152c432 100644 --- a/stac_fastapi/extensions/tests/test_filter.py +++ b/stac_fastapi/extensions/tests/test_filter.py @@ -57,6 +57,7 @@ def test_search_filter_post_filter_lang_default(client: TestClient): ) assert response.is_success, response.json() response_dict = response.json() + assert response_dict["filter_expr"] assert response_dict["filter_lang"] == "cql2-json" @@ -73,6 +74,7 @@ def test_search_filter_post_filter_lang_non_default(client: TestClient): ) assert response.is_success, response.json() response_dict = response.json() + assert response_dict["filter_expr"] assert response_dict["filter_lang"] == filter_lang_value @@ -87,7 +89,7 @@ def test_search_filter_get(client: TestClient): assert response.is_success, response.json() response_dict = response.json() assert not response_dict["collections"] - assert response_dict["filter"] == "id='item_id' AND collection='collection_id'" + assert response_dict["filter_expr"] == "id='item_id' AND collection='collection_id'" assert not response_dict["filter_crs"] assert response_dict["filter_lang"] == "cql2-text" @@ -102,7 +104,7 @@ def test_search_filter_get(client: TestClient): response_dict = response.json() assert not response_dict["collections"] assert ( - response_dict["filter"] + response_dict["filter_expr"] == "{'op': '=', 'args': [{'property': 'id'}, 'test-item']}" ) assert not response_dict["filter_crs"]