eodag 3.0.1__py3-none-any.whl → 3.1.0__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 +174 -138
- eodag/api/product/_assets.py +44 -15
- eodag/api/product/_product.py +58 -47
- eodag/api/product/drivers/__init__.py +81 -4
- eodag/api/product/drivers/base.py +65 -4
- eodag/api/product/drivers/generic.py +65 -0
- eodag/api/product/drivers/sentinel1.py +97 -0
- eodag/api/product/drivers/sentinel2.py +95 -0
- eodag/api/product/metadata_mapping.py +117 -90
- eodag/api/search_result.py +13 -23
- eodag/cli.py +26 -5
- eodag/config.py +86 -92
- eodag/plugins/apis/base.py +1 -1
- eodag/plugins/apis/ecmwf.py +42 -22
- eodag/plugins/apis/usgs.py +17 -16
- eodag/plugins/authentication/aws_auth.py +16 -13
- eodag/plugins/authentication/base.py +5 -3
- eodag/plugins/authentication/header.py +3 -3
- eodag/plugins/authentication/keycloak.py +4 -4
- eodag/plugins/authentication/oauth.py +7 -3
- eodag/plugins/authentication/openid_connect.py +22 -16
- eodag/plugins/authentication/sas_auth.py +4 -4
- eodag/plugins/authentication/token.py +41 -10
- eodag/plugins/authentication/token_exchange.py +1 -1
- eodag/plugins/base.py +4 -4
- eodag/plugins/crunch/base.py +4 -4
- eodag/plugins/crunch/filter_date.py +4 -4
- eodag/plugins/crunch/filter_latest_intersect.py +6 -6
- eodag/plugins/crunch/filter_latest_tpl_name.py +7 -7
- eodag/plugins/crunch/filter_overlap.py +4 -4
- eodag/plugins/crunch/filter_property.py +6 -7
- eodag/plugins/download/aws.py +146 -87
- eodag/plugins/download/base.py +38 -56
- eodag/plugins/download/creodias_s3.py +29 -0
- eodag/plugins/download/http.py +173 -183
- eodag/plugins/download/s3rest.py +10 -11
- eodag/plugins/manager.py +10 -20
- eodag/plugins/search/__init__.py +6 -5
- eodag/plugins/search/base.py +90 -46
- eodag/plugins/search/build_search_result.py +1048 -361
- eodag/plugins/search/cop_marine.py +22 -12
- eodag/plugins/search/creodias_s3.py +9 -73
- eodag/plugins/search/csw.py +11 -11
- eodag/plugins/search/data_request_search.py +19 -18
- eodag/plugins/search/qssearch.py +99 -258
- eodag/plugins/search/stac_list_assets.py +85 -0
- eodag/plugins/search/static_stac_search.py +4 -4
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +1134 -325
- eodag/resources/providers.yml +906 -2006
- eodag/resources/stac_api.yml +2 -2
- eodag/resources/user_conf_template.yml +10 -9
- eodag/rest/cache.py +2 -2
- eodag/rest/config.py +3 -3
- eodag/rest/core.py +112 -82
- eodag/rest/errors.py +5 -5
- eodag/rest/server.py +33 -14
- eodag/rest/stac.py +41 -38
- eodag/rest/types/collections_search.py +3 -3
- eodag/rest/types/eodag_search.py +29 -23
- eodag/rest/types/queryables.py +42 -31
- eodag/rest/types/stac_search.py +15 -25
- eodag/rest/utils/__init__.py +14 -21
- eodag/rest/utils/cql_evaluate.py +6 -6
- eodag/rest/utils/rfc3339.py +2 -2
- eodag/types/__init__.py +141 -32
- eodag/types/bbox.py +2 -2
- eodag/types/download_args.py +3 -3
- eodag/types/queryables.py +183 -72
- eodag/types/search_args.py +4 -4
- eodag/types/whoosh.py +127 -3
- eodag/utils/__init__.py +153 -51
- eodag/utils/exceptions.py +28 -21
- eodag/utils/import_system.py +2 -2
- eodag/utils/repr.py +65 -6
- eodag/utils/requests.py +13 -13
- eodag/utils/rest.py +2 -2
- eodag/utils/s3.py +231 -0
- eodag/utils/stac_reader.py +10 -10
- {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/METADATA +77 -76
- eodag-3.1.0.dist-info/RECORD +113 -0
- {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/WHEEL +1 -1
- {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/entry_points.txt +4 -2
- eodag/utils/constraints.py +0 -244
- eodag-3.0.1.dist-info/RECORD +0 -109
- {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/LICENSE +0 -0
- {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/top_level.txt +0 -0
eodag/api/search_result.py
CHANGED
|
@@ -18,17 +18,7 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
from collections import UserList
|
|
21
|
-
from typing import
|
|
22
|
-
TYPE_CHECKING,
|
|
23
|
-
Annotated,
|
|
24
|
-
Any,
|
|
25
|
-
Dict,
|
|
26
|
-
Iterable,
|
|
27
|
-
List,
|
|
28
|
-
Optional,
|
|
29
|
-
Tuple,
|
|
30
|
-
Union,
|
|
31
|
-
)
|
|
21
|
+
from typing import TYPE_CHECKING, Annotated, Any, Iterable, Optional, Union
|
|
32
22
|
|
|
33
23
|
from shapely.geometry import GeometryCollection, shape
|
|
34
24
|
from typing_extensions import Doc
|
|
@@ -56,17 +46,17 @@ class SearchResult(UserList):
|
|
|
56
46
|
:ivar number_matched: Estimated total number of matching results
|
|
57
47
|
"""
|
|
58
48
|
|
|
59
|
-
data:
|
|
49
|
+
data: list[EOProduct]
|
|
60
50
|
|
|
61
51
|
errors: Annotated[
|
|
62
|
-
|
|
52
|
+
list[tuple[str, Exception]], Doc("Tuple of provider name, exception")
|
|
63
53
|
]
|
|
64
54
|
|
|
65
55
|
def __init__(
|
|
66
56
|
self,
|
|
67
|
-
products:
|
|
57
|
+
products: list[EOProduct],
|
|
68
58
|
number_matched: Optional[int] = None,
|
|
69
|
-
errors:
|
|
59
|
+
errors: list[tuple[str, Exception]] = [],
|
|
70
60
|
) -> None:
|
|
71
61
|
super().__init__(products)
|
|
72
62
|
self.number_matched = number_matched
|
|
@@ -92,7 +82,7 @@ class SearchResult(UserList):
|
|
|
92
82
|
return self.crunch(FilterDate(dict(start=start, end=end)))
|
|
93
83
|
|
|
94
84
|
def filter_latest_intersect(
|
|
95
|
-
self, geometry: Union[
|
|
85
|
+
self, geometry: Union[dict[str, Any], BaseGeometry, Any]
|
|
96
86
|
) -> SearchResult:
|
|
97
87
|
"""
|
|
98
88
|
Apply :class:`~eodag.plugins.crunch.filter_latest_intersect.FilterLatestIntersect` crunch,
|
|
@@ -148,7 +138,7 @@ class SearchResult(UserList):
|
|
|
148
138
|
return self.filter_property(storageStatus="ONLINE")
|
|
149
139
|
|
|
150
140
|
@staticmethod
|
|
151
|
-
def from_geojson(feature_collection:
|
|
141
|
+
def from_geojson(feature_collection: dict[str, Any]) -> SearchResult:
|
|
152
142
|
"""Builds an :class:`~eodag.api.search_result.SearchResult` object from its representation as geojson
|
|
153
143
|
|
|
154
144
|
:param feature_collection: A collection representing a search result.
|
|
@@ -161,7 +151,7 @@ class SearchResult(UserList):
|
|
|
161
151
|
]
|
|
162
152
|
)
|
|
163
153
|
|
|
164
|
-
def as_geojson_object(self) ->
|
|
154
|
+
def as_geojson_object(self) -> dict[str, Any]:
|
|
165
155
|
"""GeoJSON representation of SearchResult"""
|
|
166
156
|
return {
|
|
167
157
|
"type": "FeatureCollection",
|
|
@@ -182,7 +172,7 @@ class SearchResult(UserList):
|
|
|
182
172
|
return self.as_shapely_geometry_object().wkt
|
|
183
173
|
|
|
184
174
|
@property
|
|
185
|
-
def __geo_interface__(self) ->
|
|
175
|
+
def __geo_interface__(self) -> dict[str, Any]:
|
|
186
176
|
"""Implements the geo-interface protocol.
|
|
187
177
|
|
|
188
178
|
See https://gist.github.com/sgillies/2217756
|
|
@@ -230,9 +220,9 @@ class RawSearchResult(UserList):
|
|
|
230
220
|
:param results: A list of raw/unparsed search results
|
|
231
221
|
"""
|
|
232
222
|
|
|
233
|
-
data:
|
|
234
|
-
query_params:
|
|
235
|
-
product_type_def_params:
|
|
223
|
+
data: list[Any]
|
|
224
|
+
query_params: dict[str, Any]
|
|
225
|
+
product_type_def_params: dict[str, Any]
|
|
236
226
|
|
|
237
|
-
def __init__(self, results:
|
|
227
|
+
def __init__(self, results: list[Any]) -> None:
|
|
238
228
|
super(RawSearchResult, self).__init__(results)
|
eodag/cli.py
CHANGED
|
@@ -48,7 +48,7 @@ import shutil
|
|
|
48
48
|
import sys
|
|
49
49
|
import textwrap
|
|
50
50
|
from importlib.metadata import metadata
|
|
51
|
-
from typing import TYPE_CHECKING, Any,
|
|
51
|
+
from typing import TYPE_CHECKING, Any, Mapping
|
|
52
52
|
|
|
53
53
|
import click
|
|
54
54
|
|
|
@@ -57,6 +57,11 @@ from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE, parse_qs
|
|
|
57
57
|
from eodag.utils.exceptions import NoMatchingProductType, UnsupportedProvider
|
|
58
58
|
from eodag.utils.logging import setup_logging
|
|
59
59
|
|
|
60
|
+
try:
|
|
61
|
+
from eodag.rest.utils import LIVENESS_PROBE_PATH
|
|
62
|
+
except ImportError:
|
|
63
|
+
pass
|
|
64
|
+
|
|
60
65
|
if TYPE_CHECKING:
|
|
61
66
|
from click import Context
|
|
62
67
|
|
|
@@ -70,6 +75,18 @@ CRUNCHERS = [
|
|
|
70
75
|
]
|
|
71
76
|
|
|
72
77
|
|
|
78
|
+
class LivenessFilter:
|
|
79
|
+
"""
|
|
80
|
+
Filter out requests to the liveness probe endpoint
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def filter(self, record):
|
|
84
|
+
"""
|
|
85
|
+
Filter method required by the Python logging API.
|
|
86
|
+
"""
|
|
87
|
+
return LIVENESS_PROBE_PATH not in record.getMessage()
|
|
88
|
+
|
|
89
|
+
|
|
73
90
|
class MutuallyExclusiveOption(click.Option):
|
|
74
91
|
"""Mutually Exclusive Options for Click
|
|
75
92
|
from https://gist.github.com/jacobtolar/fb80d5552a9a9dfc32b12a829fa21c0c
|
|
@@ -87,7 +104,7 @@ class MutuallyExclusiveOption(click.Option):
|
|
|
87
104
|
super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)
|
|
88
105
|
|
|
89
106
|
def handle_parse_result(
|
|
90
|
-
self, ctx: Context, opts: Mapping[str, Any], args:
|
|
107
|
+
self, ctx: Context, opts: Mapping[str, Any], args: list[str]
|
|
91
108
|
):
|
|
92
109
|
"""Raise error or use parent handle_parse_result()"""
|
|
93
110
|
if self.mutually_exclusive.intersection(opts) and self.name in opts:
|
|
@@ -342,9 +359,9 @@ def search_crunch(ctx: Context, **kwargs: Any) -> None:
|
|
|
342
359
|
count = kwargs.pop("count")
|
|
343
360
|
|
|
344
361
|
# Process inputs for crunch
|
|
345
|
-
cruncher_names:
|
|
362
|
+
cruncher_names: set[Any] = set(kwargs.pop("cruncher") or [])
|
|
346
363
|
cruncher_args = kwargs.pop("cruncher_args")
|
|
347
|
-
cruncher_args_dict:
|
|
364
|
+
cruncher_args_dict: dict[str, dict[str, Any]] = {}
|
|
348
365
|
if cruncher_args:
|
|
349
366
|
for cruncher, argname, argval in cruncher_args:
|
|
350
367
|
cruncher_args_dict.setdefault(cruncher, {}).setdefault(argname, argval)
|
|
@@ -679,7 +696,9 @@ def serve_rest(
|
|
|
679
696
|
try:
|
|
680
697
|
pid = os.fork()
|
|
681
698
|
except OSError as e:
|
|
682
|
-
raise Exception(
|
|
699
|
+
raise Exception(
|
|
700
|
+
"%s [%d]" % (e.strerror, e.errno) if e.errno is not None else e.strerror
|
|
701
|
+
)
|
|
683
702
|
|
|
684
703
|
if pid == 0:
|
|
685
704
|
os.setsid()
|
|
@@ -691,8 +710,10 @@ def serve_rest(
|
|
|
691
710
|
|
|
692
711
|
logging_config = uvicorn.config.LOGGING_CONFIG
|
|
693
712
|
uvicorn_fmt = "%(asctime)-15s %(name)-32s [%(levelname)-8s] %(message)s"
|
|
713
|
+
logging_config["filters"] = {"liveness": {"()": LivenessFilter}}
|
|
694
714
|
logging_config["formatters"]["access"]["fmt"] = uvicorn_fmt
|
|
695
715
|
logging_config["formatters"]["default"]["fmt"] = uvicorn_fmt
|
|
716
|
+
logging_config["loggers"]["uvicorn.access"]["filters"] = ["liveness"]
|
|
696
717
|
|
|
697
718
|
eodag_formatter = logging.Formatter(
|
|
698
719
|
"%(asctime)-15s %(name)-32s [%(levelname)-8s] (tid=%(thread)d) %(message)s"
|