Skip to content

Commit f296c52

Browse files
sbrunatoanesson-csalambarejlahovnik
authored
feat(plugins): EcmwfSearch search-by-id (#1580)
Co-authored-by: Augustin Nesson <[email protected]> Co-authored-by: Aubin Lambaré <[email protected]> Co-authored-by: jlahovnik <[email protected]>
1 parent 6af7ce4 commit f296c52

16 files changed

+757
-157
lines changed

eodag/api/core.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,7 @@ def _search_by_id(
15991599
if kwargs.get("raise_errors"):
16001600
raise
16011601
logger.warning(e)
1602+
results.errors.append((plugin.provider, e))
16021603
continue
16031604

16041605
# try using crunch to get unique result
@@ -1622,7 +1623,7 @@ def _search_by_id(
16221623
"Several products found for this id (%s). You may try searching using more selective criteria.",
16231624
results,
16241625
)
1625-
return SearchResult([], 0)
1626+
return SearchResult([], 0, results.errors)
16261627

16271628
def _fetch_external_product_type(self, provider: str, product_type: str):
16281629
plugins = self._plugins_manager.get_search_plugins(provider=provider)

eodag/api/search_result.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ def _repr_html_(self):
193193
<details><summary style='color: grey; font-family: monospace;'>
194194
{i}&ensp;
195195
{type(p).__name__}(id=<span style='color: black;'>{
196-
p.properties['id']
197-
}</span>, provider={p.provider})
196+
p.properties["id"]
197+
}</span>, provider={p.provider})
198198
</summary>
199199
{p._repr_html_()}
200200
</details>
@@ -214,13 +214,12 @@ def extend(self, other: Iterable) -> None:
214214
return super().extend(other)
215215

216216

217-
class RawSearchResult(UserList):
217+
class RawSearchResult(UserList[dict[str, Any]]):
218218
"""An object representing a collection of raw/unparsed search results obtained from a provider.
219219
220220
:param results: A list of raw/unparsed search results
221221
"""
222222

223-
data: list[Any]
224223
query_params: dict[str, Any]
225224
product_type_def_params: dict[str, Any]
226225

eodag/plugins/download/http.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def _order(
216216
product.properties["storageStatus"] = STAGING_STATUS
217217
except RequestException as e:
218218
self._check_auth_exception(e)
219-
msg = f'{product.properties["title"]} could not be ordered'
219+
msg = f"{product.properties['title']} could not be ordered"
220220
if e.response is not None and e.response.status_code == 400:
221221
raise ValidationError.from_error(e, msg) from e
222222
else:
@@ -255,6 +255,16 @@ def order_response_process(
255255
product.properties.update(
256256
{k: v for k, v in properties_update.items() if v != NOT_AVAILABLE}
257257
)
258+
# the job id becomes the product id for EcmwfSearch products
259+
if "ORDERABLE" in product.properties.get("id", ""):
260+
product.properties["id"] = product.properties.get(
261+
"orderId", product.properties["id"]
262+
)
263+
product.properties["title"] = (
264+
(product.product_type or product.provider).upper()
265+
+ "_"
266+
+ product.properties["id"]
267+
)
258268
if "downloadLink" in product.properties:
259269
product.remote_location = product.location = product.properties[
260270
"downloadLink"
@@ -390,7 +400,10 @@ def _request(
390400
# success and no need to get status response content
391401
skip_parsing_status_response = True
392402
except RequestException as e:
393-
msg = f'{product.properties["title"]} order status could not be checked'
403+
msg = (
404+
f"{product.properties.get('title') or product.properties.get('id') or product} "
405+
"order status could not be checked"
406+
)
394407
if e.response is not None and e.response.status_code == 400:
395408
raise ValidationError.from_error(e, msg) from e
396409
else:
@@ -426,23 +439,29 @@ def _request(
426439
f"{product.properties['title']} order status: {status_percent}"
427440
)
428441

429-
status_message = status_dict.get("message")
442+
product.properties.update(
443+
{k: v for k, v in status_dict.items() if v != NOT_AVAILABLE}
444+
)
445+
430446
product.properties["orderStatus"] = status_dict.get("status")
431447

448+
status_message = status_dict.get("message")
449+
432450
# handle status error
433451
errors: dict[str, Any] = status_config.get("error", {})
434452
if errors and errors.items() <= status_dict.items():
435453
raise DownloadError(
436454
f"Provider {product.provider} returned: {status_dict.get('error_message', status_message)}"
437455
)
438456

457+
product.properties["storageStatus"] = STAGING_STATUS
458+
439459
success_status: dict[str, Any] = status_config.get("success", {}).get("status")
440460
# if not success
441461
if (success_status and success_status != status_dict.get("status")) or (
442462
success_code and success_code != response.status_code
443463
):
444-
error = NotAvailableError(status_message)
445-
raise error
464+
return None
446465

447466
product.properties["storageStatus"] = ONLINE_STATUS
448467

@@ -461,7 +480,11 @@ def _request(
461480
product.properties["title"],
462481
e,
463482
)
464-
return None
483+
msg = f"{product.properties['title']} order status could not be checked"
484+
if e.response is not None and e.response.status_code == 400:
485+
raise ValidationError.from_error(e, msg) from e
486+
else:
487+
raise DownloadError.from_error(e, msg) from e
465488

466489
result_type = config_on_success.get("result_type", "json")
467490
result_entry = config_on_success.get("results_entry")
@@ -626,6 +649,8 @@ def download_request(
626649
if fs_path is not None:
627650
ext = Path(product.filename).suffix
628651
path = Path(fs_path).with_suffix(ext)
652+
if "ORDERABLE" in path.stem and product.properties.get("title"):
653+
path = path.with_stem(sanitize(product.properties["title"]))
629654

630655
with open(path, "wb") as fhandle:
631656
for chunk in chunk_iterator:
@@ -961,17 +986,21 @@ def _stream_download(
961986
auth = None
962987

963988
s = requests.Session()
964-
self.stream = s.request(
965-
req_method,
966-
req_url,
967-
stream=True,
968-
auth=auth,
969-
params=params,
970-
headers=USER_AGENT,
971-
timeout=DEFAULT_STREAM_REQUESTS_TIMEOUT,
972-
verify=ssl_verify,
973-
**req_kwargs,
974-
)
989+
try:
990+
self.stream = s.request(
991+
req_method,
992+
req_url,
993+
stream=True,
994+
auth=auth,
995+
params=params,
996+
headers=USER_AGENT,
997+
timeout=DEFAULT_STREAM_REQUESTS_TIMEOUT,
998+
verify=ssl_verify,
999+
**req_kwargs,
1000+
)
1001+
except requests.exceptions.MissingSchema:
1002+
# location is not a valid url -> product is not available yet
1003+
raise NotAvailableError("Product is not available yet")
9751004
try:
9761005
self.stream.raise_for_status()
9771006
except requests.exceptions.Timeout as exc:

0 commit comments

Comments
 (0)