Skip to content

Commit

Permalink
fix(wekeo-ecmwf): correct queryables (#1427)
Browse files Browse the repository at this point in the history
  • Loading branch information
alambare authored Jan 13, 2025
1 parent 419956b commit 7658679
Show file tree
Hide file tree
Showing 4 changed files with 391 additions and 925 deletions.
19 changes: 1 addition & 18 deletions eodag/api/product/metadata_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ def convert_get_hydrological_year(date: str):
date_object = datetime.strptime(utc_date, "%Y-%m-%dT%H:%M:%S.%fZ")
date_object_second_year = date_object + relativedelta(years=1)
return [
f'{date_object.strftime("%Y")}_{date_object_second_year.strftime("%y")}'
f"{date_object.strftime('%Y')}_{date_object_second_year.strftime('%y')}"
]

@staticmethod
Expand Down Expand Up @@ -1546,23 +1546,6 @@ def get_provider_queryable_key(
return eodag_key


def eodag_key_from_provider_key(
provider_key: str,
metadata_mapping: Dict[str, Union[List[Any], str]],
) -> str:
"""Get eodag key for provider key based on the metadata mapping if the provider key
appears in the metadata mapping, otherwise the provider key is returned
:param provider_key: name of the variable received from the provider
:param metadata_mapping: metadata mapping of the provider
:returns: eodag key
"""
for mm, mv in metadata_mapping.items():
if isinstance(mv, list) and len(mv) > 1 and provider_key == mv[0]:
return mm
return provider_key


# Keys taken from OpenSearch extension for Earth Observation http://docs.opengeospatial.org/is/13-026r9/13-026r9.html
# For a metadata to be queryable, The way to query it must be specified in the
# provider metadata_mapping configuration parameter. It will be automatically
Expand Down
48 changes: 32 additions & 16 deletions eodag/plugins/search/build_search_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
from eodag.api.product.metadata_mapping import (
NOT_AVAILABLE,
NOT_MAPPED,
eodag_key_from_provider_key,
format_metadata,
format_query_params,
mtd_cfg_as_conversion_and_querypath,
Expand Down Expand Up @@ -317,6 +316,11 @@ def _update_properties_from_element(
prop["description"] = description


def ecmwf_format(v: str) -> str:
"""Add ECMWF prefix to value v if v is a ECMWF keyword."""
return "ecmwf:" + v if v in ECMWF_KEYWORDS + COP_DS_KEYWORDS else v


class ECMWFSearch(PostJsonSearch):
"""ECMWF search plugin.
Expand Down Expand Up @@ -879,15 +883,11 @@ def queryables_by_form(
if default and prop["type"] == "string" and isinstance(default, list):
default = ",".join(default)

# rename keywords from form with metadata mapping.
# needed to map constraints like "xxxx" to eodag parameter "cop_cds:xxxx"
key = eodag_key_from_provider_key(name, self.config.metadata_mapping)

is_required = bool(element.get("required"))
if is_required:
required_list.append(name)

queryables[key] = Annotated[
queryables[ecmwf_format(name)] = Annotated[
get_args(
json_field_definition_to_python(
prop,
Expand Down Expand Up @@ -916,16 +916,13 @@ def queryables_by_values(
"""
# Rename keywords from form with metadata mapping.
# Needed to map constraints like "xxxx" to eodag parameter "ecmwf:xxxx"
required = [
eodag_key_from_provider_key(k, self.config.metadata_mapping)
for k in required_keywords
]
required = [ecmwf_format(k) for k in required_keywords]

queryables: Dict[str, Annotated[Any, FieldInfo]] = {}
for name, values in available_values.items():
# Rename keywords from form with metadata mapping.
# Needed to map constraints like "xxxx" to eodag parameter "ecmwf:xxxx"
key = eodag_key_from_provider_key(name, self.config.metadata_mapping)
key = ecmwf_format(name)

default = defaults.get(key)

Expand Down Expand Up @@ -1231,12 +1228,22 @@ def normalize_results(
:param kwargs: Search arguments
:returns: list of single :class:`~eodag.api.product._product.EOProduct`
"""

# formating of orderLink requires access to the productType value.
results.data = [
{**result, **results.product_type_def_params} for result in results
]

normalized = QueryStringSearch.normalize_results(self, results, **kwargs)

if len(normalized) > 0:
normalized[0].properties["_dc_qs"] = quote_plus(
orjson.dumps(results.query_params)
)
if not normalized:
return normalized

query_params_encoded = quote_plus(orjson.dumps(results.query_params))
for product in normalized:
properties = {**product.properties, **results.query_params}
properties["_dc_qs"] = query_params_encoded
product.properties = {ecmwf_format(k): v for k, v in properties.items()}

return normalized

Expand All @@ -1258,6 +1265,15 @@ def build_query_string(
:param kwargs: keyword arguments to be used in the query string
:return: formatted query params and encode query string
"""
# Reorder kwargs to make sure year/month/day/time if set overwrite default datetime.
# strip_quotes to remove duplicated quotes like "'1_1'" produced by convertors like to_geojson.
priority_keys = [
"startTimeFromAscendingNode",
"completionTimeFromAscendingNode",
]
ordered_kwargs = {k: kwargs[k] for k in priority_keys if k in kwargs}
ordered_kwargs.update({k: strip_quotes(v) for k, v in kwargs.items()})

return QueryStringSearch.build_query_string(
self, product_type=product_type, **kwargs
self, product_type=product_type, **ordered_kwargs
)
Loading

0 comments on commit 7658679

Please sign in to comment.