Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat[server]: add cql2 support #966

Merged
merged 44 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
da0cd4c
feat(server): add cql2-json support on post request
alambare Dec 12, 2023
f831ea6
feat: init search model
alambare Dec 12, 2023
636d840
update tests and reorganize code in rest
alambare Dec 19, 2023
4dc21ea
fix: search by id
alambare Dec 19, 2023
2fb68a4
test: fix tests
alambare Dec 19, 2023
ab1cca4
refactor: remove obsolet methods
alambare Dec 19, 2023
92bacf0
style: fix linter issues
alambare Dec 19, 2023
cd6741d
build: add packages iso8601 and pygeofilter
alambare Dec 19, 2023
0c67915
fix: python3.8 + deprecation warnings
alambare Dec 19, 2023
a39ce90
fix: use standard eodag date field names
alambare Dec 19, 2023
10f7c96
fix: missing provider param with get_stac_item_by_id
alambare Dec 20, 2023
713e507
fix: correct productType in download_stac_item_by_id_stream
alambare Dec 19, 2023
1a37ad6
test: update tests
alambare Dec 20, 2023
ce2ee3d
refactor[server]: use search_stac_items for all search operations
alambare Jan 11, 2024
156c249
test: remove obsolet queryable tests
alambare Jan 11, 2024
9d88f4b
fix: use start and end instead of the properties
alambare Jan 11, 2024
0dc8a8f
feat: add get_search cql support + update swagger
alambare Jan 11, 2024
f5d3822
fix: add missing license file + correct test mock properties
alambare Jan 12, 2024
40aa187
fix: correct cql2-text to cql2-json
alambare Jan 12, 2024
6950c48
fix: correct POST search error messages
alambare Jan 12, 2024
df795d7
fix: allow filter-lang without filter
alambare Jan 13, 2024
80b7816
fix: add missing translation pieces with datetime
alambare Jan 13, 2024
e251ef0
refactor: break down download_stac_item_by_id_stream
alambare Jan 19, 2024
aef443c
fix: add thumbnail in stac item only when not None
alambare Jan 19, 2024
8f691e5
feat: guess assets mime type
alambare Jan 19, 2024
5cea796
test: fix tests
alambare Jan 19, 2024
27972cd
fix: remove none values from body log
alambare Jan 19, 2024
293a87c
feat: update comformance classes
alambare Jan 19, 2024
b7faf55
feat: raise errors in search
alambare Jan 19, 2024
aebd9df
fix: creodias_s3 download return type + simplifications in rest download
alambare Feb 2, 2024
6fbaacf
refactor: simplify download, update tests
alambare Feb 2, 2024
335f40a
fix: bring back get_datetime for queryables
alambare Feb 19, 2024
8928c14
fix: add missing import
alambare Feb 23, 2024
3158f19
fix: use dateutil instead of iso8601
alambare Feb 26, 2024
0a8653e
fix: small fixes
alambare Feb 26, 2024
18d3e59
fix: improve error handling in eodag_search
alambare Feb 26, 2024
1c87ed5
test[servver]: add cql2-json tests
alambare Feb 27, 2024
5c572e8
docs: add pygeofilter to NOTICE
alambare Feb 27, 2024
1371d97
fix: solidify cql evaluator + improve error returned
alambare Feb 27, 2024
993516f
refactor: remove not required dependencies
alambare Feb 28, 2024
857beda
fix: define parameters on /items
alambare Feb 28, 2024
d480086
docs(server): updated search description
sbrunato Feb 29, 2024
ba48873
feat: implement operator 'in' on query extension
alambare Feb 29, 2024
47421c1
feat: add query and filter extensions on item_collection endpoint
alambare Feb 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ https://github.com/tiangolo/fastapi
https://github.com/urllib3/urllib3
https://github.com/annotated-types/annotated-types
https://github.com/pypa/setuptools
https://github.com/pydantic/pydantic
https://github.com/pydantic/pydantic-core
https://github.com/geopython/pygeofilter


================================================================
Expand Down
5 changes: 2 additions & 3 deletions eodag/api/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ def list_product_types(
if product_type_id == GENERIC_PRODUCT_TYPE:
continue
config = self.product_types_config[product_type_id]
config["_id"] = product_type_id
if "alias" in config:
config["_id"] = product_type_id
product_type_id = config["alias"]
product_type = dict(ID=product_type_id, **config)
if product_type_id not in product_types:
Expand Down Expand Up @@ -1618,8 +1618,7 @@ def _prepare_search(
for p in self.list_product_types(
search_plugin.provider, fetch_providers=False
)
if p["ID"] == product_type
or ("_id" in p and p["_id"] == product_type)
if p["_id"] == product_type
][0],
**{"productType": product_type},
)
Expand Down
3 changes: 2 additions & 1 deletion eodag/plugins/apis/cds.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
DEFAULT_ITEMS_PER_PAGE,
DEFAULT_PAGE,
Annotated,
StreamResponse,
datetime_range,
deepcopy,
get_geometry_from_various,
Expand Down Expand Up @@ -403,7 +404,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
"""Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers."""

Expand Down
7 changes: 4 additions & 3 deletions eodag/plugins/download/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
HTTP_REQ_TIMEOUT,
USER_AGENT,
ProgressCallback,
StreamResponse,
flatten_top_directories,
get_bucket_name_and_prefix,
path_to_uri,
Expand Down Expand Up @@ -631,7 +632,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers.
Expand Down Expand Up @@ -725,11 +726,11 @@ def _stream_download_dict(
if assets_values[0].get("type", None):
headers["content-type"] = assets_values[0]["type"]

return dict(
return StreamResponse(
content=chain(iter([first_chunks_tuple]), chunks_tuples),
headers=headers,
)
return dict(
return StreamResponse(
content=stream_zip(chunks_tuples),
media_type="application/zip",
headers={
Expand Down
3 changes: 2 additions & 1 deletion eodag/plugins/download/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
DEFAULT_DOWNLOAD_TIMEOUT,
DEFAULT_DOWNLOAD_WAIT,
ProgressCallback,
StreamResponse,
sanitize,
uri_to_path,
)
Expand Down Expand Up @@ -150,7 +151,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Base _stream_download_dict method. Not available, it must be defined for each plugin.

Expand Down
9 changes: 5 additions & 4 deletions eodag/plugins/download/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
HTTP_REQ_TIMEOUT,
USER_AGENT,
ProgressCallback,
StreamResponse,
flatten_top_directories,
parse_header,
path_to_uri,
Expand Down Expand Up @@ -535,7 +536,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers.
Expand Down Expand Up @@ -584,7 +585,7 @@ def _stream_download_dict(
"type"
]

return dict(
return StreamResponse(
content=chain(iter([first_chunks_tuple]), chunks_tuples),
headers=assets_values[0].headers,
)
Expand All @@ -595,7 +596,7 @@ def _stream_download_dict(
if "title" in product.properties
else sanitize(product.properties.get("id", "download"))
)
return dict(
return StreamResponse(
content=stream_zip(chunks_tuples),
media_type="application/zip",
headers={
Expand All @@ -612,7 +613,7 @@ def _stream_download_dict(
# start reading chunks to set product.headers
first_chunk = next(chunks)

return dict(
return StreamResponse(
content=chain(iter([first_chunk]), chunks),
headers=product.headers,
)
Expand Down
10 changes: 5 additions & 5 deletions eodag/plugins/search/creodias_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from eodag.config import PluginConfig
from eodag.plugins.authentication.aws_auth import AwsAuth
from eodag.plugins.search.qssearch import QueryStringSearch
from eodag.utils import guess_file_type
from eodag.utils.exceptions import AuthenticationError, MisconfiguredError, RequestError

DATA_EXTENSIONS = ["jp2", "tiff", "nc", "grib"]
Expand Down Expand Up @@ -75,7 +76,7 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
endpoint_url=config.base_uri,
**auth_dict,
)
logger.debug(f"Listing assets in {prefix}")
logger.debug("Listing assets in %s", prefix)
product.assets = AssetsDict(product)
for asset in auth.s3_client.list_objects(
Bucket=config.s3_bucket, Prefix=prefix, MaxKeys=300
Expand All @@ -96,6 +97,8 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
"roles": [role],
"href": f"s3://{config.s3_bucket}/{asset['Key']}",
}
if mime_type := guess_file_type(asset["Key"]):
product.assets[asset_basename]["type"] = mime_type
# update driver
product.driver = product.get_driver()

Expand All @@ -104,10 +107,7 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
raise AuthenticationError(
f"Authentication failed on {config.base_uri} s3"
) from e
else:
raise RequestError(
"assets for product %s could not be found", prefix
) from e
raise RequestError(f"assets for product {prefix} could not be found") from e


class CreodiasS3Search(QueryStringSearch):
Expand Down
52 changes: 22 additions & 30 deletions eodag/resources/stac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# limitations under the License.

stac_version: 1.0.0
stac_api_version: 1.0.0-rc.3
stac_api_version: 1.0.0

# Capabilities ----------------------------------------------------------------

Expand Down Expand Up @@ -53,13 +53,26 @@ landing_page:
# http://docs.opengeospatial.org/is/17-069r3/17-069r3.html#_declaration_of_conformance_classes
conformance:
conformsTo:
- https://api.stacspec.org/v1.0.0-rc.3/core
- https://api.stacspec.org/v1.0.0-rc.3/item-search
- https://api.stacspec.org/v1.0.0-rc.3/ogcapi-features
- https://api.stacspec.org/v1.0.0-rc.3/collections
- https://api.stacspec.org/v1.0.0/core
- https://api.stacspec.org/v1.0.0/item-search
- https://api.stacspec.org/v1.0.0/item-search#query
- https://api.stacspec.org/v1.0.0/item-search#filter
- https://api.stacspec.org/v1.0.0/item-search#sort
- https://api.stacspec.org/v1.0.0/ogcapi-features
- https://api.stacspec.org/v1.0.0/ogcapi-features#query
- https://api.stacspec.org/v1.0.0/ogcapi-features#sort
- https://api.stacspec.org/v1.0.0/collections
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson
- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/filter
- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/features-filter
- http://www.opengis.net/spec/cql2/1.0/conf/cql2-text
- http://www.opengis.net/spec/cql2/1.0/conf/cql2-json
- http://www.opengis.net/spec/cql2/1.0/conf/basic-cql2
- http://www.opengis.net/spec/cql2/1.0/conf/basic-spatial-operators
- http://www.opengis.net/spec/cql2/1.0/conf/temporal-operators
- http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators

# https://stacspec.org/STAC-api.html#operation/getCollections
collections:
Expand Down Expand Up @@ -147,20 +160,12 @@ items:
- rel: parent
title: "{catalog[id]}"
href: "{catalog[url]}"
# implement next/prev page links
# https://github.com/radiantearth/stac-spec/blob/master/api-spec/api-spec.md#paging-extension
- rel: next
href: '$.search_results.next'
title: Next page
type: application/geo+json
method: '$.search_results.method'
body: '$.search_results.body'
# time and date when the response was generated
timeStamp: '$.search_results.timeStamp'
timeStamp: '$.timeStamp'
# count request result
numberMatched: '$.search_results.numberMatched'
numberMatched: '$.numberMatched'
# len(features)
numberReturned: '$.search_results.numberReturned'
numberReturned: '$.numberReturned'

# https://stacspec.org/STAC-api.html#operation/getFeature
item:
Expand Down Expand Up @@ -216,20 +221,7 @@ item:
- rel: collection
title: "{item[collection]}"
href: "{catalog[url]}"
assets:
downloadLink:
title: 'Download link'
href: "{catalog[url]}/items/{item[id]}/download"
# https://github.com/radiantearth/stac-spec/blob/master/item-spec/item-spec.md#media-types
type: 'application/zip'
_dc_qs: '$.product.properties._dc_qs'
thumbnail:
title: 'Thumbnail'
href: '$.product.properties.quicklook'
type: 'image/jpeg'
role: thumbnail
# https://github.com/radiantearth/stac-spec/blob/master/item-spec/item-spec.md#media-types
origin_assets: '$.product.assets'

# product properties not needed in items
metadata_ignore:
- title
Expand Down
Loading
Loading