eodag 3.0.1__py3-none-any.whl → 3.1.0b2__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 +164 -127
- eodag/api/product/_assets.py +11 -11
- eodag/api/product/_product.py +45 -30
- 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 +101 -85
- eodag/api/search_result.py +13 -23
- eodag/cli.py +26 -5
- eodag/config.py +78 -81
- eodag/plugins/apis/base.py +1 -1
- eodag/plugins/apis/ecmwf.py +46 -22
- eodag/plugins/apis/usgs.py +16 -15
- 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 +16 -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 +58 -78
- 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 +87 -44
- eodag/plugins/search/build_search_result.py +1067 -329
- 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 +16 -15
- eodag/plugins/search/qssearch.py +103 -187
- eodag/plugins/search/stac_list_assets.py +85 -0
- eodag/plugins/search/static_stac_search.py +3 -3
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +663 -304
- eodag/resources/providers.yml +823 -1749
- eodag/resources/stac_api.yml +2 -2
- eodag/resources/user_conf_template.yml +11 -0
- 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 +40 -38
- eodag/rest/types/collections_search.py +3 -3
- eodag/rest/types/eodag_search.py +29 -23
- eodag/rest/types/queryables.py +15 -16
- 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 +75 -28
- 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 +152 -50
- 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 +208 -0
- eodag/utils/stac_reader.py +10 -10
- {eodag-3.0.1.dist-info → eodag-3.1.0b2.dist-info}/METADATA +77 -76
- eodag-3.1.0b2.dist-info/RECORD +113 -0
- {eodag-3.0.1.dist-info → eodag-3.1.0b2.dist-info}/WHEEL +1 -1
- {eodag-3.0.1.dist-info → eodag-3.1.0b2.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.0b2.dist-info}/LICENSE +0 -0
- {eodag-3.0.1.dist-info → eodag-3.1.0b2.dist-info}/top_level.txt +0 -0
eodag/rest/utils/__init__.py
CHANGED
|
@@ -23,17 +23,7 @@ import logging
|
|
|
23
23
|
import os
|
|
24
24
|
from io import BufferedReader
|
|
25
25
|
from shutil import make_archive, rmtree
|
|
26
|
-
from typing import
|
|
27
|
-
TYPE_CHECKING,
|
|
28
|
-
Any,
|
|
29
|
-
Callable,
|
|
30
|
-
Dict,
|
|
31
|
-
Iterator,
|
|
32
|
-
List,
|
|
33
|
-
NamedTuple,
|
|
34
|
-
Optional,
|
|
35
|
-
Union,
|
|
36
|
-
)
|
|
26
|
+
from typing import TYPE_CHECKING, Any, Callable, Iterator, NamedTuple, Optional, Union
|
|
37
27
|
from urllib.parse import unquote_plus, urlencode
|
|
38
28
|
|
|
39
29
|
import orjson
|
|
@@ -55,12 +45,15 @@ __all__ = ["get_date", "get_datetime"]
|
|
|
55
45
|
|
|
56
46
|
logger = logging.getLogger("eodag.rest.utils")
|
|
57
47
|
|
|
48
|
+
# Path of the liveness endpoint
|
|
49
|
+
LIVENESS_PROBE_PATH = "/_mgmt/ping"
|
|
50
|
+
|
|
58
51
|
|
|
59
52
|
class Cruncher(NamedTuple):
|
|
60
53
|
"""Type hinted Cruncher namedTuple"""
|
|
61
54
|
|
|
62
55
|
clazz: Callable[..., Any]
|
|
63
|
-
config_params:
|
|
56
|
+
config_params: list[str]
|
|
64
57
|
|
|
65
58
|
|
|
66
59
|
crunchers = {
|
|
@@ -87,19 +80,19 @@ def format_pydantic_error(e: pydanticValidationError) -> str:
|
|
|
87
80
|
|
|
88
81
|
def is_dict_str_any(var: Any) -> bool:
|
|
89
82
|
"""Verify whether the variable is of type dict[str, Any]"""
|
|
90
|
-
if isinstance(var,
|
|
83
|
+
if isinstance(var, dict):
|
|
91
84
|
return all(isinstance(k, str) for k in var.keys()) # type: ignore
|
|
92
85
|
return False
|
|
93
86
|
|
|
94
87
|
|
|
95
|
-
def str2list(v: Optional[str]) -> Optional[
|
|
88
|
+
def str2list(v: Optional[str]) -> Optional[list[str]]:
|
|
96
89
|
"""Convert string to list base on , delimiter."""
|
|
97
90
|
if v:
|
|
98
91
|
return v.split(",")
|
|
99
92
|
return None
|
|
100
93
|
|
|
101
94
|
|
|
102
|
-
def str2json(k: str, v: Optional[str] = None) -> Optional[
|
|
95
|
+
def str2json(k: str, v: Optional[str] = None) -> Optional[dict[str, Any]]:
|
|
103
96
|
"""decoding a URL parameter and then parsing it as JSON."""
|
|
104
97
|
if not v:
|
|
105
98
|
return None
|
|
@@ -109,25 +102,25 @@ def str2json(k: str, v: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
|
109
102
|
raise ValidationError(f"{k}: Incorrect JSON object") from e
|
|
110
103
|
|
|
111
104
|
|
|
112
|
-
def flatten_list(nested_list: Union[Any,
|
|
105
|
+
def flatten_list(nested_list: Union[Any, list[Any]]) -> list[Any]:
|
|
113
106
|
"""Flatten a nested list structure into a single list."""
|
|
114
107
|
if not isinstance(nested_list, list):
|
|
115
108
|
return [nested_list]
|
|
116
109
|
else:
|
|
117
|
-
flattened:
|
|
110
|
+
flattened: list[Any] = []
|
|
118
111
|
for element in nested_list:
|
|
119
112
|
flattened.extend(flatten_list(element))
|
|
120
113
|
return flattened
|
|
121
114
|
|
|
122
115
|
|
|
123
|
-
def list_to_str_list(input_list:
|
|
116
|
+
def list_to_str_list(input_list: list[Any]) -> list[str]:
|
|
124
117
|
"""Attempt to convert a list of any type to a list of strings."""
|
|
125
118
|
try:
|
|
126
119
|
# Try to convert each element to a string
|
|
127
120
|
return [str(element) for element in input_list]
|
|
128
121
|
except Exception as e:
|
|
129
122
|
# Raise an exception if any element cannot be converted
|
|
130
|
-
raise TypeError(f"Failed to convert to
|
|
123
|
+
raise TypeError(f"Failed to convert to list[str]: {e}") from e
|
|
131
124
|
|
|
132
125
|
|
|
133
126
|
def get_next_link(
|
|
@@ -135,7 +128,7 @@ def get_next_link(
|
|
|
135
128
|
search_request: SearchPostRequest,
|
|
136
129
|
total_results: Optional[int],
|
|
137
130
|
items_per_page: int,
|
|
138
|
-
) -> Optional[
|
|
131
|
+
) -> Optional[dict[str, Any]]:
|
|
139
132
|
"""Generate next link URL and body"""
|
|
140
133
|
body = search_request.model_dump(exclude_none=True)
|
|
141
134
|
if "bbox" in body:
|
|
@@ -156,7 +149,7 @@ def get_next_link(
|
|
|
156
149
|
params["page"] = str(page + 1)
|
|
157
150
|
url += f"?{urlencode(params)}"
|
|
158
151
|
|
|
159
|
-
next:
|
|
152
|
+
next: dict[str, Any] = {
|
|
160
153
|
"rel": "next",
|
|
161
154
|
"href": url,
|
|
162
155
|
"title": "Next page",
|
eodag/rest/utils/cql_evaluate.py
CHANGED
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
from datetime import datetime as dt
|
|
19
|
-
from typing import Any,
|
|
19
|
+
from typing import Any, Optional, Union
|
|
20
20
|
|
|
21
21
|
from pygeofilter import ast
|
|
22
22
|
from pygeofilter.backends.evaluator import Evaluator, handle
|
|
23
23
|
from pygeofilter.values import Geometry, Interval
|
|
24
24
|
|
|
25
|
-
simpleNode = Union[ast.Attribute, str, int, complex, float,
|
|
25
|
+
simpleNode = Union[ast.Attribute, str, int, complex, float, list[Any], tuple[Any, ...]]
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class EodagEvaluator(Evaluator):
|
|
@@ -36,7 +36,7 @@ class EodagEvaluator(Evaluator):
|
|
|
36
36
|
return node
|
|
37
37
|
|
|
38
38
|
@handle(Geometry)
|
|
39
|
-
def spatial(self, node: Geometry) ->
|
|
39
|
+
def spatial(self, node: Geometry) -> dict[str, Any]:
|
|
40
40
|
"""handle geometry"""
|
|
41
41
|
return node.geometry
|
|
42
42
|
|
|
@@ -46,7 +46,7 @@ class EodagEvaluator(Evaluator):
|
|
|
46
46
|
return node.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
47
47
|
|
|
48
48
|
@handle(Interval)
|
|
49
|
-
def interval(self, _, *interval: Any) ->
|
|
49
|
+
def interval(self, _, *interval: Any) -> list[Any]:
|
|
50
50
|
"""handle datetime interval"""
|
|
51
51
|
return list(interval)
|
|
52
52
|
|
|
@@ -60,7 +60,7 @@ class EodagEvaluator(Evaluator):
|
|
|
60
60
|
)
|
|
61
61
|
def predicate(
|
|
62
62
|
self, node: ast.Predicate, lhs: Any, rhs: Any
|
|
63
|
-
) -> Optional[
|
|
63
|
+
) -> Optional[dict[str, Any]]:
|
|
64
64
|
"""
|
|
65
65
|
Handle predicates
|
|
66
66
|
Verify the property is first attribute in each predicate
|
|
@@ -114,6 +114,6 @@ class EodagEvaluator(Evaluator):
|
|
|
114
114
|
return {lhs.name: list(rhs)}
|
|
115
115
|
|
|
116
116
|
@handle(ast.And)
|
|
117
|
-
def combination(self, _, lhs:
|
|
117
|
+
def combination(self, _, lhs: dict[str, str], rhs: dict[str, str]):
|
|
118
118
|
"""handle combinations"""
|
|
119
119
|
return {**lhs, **rhs}
|
eodag/rest/utils/rfc3339.py
CHANGED
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
import datetime
|
|
19
|
-
from typing import Optional
|
|
19
|
+
from typing import Optional
|
|
20
20
|
|
|
21
21
|
from eodag.utils.rest import rfc3339_str_to_datetime
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def str_to_interval(
|
|
25
25
|
interval: Optional[str],
|
|
26
|
-
) ->
|
|
26
|
+
) -> tuple[Optional[datetime.datetime], Optional[datetime.datetime]]:
|
|
27
27
|
"""Extract a tuple of datetimes from an interval string.
|
|
28
28
|
|
|
29
29
|
Interval strings are defined by
|
eodag/types/__init__.py
CHANGED
|
@@ -16,16 +16,14 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
"""EODAG types"""
|
|
19
|
+
|
|
19
20
|
from __future__ import annotations
|
|
20
21
|
|
|
21
22
|
from typing import (
|
|
22
23
|
Annotated,
|
|
23
24
|
Any,
|
|
24
|
-
Dict,
|
|
25
|
-
List,
|
|
26
25
|
Literal,
|
|
27
26
|
Optional,
|
|
28
|
-
Tuple,
|
|
29
27
|
TypedDict,
|
|
30
28
|
Union,
|
|
31
29
|
get_args,
|
|
@@ -33,7 +31,7 @@ from typing import (
|
|
|
33
31
|
)
|
|
34
32
|
|
|
35
33
|
from annotated_types import Gt, Lt
|
|
36
|
-
from pydantic import Field
|
|
34
|
+
from pydantic import BaseModel, Field, create_model
|
|
37
35
|
from pydantic.fields import FieldInfo
|
|
38
36
|
|
|
39
37
|
from eodag.utils import copy_deepcopy
|
|
@@ -41,7 +39,7 @@ from eodag.utils.exceptions import ValidationError
|
|
|
41
39
|
|
|
42
40
|
# Types mapping from JSON Schema and OpenAPI 3.1.0 specifications to Python
|
|
43
41
|
# See https://spec.openapis.org/oas/v3.1.0#data-types
|
|
44
|
-
JSON_TYPES_MAPPING:
|
|
42
|
+
JSON_TYPES_MAPPING: dict[str, type] = {
|
|
45
43
|
"boolean": bool,
|
|
46
44
|
"integer": int,
|
|
47
45
|
"number": float,
|
|
@@ -52,7 +50,7 @@ JSON_TYPES_MAPPING: Dict[str, type] = {
|
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
|
|
55
|
-
def json_type_to_python(json_type: Union[str,
|
|
53
|
+
def json_type_to_python(json_type: Union[str, list[str]]) -> type:
|
|
56
54
|
"""Get python type from json type https://spec.openapis.org/oas/v3.1.0#data-types
|
|
57
55
|
|
|
58
56
|
>>> json_type_to_python("number")
|
|
@@ -69,9 +67,9 @@ def json_type_to_python(json_type: Union[str, List[str]]) -> type:
|
|
|
69
67
|
return type(None)
|
|
70
68
|
|
|
71
69
|
|
|
72
|
-
def _get_min_or_max(type_info: Union[Lt, Gt, Any]) ->
|
|
73
|
-
"""
|
|
74
|
-
|
|
70
|
+
def _get_min_or_max(type_info: Union[Lt, Gt, Any]) -> tuple[str, Any]:
|
|
71
|
+
"""Checks if the value from an Annotated object is a minimum or maximum
|
|
72
|
+
|
|
75
73
|
:param type_info: info from Annotated
|
|
76
74
|
:return: "min" or "max"
|
|
77
75
|
"""
|
|
@@ -83,10 +81,10 @@ def _get_min_or_max(type_info: Union[Lt, Gt, Any]) -> Tuple[str, Any]:
|
|
|
83
81
|
|
|
84
82
|
|
|
85
83
|
def _get_type_info_from_annotated(
|
|
86
|
-
annotated_type: Annotated[type, Any]
|
|
87
|
-
) ->
|
|
88
|
-
"""
|
|
89
|
-
|
|
84
|
+
annotated_type: Annotated[type, Any],
|
|
85
|
+
) -> dict[str, Any]:
|
|
86
|
+
"""Retrieves type information from an annotated object
|
|
87
|
+
|
|
90
88
|
:param annotated_type: annotated object
|
|
91
89
|
:return: dict containing type and min/max if available
|
|
92
90
|
"""
|
|
@@ -107,7 +105,7 @@ def _get_type_info_from_annotated(
|
|
|
107
105
|
|
|
108
106
|
def python_type_to_json(
|
|
109
107
|
python_type: type,
|
|
110
|
-
) -> Optional[Union[str,
|
|
108
|
+
) -> Optional[Union[str, list[dict[str, Any]]]]:
|
|
111
109
|
"""Get json type from python https://spec.openapis.org/oas/v3.1.0#data-types
|
|
112
110
|
|
|
113
111
|
>>> python_type_to_json(int)
|
|
@@ -118,7 +116,8 @@ def python_type_to_json(
|
|
|
118
116
|
:param python_type: the python type
|
|
119
117
|
:returns: the json type
|
|
120
118
|
"""
|
|
121
|
-
|
|
119
|
+
origin = get_origin(python_type)
|
|
120
|
+
if origin is Union:
|
|
122
121
|
json_type = list()
|
|
123
122
|
for single_python_type in get_args(python_type):
|
|
124
123
|
type_data = {}
|
|
@@ -138,14 +137,16 @@ def python_type_to_json(
|
|
|
138
137
|
return list(JSON_TYPES_MAPPING.keys())[
|
|
139
138
|
list(JSON_TYPES_MAPPING.values()).index(python_type)
|
|
140
139
|
]
|
|
141
|
-
elif
|
|
140
|
+
elif origin is Annotated:
|
|
142
141
|
return [_get_type_info_from_annotated(python_type)]
|
|
142
|
+
elif origin is list:
|
|
143
|
+
raise NotImplementedError("Never completed")
|
|
143
144
|
else:
|
|
144
145
|
return None
|
|
145
146
|
|
|
146
147
|
|
|
147
148
|
def json_field_definition_to_python(
|
|
148
|
-
json_field_definition:
|
|
149
|
+
json_field_definition: dict[str, Any],
|
|
149
150
|
default_value: Optional[Any] = None,
|
|
150
151
|
required: Optional[bool] = False,
|
|
151
152
|
) -> Annotated[Any, FieldInfo]:
|
|
@@ -173,12 +174,27 @@ def json_field_definition_to_python(
|
|
|
173
174
|
title=json_field_definition.get("title", None),
|
|
174
175
|
description=json_field_definition.get("description", None),
|
|
175
176
|
pattern=json_field_definition.get("pattern", None),
|
|
177
|
+
le=json_field_definition.get("maximum"),
|
|
178
|
+
ge=json_field_definition.get("minimum"),
|
|
176
179
|
)
|
|
177
180
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
):
|
|
181
|
-
|
|
181
|
+
enum = json_field_definition.get("enum")
|
|
182
|
+
|
|
183
|
+
if python_type in (list, set):
|
|
184
|
+
items = json_field_definition.get("items", None)
|
|
185
|
+
if isinstance(items, list):
|
|
186
|
+
python_type = tuple[ # type: ignore
|
|
187
|
+
tuple(
|
|
188
|
+
json_field_definition_to_python(item, required=required)
|
|
189
|
+
for item in items
|
|
190
|
+
)
|
|
191
|
+
]
|
|
192
|
+
elif isinstance(items, dict):
|
|
193
|
+
enum = items.get("enum")
|
|
194
|
+
|
|
195
|
+
if enum:
|
|
196
|
+
literal = Literal[tuple(sorted(enum))] # type: ignore
|
|
197
|
+
python_type = list[literal] if python_type in (list, set) else literal # type: ignore
|
|
182
198
|
|
|
183
199
|
if "$ref" in json_field_definition:
|
|
184
200
|
field_type_kwargs["json_schema_extra"] = {"$ref": json_field_definition["$ref"]}
|
|
@@ -190,8 +206,8 @@ def json_field_definition_to_python(
|
|
|
190
206
|
|
|
191
207
|
|
|
192
208
|
def python_field_definition_to_json(
|
|
193
|
-
python_field_definition: Annotated[Any, FieldInfo]
|
|
194
|
-
) ->
|
|
209
|
+
python_field_definition: Annotated[Any, FieldInfo],
|
|
210
|
+
) -> dict[str, Any]:
|
|
195
211
|
"""Get json field definition from python `typing.Annotated`
|
|
196
212
|
|
|
197
213
|
>>> from pydantic import Field
|
|
@@ -212,7 +228,7 @@ def python_field_definition_to_json(
|
|
|
212
228
|
"%s must be an instance of Annotated" % python_field_definition
|
|
213
229
|
)
|
|
214
230
|
|
|
215
|
-
json_field_definition:
|
|
231
|
+
json_field_definition: dict[str, Any] = dict()
|
|
216
232
|
|
|
217
233
|
python_field_args = get_args(python_field_definition)
|
|
218
234
|
|
|
@@ -252,6 +268,7 @@ def python_field_definition_to_json(
|
|
|
252
268
|
json_field_definition["max"] = [
|
|
253
269
|
row["max"] if "max" in row else None for row in field_type
|
|
254
270
|
]
|
|
271
|
+
|
|
255
272
|
if "min" in json_field_definition and json_field_definition["min"].count(
|
|
256
273
|
None
|
|
257
274
|
) == len(json_field_definition["min"]):
|
|
@@ -291,8 +308,8 @@ def python_field_definition_to_json(
|
|
|
291
308
|
|
|
292
309
|
|
|
293
310
|
def model_fields_to_annotated(
|
|
294
|
-
model_fields:
|
|
295
|
-
) ->
|
|
311
|
+
model_fields: dict[str, FieldInfo],
|
|
312
|
+
) -> dict[str, Annotated[Any, FieldInfo]]:
|
|
296
313
|
"""Convert BaseModel.model_fields from FieldInfo to Annotated
|
|
297
314
|
|
|
298
315
|
>>> from pydantic import create_model
|
|
@@ -306,7 +323,7 @@ def model_fields_to_annotated(
|
|
|
306
323
|
:param model_fields: BaseModel.model_fields to convert
|
|
307
324
|
:returns: Annotated tuple usable as create_model argument
|
|
308
325
|
"""
|
|
309
|
-
annotated_model_fields = dict()
|
|
326
|
+
annotated_model_fields: dict[str, Annotated[Any, FieldInfo]] = dict()
|
|
310
327
|
for param, field_info in model_fields.items():
|
|
311
328
|
field_type = field_info.annotation or type(None)
|
|
312
329
|
new_field_info = copy_deepcopy(field_info)
|
|
@@ -315,6 +332,27 @@ def model_fields_to_annotated(
|
|
|
315
332
|
return annotated_model_fields
|
|
316
333
|
|
|
317
334
|
|
|
335
|
+
def annotated_dict_to_model(
|
|
336
|
+
model_name: str, annotated_fields: dict[str, Annotated[Any, FieldInfo]]
|
|
337
|
+
) -> BaseModel:
|
|
338
|
+
"""Convert a dictionary of Annotated values to a Pydantic BaseModel.
|
|
339
|
+
|
|
340
|
+
:param model_name: name of the model to be created
|
|
341
|
+
:param annotated_fields: dict containing the parameters and annotated values that should become
|
|
342
|
+
the properties of the model
|
|
343
|
+
:returns: pydantic model
|
|
344
|
+
"""
|
|
345
|
+
fields = {
|
|
346
|
+
name: (field.__args__[0], field.__metadata__[0])
|
|
347
|
+
for name, field in annotated_fields.items()
|
|
348
|
+
}
|
|
349
|
+
return create_model(
|
|
350
|
+
model_name,
|
|
351
|
+
**fields, # type: ignore
|
|
352
|
+
__config__={"arbitrary_types_allowed": True},
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
|
|
318
356
|
class ProviderSortables(TypedDict):
|
|
319
357
|
"""A class representing sortable parameter(s) of a provider and the allowed
|
|
320
358
|
maximum number of used sortable(s) in a search request with the provider
|
|
@@ -323,5 +361,14 @@ class ProviderSortables(TypedDict):
|
|
|
323
361
|
:param max_sort_params: (optional) The allowed maximum number of sortable(s) in a search request with the provider
|
|
324
362
|
"""
|
|
325
363
|
|
|
326
|
-
sortables:
|
|
364
|
+
sortables: list[str]
|
|
327
365
|
max_sort_params: Annotated[Optional[int], Gt(0)]
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class S3SessionKwargs(TypedDict, total=False):
|
|
369
|
+
"""A class representing available keyword arguments to pass to :class:`boto3.session.Session` for authentication"""
|
|
370
|
+
|
|
371
|
+
aws_access_key_id: Optional[str]
|
|
372
|
+
aws_secret_access_key: Optional[str]
|
|
373
|
+
aws_session_token: Optional[str]
|
|
374
|
+
profile_name: Optional[str]
|
eodag/types/bbox.py
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import Union
|
|
19
19
|
|
|
20
20
|
from pydantic import BaseModel, ValidationInfo, field_validator
|
|
21
21
|
from shapely.geometry.polygon import Polygon
|
|
22
22
|
|
|
23
23
|
NumType = Union[float, int]
|
|
24
24
|
BBoxArgs = Union[
|
|
25
|
-
|
|
25
|
+
list[NumType], tuple[NumType, NumType, NumType, NumType], dict[str, NumType]
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
|
eodag/types/download_args.py
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from typing import
|
|
20
|
+
from typing import Optional, TypedDict, Union
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class DownloadConf(TypedDict, total=False):
|
|
@@ -33,8 +33,8 @@ class DownloadConf(TypedDict, total=False):
|
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
output_dir: str
|
|
36
|
-
output_extension: str
|
|
36
|
+
output_extension: Union[str, None]
|
|
37
37
|
extract: bool
|
|
38
|
-
dl_url_params:
|
|
38
|
+
dl_url_params: dict[str, str]
|
|
39
39
|
delete_archive: bool
|
|
40
40
|
asset: Optional[str]
|