diff --git a/CHANGELOG.md b/CHANGELOG.md index f3824554..414f8e64 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] +### Fixed + +- Use singular `include` and `exclude` Field extension key names to align with the extension documentation. [#690](https://github.com/stac-utils/pystac-client/issues/690) + ## [v0.8.0] - 2024-05-17 ### Fixed diff --git a/pystac_client/item_search.py b/pystac_client/item_search.py index de9b51c5..5e6303a5 100644 --- a/pystac_client/item_search.py +++ b/pystac_client/item_search.py @@ -633,12 +633,12 @@ def _fields_to_dict(fields: List[str]) -> Fields: includes.append(field[1:]) else: includes.append(field) - return {"includes": includes, "excludes": excludes} + return {"include": includes, "exclude": excludes} @staticmethod def _fields_dict_to_str(fields: Fields) -> str: - includes = [f"+{x}" for x in fields.get("includes", [])] - excludes = [f"-{x}" for x in fields.get("excludes", [])] + includes = [f"+{x}" for x in fields.get("include", [])] + excludes = [f"-{x}" for x in fields.get("exclude", [])] return ",".join(chain(includes, excludes)) @staticmethod diff --git a/tests/cassettes/test_item_search/test_fields.yaml b/tests/cassettes/test_item_search/test_fields.yaml new file mode 100644 index 00000000..49e3a2b8 --- /dev/null +++ b/tests/cassettes/test_item_search/test_fields.yaml @@ -0,0 +1,59 @@ +interactions: +- request: + body: '{"collections": ["sentinel-2-c1-l2a"], "intersects": {"type": "Point", + "coordinates": [-105.1019, 40.1672]}, "fields": {"include": [], "exclude": ["geometry", + "assets", "links"]}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '179' + Content-Type: + - application/json + User-Agent: + - python-requests/2.31.0 + method: POST + uri: https://earth-search.aws.element84.com/v1/search + response: + body: + string: '{"type":"FeatureCollection","stac_version":"1.0.0","stac_extensions":[],"context":{"limit":10,"matched":572,"returned":10},"numberMatched":572,"numberReturned":10,"features":[{"stac_version":"1.0.0","bbox":[-105.349918,39.661089,-104.884569,40.650836],"id":"S2A_T13TDE_20240522T174948_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-22T17:52:58.479000Z"}},{"stac_version":"1.0.0","bbox":[-106.183161,39.655762,-104.884569,40.65079],"id":"S2B_T13TDE_20240520T175430_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-20T18:02:54.683000Z"}},{"stac_version":"1.0.0","bbox":[-105.348402,39.661093,-104.884569,40.650836],"id":"S2B_T13TDE_20240517T174143_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-17T17:52:57.296000Z"}},{"stac_version":"1.0.0","bbox":[-106.183161,39.655762,-104.884569,40.65079],"id":"S2A_T13TDE_20240515T175302_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-15T18:02:58.179000Z"}},{"stac_version":"1.0.0","bbox":[-105.368102,39.661033,-104.884569,40.650826],"id":"S2A_T13TDE_20240512T174554_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-12T17:53:02.216000Z"}},{"stac_version":"1.0.0","bbox":[-106.183161,39.655762,-104.884569,40.65079],"id":"S2B_T13TDE_20240510T175043_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-10T18:02:56.145000Z"}},{"stac_version":"1.0.0","bbox":[-105.361809,39.661052,-104.884569,40.650829],"id":"S2B_T13TDE_20240507T174341_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-07T17:52:59.873000Z"}},{"stac_version":"1.0.0","bbox":[-106.183161,39.655762,-104.884569,40.65079],"id":"S2A_T13TDE_20240505T175610_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-05T18:02:58.175000Z"}},{"stac_version":"1.0.0","bbox":[-105.368337,39.661032,-104.884569,40.650825],"id":"S2A_T13TDE_20240502T175028_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-05-02T17:53:01.904000Z"}},{"stac_version":"1.0.0","bbox":[-106.183161,39.655762,-104.884569,40.65079],"id":"S2B_T13TDE_20240430T175332_L2A","collection":"sentinel-2-c1-l2a","type":"Feature","properties":{"datetime":"2024-04-30T18:02:55.400000Z"}}],"links":[{"rel":"next","title":"Next + page of Items","method":"POST","type":"application/geo+json","href":"https://earth-search.aws.element84.com/v1/search","merge":false,"body":{"intersects":{"type":"Point","coordinates":[-105.1019,40.1672]},"fields":{"include":[],"exclude":["geometry","assets","links"]},"collections":["sentinel-2-c1-l2a"],"next":"2024-04-30T18:02:55.400000Z,S2B_T13TDE_20240430T175332_L2A,sentinel-2-c1-l2a"}},{"rel":"root","type":"application/json","href":"https://earth-search.aws.element84.com/v1"}]}' + headers: + Connection: + - keep-alive + Content-Length: + - '2914' + Content-Type: + - application/geo+json; charset=utf-8 + Date: + - Thu, 23 May 2024 13:55:07 GMT + Via: + - 1.1 584febef1233840787d98d1cd03f82c0.cloudfront.net (CloudFront) + X-Amz-Cf-Id: + - SvrAu9sInbz45xXsZLnU9fYdDuyPI4l5_IVhZTXZaoplQEKQ9CUNKw== + X-Amz-Cf-Pop: + - DEN52-C1 + X-Amzn-Trace-Id: + - Root=1-664f4abb-67c82c1178b7ad8c4adf165a;Parent=07f14554667b6d8c;Sampled=0;lineage=9e2884e9:0 + X-Cache: + - Miss from cloudfront + access-control-allow-origin: + - '*' + etag: + - W/"b62-IhsIfKrcigmqt63/hc9yHpeCjD8" + x-amz-apigw-id: + - YOidRFT8vHcEj-w= + x-amzn-Remapped-content-length: + - '2914' + x-amzn-RequestId: + - d105b93a-e1f1-4d32-b4ef-86a4b3e10525 + x-powered-by: + - Express + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_item_search.py b/tests/test_item_search.py index a198181e..3f38a3c4 100644 --- a/tests/test_item_search.py +++ b/tests/test_item_search.py @@ -468,23 +468,23 @@ def test_fields(self) -> None: search = ItemSearch(url=SEARCH_URL, fields="id,collection,+foo,-bar") assert search.get_parameters()["fields"] == { - "excludes": ["bar"], - "includes": ["id", "collection", "foo"], + "exclude": ["bar"], + "include": ["id", "collection", "foo"], } search = ItemSearch(url=SEARCH_URL, fields=["id", "collection", "+foo", "-bar"]) assert search.get_parameters()["fields"] == { - "excludes": ["bar"], - "includes": ["id", "collection", "foo"], + "exclude": ["bar"], + "include": ["id", "collection", "foo"], } search = ItemSearch( url=SEARCH_URL, - fields={"excludes": ["bar"], "includes": ["id", "collection"]}, + fields={"exclude": ["bar"], "include": ["id", "collection"]}, ) assert search.get_parameters()["fields"] == { - "excludes": ["bar"], - "includes": ["id", "collection"], + "exclude": ["bar"], + "include": ["id", "collection"], } search = ItemSearch( @@ -500,7 +500,7 @@ def test_fields(self) -> None: search = ItemSearch( url=SEARCH_URL, method="GET", - fields={"excludes": ["bar"], "includes": ["id", "collection"]}, + fields={"exclude": ["bar"], "include": ["id", "collection"]}, ) assert search.get_parameters()["fields"] == "+id,+collection,-bar" @@ -835,3 +835,18 @@ def test_naive_datetime() -> None: method="POST", ) assert search.get_parameters()["datetime"] == "2024-05-14T04:25:42Z" + + +@pytest.mark.vcr +def test_fields() -> None: + search = ItemSearch( + url="https://earth-search.aws.element84.com/v1/search", + collections=["sentinel-2-c1-l2a"], + intersects={"type": "Point", "coordinates": [-105.1019, 40.1672]}, + max_items=1, + fields=["-geometry", "-assets", "-links"], + ) + item = next(search.items_as_dicts()) + assert "geometry" not in item + assert "assets" not in item + assert "links" not in item