diff --git a/CHANGELOG.md b/CHANGELOG.md index 79fd3a7..7b589a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,14 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --> ----- +## [1.0.21](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.20...v1.0.21) +### Changed +- bump asf-search to v14.0.1 + - `SMAP` product type aliases + - `collectionName` and `conceptID` to general jsonlite output +### Fixed +- boolean keywords (`jointObservation`, `collectionAlias`) are parsed from strings, so `false` is no longer treated as true +----- ## [1.0.20](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.19...v1.0.20) ### Changed - bump asf-search to v14.0.0 diff --git a/requirements.txt b/requirements.txt index d7140a5..e65c2a0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,7 +22,7 @@ ujson==5.7.0 uvicorn==0.21.1 watchfiles==0.19.0 -asf-search[asf-enumeration]==14.0.0 +asf-search[asf-enumeration]==14.0.1 python-json-logger==2.0.7 pyshp==2.1.3 diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index 245ef3d..b7e198d 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -59,6 +59,16 @@ def string_to_num_or_range_list(v: Union[str, list]): return v_list +def string_to_bool(v: Union[str, bool]) -> bool: + if not isinstance(v, str): + return bool(v) + if v.lower() == "true": + return True + if v.lower() == "false": + return False + raise ValueError(f"Invalid boolean: {v}") + + string_to_obj_map = { # Range only: asf.validators.parse_date_range: string_to_range, @@ -75,6 +85,8 @@ def string_to_num_or_range_list(v: Union[str, list]): # Number or Range-list: asf.validators.parse_int_or_range_list: string_to_num_or_range_list, asf.validators.parse_float_or_range_list: string_to_num_or_range_list, + # Boolean only: + bool: string_to_bool, } diff --git a/tests/unit/test_asf_opts.py b/tests/unit/test_asf_opts.py new file mode 100644 index 0000000..8074b7d --- /dev/null +++ b/tests/unit/test_asf_opts.py @@ -0,0 +1,26 @@ +import pytest +from fastapi import HTTPException + +from SearchAPI.application.asf_opts import get_asf_opts, string_to_bool + + +def test_string_to_bool(): + assert string_to_bool('true') is True + assert string_to_bool('False') is False + assert string_to_bool(True) is True + + with pytest.raises(ValueError): + string_to_bool('asdf') + + +def test_bool_keywords_from_strings(): + assert get_asf_opts({'jointObservation': 'true'}).jointObservation is True + assert get_asf_opts({'jointObservation': 'false'}).jointObservation is False + assert get_asf_opts({'collectionAlias': 'false'}).collectionAlias is False + + +def test_invalid_bool_keyword_is_400(): + with pytest.raises(HTTPException) as exc: + get_asf_opts({'jointObservation': 'asdf'}) + + assert exc.value.status_code == 400 diff --git a/tests/yml_tests/test_URLs.yml b/tests/yml_tests/test_URLs.yml index b2c0f33..0802aae 100644 --- a/tests/yml_tests/test_URLs.yml +++ b/tests/yml_tests/test_URLs.yml @@ -306,6 +306,14 @@ tests: expected file: count expected code: 200 +- jointObservation false count: + dataset: NISAR + jointObservation: "false" + output: count + + expected file: count + expected code: 200 + - flightDirection A: flightDirection: A maxresults: 10 diff --git a/tests/yml_tests/test_URLs_expected_400.yml b/tests/yml_tests/test_URLs_expected_400.yml index 7437ee8..6e570ef 100644 --- a/tests/yml_tests/test_URLs_expected_400.yml +++ b/tests/yml_tests/test_URLs_expected_400.yml @@ -20,6 +20,14 @@ tests: expected file: error json expected code: 400 +- jointObservation invalid bool: + jointObservation: asdf + dataset: NISAR + output: count + + expected file: error json + expected code: 400 + - blank keyword invalid: platform: null output: csv