Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions eodag/api/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1879,10 +1879,10 @@ def _do_search(

search_result = search_plugin.query(prep, **search_params)

if not isinstance(search_result.data, list):
if not isinstance(search_result, SearchResult):
raise PluginImplementationError(
"The query function of a Search plugin must return a list of "
"results, got {} instead".format(type(search_result.data))
"The query function of a Search plugin must return a SearchResult "
"results, got {} instead".format(type(search_result))
)
# Filter and attach to each eoproduct in the result the plugin capable of
# downloading it (this is done to enable the eo_product to download itself
Expand All @@ -1893,7 +1893,7 @@ def _do_search(
# WARNING: this means an eo_product that has an invalid geometry can still
# be returned as a search result if there was no search extent (because we
# will not try to do an intersection)
for eo_product in search_result.data:
for eo_product in search_result:
# if collection is not defined, try to guess using properties
if eo_product.collection is None:
pattern = re.compile(r"[^\w,]+")
Expand Down
4 changes: 3 additions & 1 deletion eodag/api/product/metadata_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,10 @@ def get_value(
"""
if isinstance(key, str):
original_key = key.replace("__", ":")
key_with_COLON = key.replace("__", "_COLON_")
result = kwargs.get(original_key)
if result is not None:
return result
key_with_COLON = key.replace("__", "_COLON_")
return kwargs.get(key_with_COLON)
return super().get_value(key, args, kwargs)

Expand Down Expand Up @@ -963,6 +963,8 @@ def convert_interval_to_datetime_dict(
start_date_object = datetime.strptime(
start_utc_date, "%Y-%m-%dT%H:%M:%S.%fZ"
)
if end_utc_date == "None":
end_utc_date = start_utc_date
end_date_object = datetime.strptime(end_utc_date, "%Y-%m-%dT%H:%M:%S.%fZ")

delta_utc_date = end_date_object - start_date_object
Expand Down
3 changes: 0 additions & 3 deletions eodag/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,6 @@ class MetadataPreMapping(TypedDict, total=False):
#: Maximum number of connections for concurrent HTTP requests
max_connections: int
#: :class:`~eodag.plugins.search.build_search_result.ECMWFSearch`
#: if date parameters are mandatory in the request
dates_required: bool
#: :class:`~eodag.plugins.search.build_search_result.ECMWFSearch`
#: Whether end date should be excluded from search request or not
end_date_excluded: bool
#: :class:`~eodag.plugins.search.build_search_result.ECMWFSearch`
Expand Down
15 changes: 0 additions & 15 deletions eodag/plugins/apis/ecmwf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import logging
import os
from datetime import datetime, timezone
from typing import TYPE_CHECKING, Annotated

import geojson
Expand All @@ -35,8 +34,6 @@
from eodag.utils import (
DEFAULT_DOWNLOAD_TIMEOUT,
DEFAULT_DOWNLOAD_WAIT,
DEFAULT_MISSION_START_DATE,
get_collection_dates,
get_geometry_from_various,
path_to_uri,
sanitize,
Expand Down Expand Up @@ -135,18 +132,6 @@ def query(
kwargs.get("ecmwf:levtype", ""),
)

col_start, col_end = get_collection_dates(
getattr(self.config, "collection_config", {})
)
# start date
if "start_datetime" not in kwargs:
kwargs["start_datetime"] = col_start or DEFAULT_MISSION_START_DATE
# end date
if "end_datetime" not in kwargs:
kwargs["end_datetime"] = col_end or datetime.now(timezone.utc).isoformat(
timespec="seconds"
)

# geometry
if "geometry" in kwargs:
kwargs["geometry"] = get_geometry_from_various(geometry=kwargs["geometry"])
Expand Down
112 changes: 61 additions & 51 deletions eodag/plugins/search/build_search_result.py
Comment thread
pdavid-cssopra marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import orjson
from dateutil.parser import isoparse
from dateutil.tz import tzutc
from dateutil.utils import today
from pydantic import AliasChoices
from pydantic.fields import FieldInfo
from requests.auth import AuthBase
Expand All @@ -52,7 +51,6 @@
from eodag.types import json_field_definition_to_python # noqa: F401
from eodag.types.queryables import Queryables, QueryablesDict
from eodag.utils import (
DEFAULT_MISSION_START_DATE,
DEFAULT_SEARCH_TIMEOUT,
deepcopy,
dict_items_recursive_sort,
Expand All @@ -66,10 +64,13 @@
from eodag.utils.dates import (
COMPACT_DATE_RANGE_PATTERN,
DATE_RANGE_PATTERN,
compute_date_range_from_params,
format_date,
is_range_in_range,
parse_date,
parse_year_month_day,
time_values_to_hhmm,
validate_datetime_param,
)
from eodag.utils.exceptions import DownloadError, NotAvailableError, ValidationError
from eodag.utils.requests import fetch_json
Expand Down Expand Up @@ -395,7 +396,6 @@ class ECMWFSearch(PostJsonSearch):
used to parse metadata but that must not be included to the query
* :attr:`~eodag.config.PluginConfig.end_date_excluded` (``bool``): Set to `False` if
provider does not include end date to search
* :attr:`~eodag.config.PluginConfig.dates_required` (``bool``): if date parameters are mandatory in the request
* :attr:`~eodag.config.PluginConfig.discover_queryables`
(:class:`~eodag.config.PluginConfig.DiscoverQueryables`): configuration to fetch the queryables from a
provider queryables endpoint; It has the following keys:
Expand Down Expand Up @@ -566,17 +566,23 @@ def _preprocess_search_params(
if v is not None
}

# dates
# check if default dates have to be added
if getattr(self.config, "dates_required", False):
self._check_date_params(params, collection)

# read 'start_datetime' and 'end_datetime' from 'date' range
if "date" in params:
start_date, end_date = parse_date(params["date"])
params[START] = format_date(start_date)
params[END] = format_date(end_date)

# start_datetime / computed from "date", "time", "year", "month", "day"
indirects = self._preprocess_indirect_date_parameters(params)
if params.get(START) is None:
value = indirects.get("start_datetime", None)
if value is not None:
params[START] = value
if params.get(END) is None:
value = indirects.get("end_datetime", None)
if value is not None:
params[END] = value

# adapt end date if it is midnight
if END in params:
end_date_excluded = getattr(self.config, "end_date_excluded", True)
Expand Down Expand Up @@ -623,51 +629,55 @@ def _preprocess_search_params(

return params

def _check_date_params(
self, keywords: dict[str, Any], collection: Optional[str]
) -> None:
"""checks if start and end date are present in the keywords and adds them if not"""

if START in keywords and END in keywords:
return
def _preprocess_indirect_date_parameters(self, params: dict[str, Any]) -> dict:
"""
Compute start_datetime / end_datetime from "date", "time", "year", "month", "day"
"""
indirects: dict[str, Any] = {}

collection_conf = getattr(self.config, "metadata_mapping", {})
if (
collection
and collection in self.config.products
and "metadata_mapping" in self.config.products[collection]
):
collection_conf = self.config.products[collection]["metadata_mapping"]

# start time given, end time missing
if START in keywords:
keywords[END] = (
keywords[START]
if END in collection_conf
# else self.get_collection_cfg_value(
else self.get_collection_cfg_dates(None, today().isoformat())[1]
)
return

if END in collection_conf:
mapping = collection_conf[START]
if not isinstance(mapping, list):
mapping = collection_conf[END]
if isinstance(mapping, list):
# if startTime is not given but other time params (e.g. year/month/(day)) are given,
# no default date is required
start, end = ecmwf_temporal_to_eodag(keywords)
if start is None:
col_start, col_end = self.get_collection_cfg_dates(
DEFAULT_MISSION_START_DATE, today().isoformat()
)
keywords[START] = col_start
keywords[END] = (
keywords[START] if END in collection_conf else col_end
# Validate and collect indirect date parameters
time = validate_datetime_param(
params.get("time"), "time", ["%H%M", "%H:%M", "%H%M%S", "%H:%M:%S"]
)
year = validate_datetime_param(params.get("year"), "year", ["%Y"])
month = validate_datetime_param(params.get("month"), "month", ["%m"])
day = validate_datetime_param(params.get("day"), "day", ["%d"])

if time is not None:
time = time_values_to_hhmm(time)
indirects["time"] = time
if year is not None:
indirects["year"] = year
if month is not None:
indirects["month"] = month
if day is not None:
indirects["day"] = day

# Compute date range from "date" param (takes precedence)
date = params.get("date", None)
if date is not None:
try:
start, end = compute_date_range_from_params(date=date, time=time)
indirects["start_datetime"] = start
indirects["end_datetime"] = end
return indirects
except Exception as e:
raise ValidationError(
'Malformed parameter "date" (date given "{}", time given: "{}"): {}'.format(
params.get("date"), params.get("time"), str(e)
)
else:
keywords[START] = start
keywords[END] = end
)

# Compute date range from year/month/day/time params
start, end = compute_date_range_from_params(
year=year, month=month, day=day, time=time
)
if start is not None:
indirects["start_datetime"] = start
if end is not None:
indirects["end_datetime"] = end

return indirects

def _get_collection_queryables(
self, collection: Optional[str], alias: Optional[str], filters: dict[str, Any]
Expand Down
5 changes: 5 additions & 0 deletions eodag/plugins/search/qssearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,11 @@ def query(

qp, _ = self.build_query_string(collection, keywords)

# Force sort qp list parameters
for key in qp:
if isinstance(qp[key], list):
qp[key].sort()

for query_param, query_value in qp.items():
if (
query_param
Expand Down
2 changes: 0 additions & 2 deletions eodag/resources/providers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4424,7 +4424,6 @@
type: ECMWFSearch
need_auth: true
ssl_verify: true
dates_required: True
discover_queryables:
fetch_url: null
collection_fetch_url: null
Expand Down Expand Up @@ -4622,7 +4621,6 @@
type: ECMWFSearch
need_auth: true
ssl_verify: true
dates_required: True
discover_queryables:
fetch_url: null
collection_fetch_url: null
Expand Down
Loading
Loading