eodag 3.0.0b3__py3-none-any.whl → 3.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eodag/api/core.py +189 -125
- eodag/api/product/metadata_mapping.py +12 -3
- eodag/api/search_result.py +29 -3
- eodag/cli.py +35 -19
- eodag/config.py +412 -116
- eodag/plugins/apis/base.py +10 -4
- eodag/plugins/apis/ecmwf.py +14 -4
- eodag/plugins/apis/usgs.py +25 -2
- eodag/plugins/authentication/aws_auth.py +14 -5
- eodag/plugins/authentication/base.py +10 -1
- eodag/plugins/authentication/generic.py +14 -3
- eodag/plugins/authentication/header.py +12 -4
- eodag/plugins/authentication/keycloak.py +41 -22
- eodag/plugins/authentication/oauth.py +11 -1
- eodag/plugins/authentication/openid_connect.py +178 -163
- eodag/plugins/authentication/qsauth.py +12 -4
- eodag/plugins/authentication/sas_auth.py +19 -2
- eodag/plugins/authentication/token.py +57 -10
- eodag/plugins/authentication/token_exchange.py +19 -19
- eodag/plugins/crunch/base.py +4 -1
- eodag/plugins/crunch/filter_date.py +5 -2
- eodag/plugins/crunch/filter_latest_intersect.py +5 -4
- eodag/plugins/crunch/filter_latest_tpl_name.py +1 -1
- eodag/plugins/crunch/filter_overlap.py +5 -7
- eodag/plugins/crunch/filter_property.py +4 -3
- eodag/plugins/download/aws.py +39 -22
- eodag/plugins/download/base.py +11 -11
- eodag/plugins/download/creodias_s3.py +11 -2
- eodag/plugins/download/http.py +86 -52
- eodag/plugins/download/s3rest.py +20 -18
- eodag/plugins/manager.py +168 -23
- eodag/plugins/search/base.py +33 -14
- eodag/plugins/search/build_search_result.py +55 -51
- eodag/plugins/search/cop_marine.py +112 -29
- eodag/plugins/search/creodias_s3.py +20 -5
- eodag/plugins/search/csw.py +41 -1
- eodag/plugins/search/data_request_search.py +109 -9
- eodag/plugins/search/qssearch.py +532 -152
- eodag/plugins/search/static_stac_search.py +20 -21
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +187 -56
- eodag/resources/providers.yml +1610 -1701
- eodag/resources/stac.yml +3 -163
- eodag/resources/user_conf_template.yml +112 -97
- eodag/rest/config.py +1 -2
- eodag/rest/constants.py +0 -1
- eodag/rest/core.py +61 -51
- eodag/rest/errors.py +181 -0
- eodag/rest/server.py +24 -325
- eodag/rest/stac.py +93 -544
- eodag/rest/types/eodag_search.py +13 -8
- eodag/rest/types/queryables.py +1 -2
- eodag/rest/types/stac_search.py +11 -2
- eodag/types/__init__.py +15 -3
- eodag/types/download_args.py +1 -1
- eodag/types/queryables.py +1 -2
- eodag/types/search_args.py +3 -3
- eodag/utils/__init__.py +77 -57
- eodag/utils/exceptions.py +23 -9
- eodag/utils/logging.py +37 -77
- eodag/utils/requests.py +1 -3
- eodag/utils/stac_reader.py +1 -1
- {eodag-3.0.0b3.dist-info → eodag-3.0.1.dist-info}/METADATA +11 -12
- eodag-3.0.1.dist-info/RECORD +109 -0
- {eodag-3.0.0b3.dist-info → eodag-3.0.1.dist-info}/WHEEL +1 -1
- {eodag-3.0.0b3.dist-info → eodag-3.0.1.dist-info}/entry_points.txt +1 -0
- eodag/resources/constraints/climate-dt.json +0 -13
- eodag/resources/constraints/extremes-dt.json +0 -8
- eodag-3.0.0b3.dist-info/RECORD +0 -110
- {eodag-3.0.0b3.dist-info → eodag-3.0.1.dist-info}/LICENSE +0 -0
- {eodag-3.0.0b3.dist-info → eodag-3.0.1.dist-info}/top_level.txt +0 -0
|
@@ -41,6 +41,7 @@ import geojson
|
|
|
41
41
|
import orjson
|
|
42
42
|
import pyproj
|
|
43
43
|
from dateutil.parser import isoparse
|
|
44
|
+
from dateutil.relativedelta import relativedelta
|
|
44
45
|
from dateutil.tz import UTC, tzutc
|
|
45
46
|
from jsonpath_ng.jsonpath import Child, JSONPath
|
|
46
47
|
from lxml import etree
|
|
@@ -152,7 +153,7 @@ def get_search_param(map_value: List[str]) -> str:
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
def format_metadata(search_param: str, *args: Any, **kwargs: Any) -> str:
|
|
155
|
-
"""Format a string of form {<field_name>#<conversion_function>}
|
|
156
|
+
"""Format a string of form ``{<field_name>#<conversion_function>}``
|
|
156
157
|
|
|
157
158
|
The currently understood converters are:
|
|
158
159
|
- ``datetime_to_timestamp_milliseconds``: converts a utc date string to a timestamp in
|
|
@@ -831,7 +832,7 @@ def format_metadata(search_param: str, *args: Any, **kwargs: Any) -> str:
|
|
|
831
832
|
def convert_get_hydrological_year(date: str):
|
|
832
833
|
utc_date = MetadataFormatter.convert_to_iso_utc_datetime(date)
|
|
833
834
|
date_object = datetime.strptime(utc_date, "%Y-%m-%dT%H:%M:%S.%fZ")
|
|
834
|
-
date_object_second_year = date_object +
|
|
835
|
+
date_object_second_year = date_object + relativedelta(years=1)
|
|
835
836
|
return [
|
|
836
837
|
f'{date_object.strftime("%Y")}_{date_object_second_year.strftime("%y")}'
|
|
837
838
|
]
|
|
@@ -1208,7 +1209,7 @@ def mtd_cfg_as_conversion_and_querypath(
|
|
|
1208
1209
|
dest_dict: Dict[str, Any] = {},
|
|
1209
1210
|
result_type: str = "json",
|
|
1210
1211
|
) -> Dict[str, Any]:
|
|
1211
|
-
"""Metadata configuration dictionary to querypath with conversion
|
|
1212
|
+
"""Metadata configuration dictionary to querypath with conversion dictionary
|
|
1212
1213
|
Transform every src_dict value from jsonpath_str to tuple `(conversion, jsonpath_object)`
|
|
1213
1214
|
or from xpath_str to tuple `(conversion, xpath_str)`
|
|
1214
1215
|
|
|
@@ -1462,6 +1463,14 @@ def get_queryable_from_provider(
|
|
|
1462
1463
|
:returns: EODAG configured queryable parameter or None
|
|
1463
1464
|
"""
|
|
1464
1465
|
pattern = rf"\b{provider_queryable}\b"
|
|
1466
|
+
# if 1:1 mapping exists privilege this one instead of other mapping
|
|
1467
|
+
# e.g. provider queryable = year -> use year and not date in which year also appears
|
|
1468
|
+
mapping_values = [
|
|
1469
|
+
v[0] if isinstance(v, list) else "" for v in metadata_mapping.values()
|
|
1470
|
+
]
|
|
1471
|
+
if provider_queryable in mapping_values:
|
|
1472
|
+
ind = mapping_values.index(provider_queryable)
|
|
1473
|
+
return Queryables.get_queryable_from_alias(list(metadata_mapping.keys())[ind])
|
|
1465
1474
|
for param, param_conf in metadata_mapping.items():
|
|
1466
1475
|
if isinstance(param_conf, list) and re.search(pattern, param_conf[0]):
|
|
1467
1476
|
return Queryables.get_queryable_from_alias(param)
|
eodag/api/search_result.py
CHANGED
|
@@ -18,9 +18,20 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
from collections import UserList
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import (
|
|
22
|
+
TYPE_CHECKING,
|
|
23
|
+
Annotated,
|
|
24
|
+
Any,
|
|
25
|
+
Dict,
|
|
26
|
+
Iterable,
|
|
27
|
+
List,
|
|
28
|
+
Optional,
|
|
29
|
+
Tuple,
|
|
30
|
+
Union,
|
|
31
|
+
)
|
|
22
32
|
|
|
23
33
|
from shapely.geometry import GeometryCollection, shape
|
|
34
|
+
from typing_extensions import Doc
|
|
24
35
|
|
|
25
36
|
from eodag.api.product import EOProduct
|
|
26
37
|
from eodag.plugins.crunch.filter_date import FilterDate
|
|
@@ -47,11 +58,19 @@ class SearchResult(UserList):
|
|
|
47
58
|
|
|
48
59
|
data: List[EOProduct]
|
|
49
60
|
|
|
61
|
+
errors: Annotated[
|
|
62
|
+
List[Tuple[str, Exception]], Doc("Tuple of provider name, exception")
|
|
63
|
+
]
|
|
64
|
+
|
|
50
65
|
def __init__(
|
|
51
|
-
self,
|
|
66
|
+
self,
|
|
67
|
+
products: List[EOProduct],
|
|
68
|
+
number_matched: Optional[int] = None,
|
|
69
|
+
errors: List[Tuple[str, Exception]] = [],
|
|
52
70
|
) -> None:
|
|
53
|
-
super(
|
|
71
|
+
super().__init__(products)
|
|
54
72
|
self.number_matched = number_matched
|
|
73
|
+
self.errors = errors
|
|
55
74
|
|
|
56
75
|
def crunch(self, cruncher: Crunch, **search_params: Any) -> SearchResult:
|
|
57
76
|
"""Do some crunching with the underlying EO products.
|
|
@@ -197,6 +216,13 @@ class SearchResult(UserList):
|
|
|
197
216
|
+ "</table>"
|
|
198
217
|
)
|
|
199
218
|
|
|
219
|
+
def extend(self, other: Iterable) -> None:
|
|
220
|
+
"""override extend method to include errors"""
|
|
221
|
+
if isinstance(other, SearchResult):
|
|
222
|
+
self.errors.extend(other.errors)
|
|
223
|
+
|
|
224
|
+
return super().extend(other)
|
|
225
|
+
|
|
200
226
|
|
|
201
227
|
class RawSearchResult(UserList):
|
|
202
228
|
"""An object representing a collection of raw/unparsed search results obtained from a provider.
|
eodag/cli.py
CHANGED
|
@@ -39,6 +39,7 @@ Commands:
|
|
|
39
39
|
|
|
40
40
|
noqa: D103
|
|
41
41
|
"""
|
|
42
|
+
|
|
42
43
|
from __future__ import annotations
|
|
43
44
|
|
|
44
45
|
import json
|
|
@@ -553,12 +554,13 @@ def download(ctx: Context, **kwargs: Any) -> None:
|
|
|
553
554
|
|
|
554
555
|
for idx, product in enumerate(search_results):
|
|
555
556
|
if product.downloader is None:
|
|
557
|
+
downloader = satim_api._plugins_manager.get_download_plugin(product)
|
|
556
558
|
auth = product.downloader_auth
|
|
557
559
|
if auth is None:
|
|
558
|
-
auth = satim_api._plugins_manager.get_auth_plugin(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
)
|
|
560
|
+
auth = satim_api._plugins_manager.get_auth_plugin(
|
|
561
|
+
downloader, product
|
|
562
|
+
)
|
|
563
|
+
search_results[idx].register_downloader(downloader, auth)
|
|
562
564
|
|
|
563
565
|
downloaded_file = product.get_quicklook()
|
|
564
566
|
if not downloaded_file:
|
|
@@ -573,12 +575,13 @@ def download(ctx: Context, **kwargs: Any) -> None:
|
|
|
573
575
|
# register downloader
|
|
574
576
|
for idx, product in enumerate(search_results):
|
|
575
577
|
if product.downloader is None:
|
|
578
|
+
downloader = satim_api._plugins_manager.get_download_plugin(product)
|
|
576
579
|
auth = product.downloader_auth
|
|
577
580
|
if auth is None:
|
|
578
|
-
auth = satim_api._plugins_manager.get_auth_plugin(
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
)
|
|
581
|
+
auth = satim_api._plugins_manager.get_auth_plugin(
|
|
582
|
+
downloader, product
|
|
583
|
+
)
|
|
584
|
+
search_results[idx].register_downloader(downloader, auth)
|
|
582
585
|
|
|
583
586
|
downloaded_files = satim_api.download_all(search_results)
|
|
584
587
|
if downloaded_files and len(downloaded_files) > 0:
|
|
@@ -684,19 +687,32 @@ def serve_rest(
|
|
|
684
687
|
else:
|
|
685
688
|
sys.exit(0)
|
|
686
689
|
else:
|
|
690
|
+
import logging
|
|
691
|
+
|
|
687
692
|
logging_config = uvicorn.config.LOGGING_CONFIG
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
693
|
+
uvicorn_fmt = "%(asctime)-15s %(name)-32s [%(levelname)-8s] %(message)s"
|
|
694
|
+
logging_config["formatters"]["access"]["fmt"] = uvicorn_fmt
|
|
695
|
+
logging_config["formatters"]["default"]["fmt"] = uvicorn_fmt
|
|
696
|
+
|
|
697
|
+
eodag_formatter = logging.Formatter(
|
|
698
|
+
"%(asctime)-15s %(name)-32s [%(levelname)-8s] (tid=%(thread)d) %(message)s"
|
|
699
|
+
)
|
|
700
|
+
logging.getLogger("eodag").handlers[0].setFormatter(eodag_formatter)
|
|
701
|
+
|
|
702
|
+
if ctx.obj["verbosity"] <= 1:
|
|
703
|
+
logging_config["handlers"]["null"] = {
|
|
704
|
+
"level": "DEBUG",
|
|
705
|
+
"class": "logging.NullHandler",
|
|
699
706
|
}
|
|
707
|
+
logging_config["loggers"]["uvicorn"]["handlers"] = ["null"]
|
|
708
|
+
logging_config["loggers"]["uvicorn.error"]["handlers"] = ["null"]
|
|
709
|
+
logging_config["loggers"]["uvicorn.access"]["handlers"] = ["null"]
|
|
710
|
+
else:
|
|
711
|
+
log_level = "INFO" if ctx.obj["verbosity"] == 2 else "DEBUG"
|
|
712
|
+
logging_config["loggers"]["uvicorn"]["level"] = log_level
|
|
713
|
+
logging_config["loggers"]["uvicorn.error"]["level"] = log_level
|
|
714
|
+
logging_config["loggers"]["uvicorn.access"]["level"] = log_level
|
|
715
|
+
|
|
700
716
|
uvicorn.run(
|
|
701
717
|
"eodag.rest.server:app",
|
|
702
718
|
host=bind_host,
|