From 3695e4e5d779d046f79545e52cc27e2cb974e45f Mon Sep 17 00:00:00 2001 From: Matt McFarland Date: Tue, 4 Jan 2022 11:52:16 -0500 Subject: [PATCH 1/3] Allow providing filter-lang to search The user can optionally provide a filter-lang parameter to the ItemSearch endpoint when using filter. This preserves the existing behavior of defaulting to `cql-json` when no value is provided, so it should be backwards compatible with existing code. By optionally providing a new value, such as `cql2-json`, the user can supply filters with different JSON language variants. --- pystac_client/item_search.py | 17 ++++++++++++++--- tests/test_item_search.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pystac_client/item_search.py b/pystac_client/item_search.py index cb2df4d2..ef1de787 100644 --- a/pystac_client/item_search.py +++ b/pystac_client/item_search.py @@ -41,6 +41,8 @@ Query = dict QueryLike = Union[Query, List[str]] +FilterLangLike = str + FilterLike = dict Sortby = List[str] @@ -135,6 +137,7 @@ class ItemSearch: of the provided Collections will be searched query: List or JSON of query parameters as per the STAC API `query` extension filter: JSON of query parameters as per the STAC API `filter` extension + filter_lang: Language variant used in the filter body. Defaults to 'cql-json'. sortby: A single field or list of fields to sort the response by fields: A list of fields to return in the response. Note this may result in invalid JSON. Use `get_all_items_as_dict` to avoid errors @@ -154,6 +157,7 @@ def __init__(self, collections: Optional[CollectionsLike] = None, query: Optional[QueryLike] = None, filter: Optional[FilterLike] = None, + filter_lang: Optional[FilterLangLike] = None, sortby: Optional[SortbyLike] = None, fields: Optional[FieldsLike] = None, max_items: Optional[int] = None, @@ -187,13 +191,11 @@ def __init__(self, 'intersects': self._format_intersects(intersects), 'query': self._format_query(query), 'filter': self._format_filter(filter), + 'filter-lang': self._format_filter_lang(filter, filter_lang), 'sortby': self._format_sortby(sortby), 'fields': self._format_fields(fields) } - if params['filter'] is not None: - params['filter-lang'] = 'cql-json' - self._parameters = {k: v for k, v in params.items() if v is not None} def get_parameters(self): @@ -237,6 +239,15 @@ def _format_query(value: List[QueryLike]) -> Optional[dict]: return query + def _format_filter_lang(self, filter: FilterLike, value: FilterLike) -> Optional[str]: + if filter is None: + return None + + if value is None: + return 'cql-json' + + return value + def _format_filter(self, value: FilterLike) -> Optional[dict]: if value is None: return None diff --git a/tests/test_item_search.py b/tests/test_item_search.py index e6b7bc4e..c13c4746 100644 --- a/tests/test_item_search.py +++ b/tests/test_item_search.py @@ -260,6 +260,21 @@ def test_intersects_json_string(self): search = ItemSearch(url=SEARCH_URL, intersects=json.dumps(INTERSECTS_EXAMPLE)) assert search._parameters['intersects'] == INTERSECTS_EXAMPLE + def test_filter_lang_default(self): + # No filter_lang specified + search = ItemSearch(url=SEARCH_URL, filter={}) + assert search._parameters['filter-lang'] == 'cql-json' + + def test_filter_lang(self): + # Use specified filter_lang + search = ItemSearch(url=SEARCH_URL, filter_lang="cql2-json", filter={}) + assert search._parameters['filter-lang'] == 'cql2-json' + + def test_filter_lang_without_filter(self): + # No filter provided + search = ItemSearch(url=SEARCH_URL) + assert 'filter-lang' not in search._parameters + class TestItemSearch: @pytest.fixture(scope='function') From 12d1a8e14683de452bafce1239d0c62216d6e1b7 Mon Sep 17 00:00:00 2001 From: Matt McFarland Date: Tue, 4 Jan 2022 12:13:37 -0500 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae51d0df..348acdba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- `Client.search` accepts an optional `filter_lang` argument for `filter` requests [#128](https://github.com/stac-utils/pystac-client/pull/128) + ### Fixed - Parameter formatting for GET searches in `ItemSearch.get_parameters` [#124](https://github.com/stac-utils/pystac-client/pull/124) From 2e24e62a4fe0fe6456329a225f601b104d38661a Mon Sep 17 00:00:00 2001 From: Matt McFarland Date: Tue, 4 Jan 2022 12:20:12 -0500 Subject: [PATCH 3/3] Use correct type annotation for filter-lang --- pystac_client/item_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac_client/item_search.py b/pystac_client/item_search.py index ef1de787..248b20e3 100644 --- a/pystac_client/item_search.py +++ b/pystac_client/item_search.py @@ -239,7 +239,7 @@ def _format_query(value: List[QueryLike]) -> Optional[dict]: return query - def _format_filter_lang(self, filter: FilterLike, value: FilterLike) -> Optional[str]: + def _format_filter_lang(self, filter: FilterLike, value: FilterLangLike) -> Optional[str]: if filter is None: return None