eodag 3.0.0b3__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 +347 -247
- 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 +129 -93
- eodag/api/search_result.py +28 -12
- eodag/cli.py +61 -24
- eodag/config.py +457 -167
- eodag/plugins/apis/base.py +10 -4
- eodag/plugins/apis/ecmwf.py +53 -23
- eodag/plugins/apis/usgs.py +41 -17
- eodag/plugins/authentication/aws_auth.py +30 -18
- eodag/plugins/authentication/base.py +14 -3
- eodag/plugins/authentication/generic.py +14 -3
- eodag/plugins/authentication/header.py +14 -6
- eodag/plugins/authentication/keycloak.py +44 -25
- eodag/plugins/authentication/oauth.py +18 -4
- eodag/plugins/authentication/openid_connect.py +192 -171
- eodag/plugins/authentication/qsauth.py +12 -4
- eodag/plugins/authentication/sas_auth.py +22 -5
- eodag/plugins/authentication/token.py +95 -17
- eodag/plugins/authentication/token_exchange.py +19 -19
- eodag/plugins/base.py +4 -4
- eodag/plugins/crunch/base.py +8 -5
- eodag/plugins/crunch/filter_date.py +9 -6
- eodag/plugins/crunch/filter_latest_intersect.py +9 -8
- eodag/plugins/crunch/filter_latest_tpl_name.py +8 -8
- eodag/plugins/crunch/filter_overlap.py +9 -11
- eodag/plugins/crunch/filter_property.py +10 -10
- eodag/plugins/download/aws.py +181 -105
- eodag/plugins/download/base.py +49 -67
- eodag/plugins/download/creodias_s3.py +40 -2
- eodag/plugins/download/http.py +247 -223
- eodag/plugins/download/s3rest.py +29 -28
- eodag/plugins/manager.py +176 -41
- eodag/plugins/search/__init__.py +6 -5
- eodag/plugins/search/base.py +123 -60
- eodag/plugins/search/build_search_result.py +1046 -355
- eodag/plugins/search/cop_marine.py +132 -39
- eodag/plugins/search/creodias_s3.py +19 -68
- eodag/plugins/search/csw.py +48 -8
- eodag/plugins/search/data_request_search.py +124 -23
- eodag/plugins/search/qssearch.py +531 -310
- eodag/plugins/search/stac_list_assets.py +85 -0
- eodag/plugins/search/static_stac_search.py +23 -24
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +1295 -355
- eodag/resources/providers.yml +1819 -3010
- eodag/resources/stac.yml +3 -163
- eodag/resources/stac_api.yml +2 -2
- eodag/resources/user_conf_template.yml +115 -99
- eodag/rest/cache.py +2 -2
- eodag/rest/config.py +3 -4
- eodag/rest/constants.py +0 -1
- eodag/rest/core.py +157 -117
- eodag/rest/errors.py +181 -0
- eodag/rest/server.py +57 -339
- eodag/rest/stac.py +133 -581
- eodag/rest/types/collections_search.py +3 -3
- eodag/rest/types/eodag_search.py +41 -30
- eodag/rest/types/queryables.py +42 -32
- eodag/rest/types/stac_search.py +15 -16
- 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 +153 -32
- eodag/types/bbox.py +2 -2
- eodag/types/download_args.py +4 -4
- eodag/types/queryables.py +183 -73
- eodag/types/search_args.py +6 -6
- eodag/types/whoosh.py +127 -3
- eodag/utils/__init__.py +228 -106
- eodag/utils/exceptions.py +47 -26
- eodag/utils/import_system.py +2 -2
- eodag/utils/logging.py +37 -77
- eodag/utils/repr.py +65 -6
- eodag/utils/requests.py +13 -15
- eodag/utils/rest.py +2 -2
- eodag/utils/s3.py +231 -0
- eodag/utils/stac_reader.py +11 -11
- {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/METADATA +81 -81
- eodag-3.1.0.dist-info/RECORD +113 -0
- {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/WHEEL +1 -1
- {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/entry_points.txt +5 -2
- eodag/resources/constraints/climate-dt.json +0 -13
- eodag/resources/constraints/extremes-dt.json +0 -8
- eodag/utils/constraints.py +0 -244
- eodag-3.0.0b3.dist-info/RECORD +0 -110
- {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/LICENSE +0 -0
- {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/top_level.txt +0 -0
eodag/utils/exceptions.py
CHANGED
|
@@ -17,24 +17,18 @@
|
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from typing import TYPE_CHECKING
|
|
20
|
+
from typing import TYPE_CHECKING, Annotated
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
|
-
from typing import Optional
|
|
23
|
+
from typing import Optional
|
|
24
|
+
|
|
25
|
+
from typing_extensions import Doc, Self
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class EodagError(Exception):
|
|
27
29
|
"""General EODAG error"""
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
class ValidationError(EodagError):
|
|
31
|
-
"""Error validating data"""
|
|
32
|
-
|
|
33
|
-
def __init__(self, message: str, parameters: Set[str] = set()) -> None:
|
|
34
|
-
self.message = message
|
|
35
|
-
self.parameters = parameters
|
|
36
|
-
|
|
37
|
-
|
|
38
32
|
class PluginNotFoundError(EodagError):
|
|
39
33
|
"""Error when looking for a plugin class that was not defined"""
|
|
40
34
|
|
|
@@ -72,35 +66,62 @@ class AuthenticationError(EodagError):
|
|
|
72
66
|
authenticating a user"""
|
|
73
67
|
|
|
74
68
|
|
|
75
|
-
class DownloadError(EodagError):
|
|
76
|
-
"""An error indicating something wrong with the download process"""
|
|
77
|
-
|
|
78
|
-
|
|
79
69
|
class NotAvailableError(EodagError):
|
|
80
70
|
"""An error indicating that the product is not available for download"""
|
|
81
71
|
|
|
82
72
|
|
|
73
|
+
class NoMatchingProductType(EodagError):
|
|
74
|
+
"""An error indicating that eodag was unable to derive a product type from a set
|
|
75
|
+
of search parameters"""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class STACOpenerError(EodagError):
|
|
79
|
+
"""An error indicating that a STAC file could not be opened"""
|
|
80
|
+
|
|
81
|
+
|
|
83
82
|
class RequestError(EodagError):
|
|
84
83
|
"""An error indicating that a request has failed. Usually eodag functions
|
|
85
84
|
and methods should catch and skip this"""
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
parameters: Set[str] = set()
|
|
86
|
+
status_code: Annotated[Optional[int], Doc("HTTP status code")] = None
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
@classmethod
|
|
89
|
+
def from_error(cls, error: Exception, msg: Optional[str] = None) -> Self:
|
|
90
|
+
"""Generate a RequestError from an Exception"""
|
|
91
|
+
status_code = getattr(error, "code", None)
|
|
92
|
+
text = getattr(error, "msg", None)
|
|
95
93
|
|
|
94
|
+
response = getattr(error, "response", None)
|
|
95
|
+
# Explicitly test for None because response objects are considered false if they
|
|
96
|
+
# have a status code other than 200
|
|
97
|
+
if response is not None:
|
|
98
|
+
status_code = response.status_code
|
|
99
|
+
text = " ".join([text or "", response.text])
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
"""An error indicating that eodag was unable to derive a product type from a set
|
|
99
|
-
of search parameters"""
|
|
101
|
+
text = text or str(error)
|
|
100
102
|
|
|
103
|
+
e = cls(msg, text) if msg else cls(text)
|
|
104
|
+
e.status_code = status_code
|
|
105
|
+
return e
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
|
|
108
|
+
class ValidationError(RequestError):
|
|
109
|
+
"""Error validating data"""
|
|
110
|
+
|
|
111
|
+
def __init__(self, message: str, parameters: set[str] = set()) -> None:
|
|
112
|
+
self.message = message
|
|
113
|
+
self.parameters = parameters
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def from_error(cls, error: Exception, msg: Optional[str] = None) -> Self:
|
|
117
|
+
"""Override parent from_error to handle ValidationError specificities."""
|
|
118
|
+
setattr(error, "msg", msg)
|
|
119
|
+
validation_error = super().from_error(error)
|
|
120
|
+
return validation_error
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class DownloadError(RequestError):
|
|
124
|
+
"""An error indicating something wrong with the download process"""
|
|
104
125
|
|
|
105
126
|
|
|
106
127
|
class TimeOutError(RequestError):
|
eodag/utils/import_system.py
CHANGED
|
@@ -21,14 +21,14 @@ import importlib
|
|
|
21
21
|
import pkgutil
|
|
22
22
|
from contextlib import contextmanager
|
|
23
23
|
from functools import partial
|
|
24
|
-
from typing import TYPE_CHECKING, Any, Generator
|
|
24
|
+
from typing import TYPE_CHECKING, Any, Generator
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
27
|
from types import ModuleType
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def import_all_modules(
|
|
31
|
-
base_package: ModuleType, depth: int = 1, exclude:
|
|
31
|
+
base_package: ModuleType, depth: int = 1, exclude: tuple[str, ...] = ()
|
|
32
32
|
) -> None:
|
|
33
33
|
"""Import all modules in base_package, including modules in the sub-packages up to `depth` and excluding modules in
|
|
34
34
|
`exclude`.
|
eodag/utils/logging.py
CHANGED
|
@@ -37,88 +37,48 @@ def setup_logging(verbose: int, no_progress_bar: bool = False) -> None:
|
|
|
37
37
|
global disable_tqdm
|
|
38
38
|
disable_tqdm = no_progress_bar
|
|
39
39
|
|
|
40
|
+
if verbose > 3:
|
|
41
|
+
raise ValueError("'verbose' must be one of: 0, 1, 2, 3")
|
|
42
|
+
|
|
40
43
|
if verbose < 1:
|
|
41
44
|
disable_tqdm = True
|
|
42
45
|
|
|
43
|
-
if verbose
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"formatter": "standard",
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
"loggers": {
|
|
74
|
-
"eodag": {
|
|
75
|
-
"handlers": ["console"],
|
|
76
|
-
"propagate": True,
|
|
77
|
-
"level": "INFO",
|
|
78
|
-
},
|
|
79
|
-
"sentinelsat": {
|
|
80
|
-
"handlers": ["console"],
|
|
81
|
-
"propagate": True,
|
|
82
|
-
"level": "INFO",
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
}
|
|
86
|
-
)
|
|
87
|
-
elif verbose == 3:
|
|
88
|
-
logging.config.dictConfig(
|
|
89
|
-
{
|
|
90
|
-
"version": 1,
|
|
91
|
-
"disable_existing_loggers": False,
|
|
92
|
-
"formatters": {
|
|
93
|
-
"verbose": {
|
|
94
|
-
"format": (
|
|
95
|
-
"%(asctime)-15s %(name)-32s [%(levelname)-8s] (tid=%(thread)d) %(message)s"
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
"handlers": {
|
|
100
|
-
"console": {
|
|
101
|
-
"level": "DEBUG",
|
|
102
|
-
"class": "logging.StreamHandler",
|
|
103
|
-
"formatter": "verbose",
|
|
104
|
-
}
|
|
46
|
+
level = "DEBUG" if verbose == 3 else "INFO"
|
|
47
|
+
|
|
48
|
+
handlers = {
|
|
49
|
+
"console": {
|
|
50
|
+
"level": level,
|
|
51
|
+
"class": "logging.StreamHandler",
|
|
52
|
+
"formatter": "standard",
|
|
53
|
+
},
|
|
54
|
+
"null": {"level": level, "class": "logging.NullHandler"},
|
|
55
|
+
}
|
|
56
|
+
handler = "console" if verbose > 1 else "null"
|
|
57
|
+
|
|
58
|
+
logging.config.dictConfig(
|
|
59
|
+
{
|
|
60
|
+
"version": 1,
|
|
61
|
+
"disable_existing_loggers": False,
|
|
62
|
+
"formatters": {
|
|
63
|
+
"standard": {
|
|
64
|
+
"format": "%(asctime)-15s %(name)-32s [%(levelname)-8s] %(message)s"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"handlers": handlers,
|
|
68
|
+
"loggers": {
|
|
69
|
+
"eodag": {
|
|
70
|
+
"handlers": [handler],
|
|
71
|
+
"propagate": True,
|
|
72
|
+
"level": f"{level}",
|
|
105
73
|
},
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"level": "DEBUG",
|
|
111
|
-
},
|
|
112
|
-
"sentinelsat": {
|
|
113
|
-
"handlers": ["console"],
|
|
114
|
-
"propagate": True,
|
|
115
|
-
"level": "DEBUG",
|
|
116
|
-
},
|
|
74
|
+
"eodag-cube": {
|
|
75
|
+
"handlers": [handler],
|
|
76
|
+
"propagate": True,
|
|
77
|
+
"level": f"{level}",
|
|
117
78
|
},
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
raise ValueError("'verbose' must be one of: 0, 1, 2, 3")
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
)
|
|
122
82
|
|
|
123
83
|
|
|
124
84
|
def get_logging_verbose() -> Optional[int]:
|
eodag/utils/repr.py
CHANGED
|
@@ -18,12 +18,21 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import collections.abc
|
|
21
|
+
import re
|
|
21
22
|
from typing import Any, Optional
|
|
22
23
|
from urllib.parse import urlparse
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def str_as_href(link: str) -> str:
|
|
26
|
-
"""URL to html link
|
|
27
|
+
"""URL to html link
|
|
28
|
+
|
|
29
|
+
:param link: URL to format
|
|
30
|
+
:returns: HMLT formatted link
|
|
31
|
+
|
|
32
|
+
>>> str_as_href("http://foo.bar")
|
|
33
|
+
"<a href='http://foo.bar' target='_blank'>http://foo.bar</a>"
|
|
34
|
+
|
|
35
|
+
"""
|
|
27
36
|
if urlparse(link).scheme in ("file", "http", "https", "s3"):
|
|
28
37
|
return f"<a href='{link}' target='_blank'>{link}</a>"
|
|
29
38
|
else:
|
|
@@ -31,7 +40,13 @@ def str_as_href(link: str) -> str:
|
|
|
31
40
|
|
|
32
41
|
|
|
33
42
|
def html_table(input: Any, depth: Optional[int] = None) -> str:
|
|
34
|
-
"""Transform input to HTML table
|
|
43
|
+
"""Transform input object to HTML table
|
|
44
|
+
|
|
45
|
+
:param input: input object to represent
|
|
46
|
+
:param depth: maximum depth level until which nested objects should be represented
|
|
47
|
+
in new tables (unlimited by default)
|
|
48
|
+
:returns: HTML table
|
|
49
|
+
"""
|
|
35
50
|
if isinstance(input, collections.abc.Mapping):
|
|
36
51
|
return dict_to_html_table(input, depth=depth)
|
|
37
52
|
elif isinstance(input, collections.abc.Sequence) and not isinstance(input, str):
|
|
@@ -47,7 +62,14 @@ def dict_to_html_table(
|
|
|
47
62
|
depth: Optional[int] = None,
|
|
48
63
|
brackets: bool = True,
|
|
49
64
|
) -> str:
|
|
50
|
-
"""Transform input dict to HTML table
|
|
65
|
+
"""Transform input dict to HTML table
|
|
66
|
+
|
|
67
|
+
:param input_dict: input dict to represent
|
|
68
|
+
:param depth: maximum depth level until which nested objects should be represented
|
|
69
|
+
in new tables (unlimited by default)
|
|
70
|
+
:param brackets: whether surrounding brackets should be displayed or not
|
|
71
|
+
:returns: HTML table
|
|
72
|
+
"""
|
|
51
73
|
opening_bracket = "<span style='color: grey;'>{</span>" if brackets else ""
|
|
52
74
|
closing_bracket = "<span style='color: grey;'>}</span>" if brackets else ""
|
|
53
75
|
indent = "10px" if brackets else "0"
|
|
@@ -90,7 +112,13 @@ def dict_to_html_table(
|
|
|
90
112
|
def list_to_html_table(
|
|
91
113
|
input_list: collections.abc.Sequence, depth: Optional[int] = None
|
|
92
114
|
) -> str:
|
|
93
|
-
"""Transform input list to HTML table
|
|
115
|
+
"""Transform input list to HTML table
|
|
116
|
+
|
|
117
|
+
:param input_list: input list to represent
|
|
118
|
+
:param depth: maximum depth level until which nested objects should be represented
|
|
119
|
+
in new tables (unlimited by default)
|
|
120
|
+
:returns: HTML table
|
|
121
|
+
"""
|
|
94
122
|
if depth is not None:
|
|
95
123
|
depth -= 1
|
|
96
124
|
separator = (
|
|
@@ -103,11 +131,42 @@ def list_to_html_table(
|
|
|
103
131
|
+ separator.join(
|
|
104
132
|
[
|
|
105
133
|
f"""<span style='text-align: left;'>{
|
|
106
|
-
|
|
107
|
-
|
|
134
|
+
html_table(v, depth=depth)
|
|
135
|
+
}</span>
|
|
108
136
|
"""
|
|
109
137
|
for v in input_list
|
|
110
138
|
]
|
|
111
139
|
)
|
|
112
140
|
+ "<span style='color: grey;'>]</span>"
|
|
113
141
|
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def remove_class_repr(type_repr: str) -> str:
|
|
145
|
+
"""Removes class tag from type representation
|
|
146
|
+
|
|
147
|
+
:param type_repr: input type representation
|
|
148
|
+
:returns: type without class tag
|
|
149
|
+
|
|
150
|
+
>>> remove_class_repr(str(type("foo")))
|
|
151
|
+
'str'
|
|
152
|
+
"""
|
|
153
|
+
return re.sub(r"<class '(\w+)'>", r"\1", type_repr)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def shorter_type_repr(long_type: str) -> str:
|
|
157
|
+
"""Shorten long type representation
|
|
158
|
+
|
|
159
|
+
:param long_type: long type representation
|
|
160
|
+
:returns: type reprensentation shortened
|
|
161
|
+
|
|
162
|
+
>>> import typing
|
|
163
|
+
>>> shorter_type_repr(str(typing.Literal["foo", "bar"]))
|
|
164
|
+
"Literal['foo', ...]"
|
|
165
|
+
"""
|
|
166
|
+
# shorten lists
|
|
167
|
+
shorter = re.sub(r",[^\[^\]]+\]", ", ...]", str(long_type))
|
|
168
|
+
# remove class prefix
|
|
169
|
+
shorter = remove_class_repr(shorter)
|
|
170
|
+
# remove parent objects
|
|
171
|
+
shorter = re.sub(r"\w+\.", "", shorter)
|
|
172
|
+
return shorter
|
eodag/utils/requests.py
CHANGED
|
@@ -19,7 +19,7 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import logging
|
|
21
21
|
import os
|
|
22
|
-
from typing import Any, Optional
|
|
22
|
+
from typing import Any, Optional
|
|
23
23
|
|
|
24
24
|
import requests
|
|
25
25
|
|
|
@@ -30,7 +30,7 @@ logger = logging.getLogger("eodag.utils.requests")
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def fetch_json(
|
|
33
|
-
|
|
33
|
+
url: str,
|
|
34
34
|
req_session: Optional[requests.Session] = None,
|
|
35
35
|
auth: Optional[requests.auth.AuthBase] = None,
|
|
36
36
|
timeout: float = HTTP_REQ_TIMEOUT,
|
|
@@ -38,34 +38,32 @@ def fetch_json(
|
|
|
38
38
|
"""
|
|
39
39
|
Fetches http/distant or local json file
|
|
40
40
|
|
|
41
|
-
:param
|
|
41
|
+
:param url: url from which the file can be fetched
|
|
42
42
|
:param req_session: (optional) requests session
|
|
43
43
|
:param auth: (optional) authenticated object if request needs authentication
|
|
44
44
|
:param timeout: (optional) authenticated object
|
|
45
45
|
:returns: json file content
|
|
46
46
|
"""
|
|
47
47
|
if req_session is None:
|
|
48
|
-
req_session = requests.Session()
|
|
48
|
+
req_session = requests.sessions.Session()
|
|
49
49
|
try:
|
|
50
|
-
if not
|
|
51
|
-
|
|
50
|
+
if not url.lower().startswith("http"):
|
|
51
|
+
url = path_to_uri(os.path.abspath(url))
|
|
52
52
|
req_session.mount("file://", LocalFileAdapter())
|
|
53
53
|
|
|
54
54
|
headers = USER_AGENT
|
|
55
|
-
logger.debug(f"fetching {
|
|
55
|
+
logger.debug(f"fetching {url}")
|
|
56
56
|
res = req_session.get(
|
|
57
|
-
|
|
57
|
+
url,
|
|
58
58
|
headers=headers,
|
|
59
59
|
auth=auth,
|
|
60
60
|
timeout=timeout,
|
|
61
61
|
)
|
|
62
62
|
res.raise_for_status()
|
|
63
63
|
except requests.exceptions.Timeout as exc:
|
|
64
|
-
raise TimeOutError(exc, timeout=
|
|
64
|
+
raise TimeOutError(exc, timeout=timeout) from exc
|
|
65
65
|
except requests.exceptions.RequestException as exc:
|
|
66
|
-
raise RequestError(
|
|
67
|
-
f"Unable to fetch {file_url}: {str(exc)}",
|
|
68
|
-
) from exc
|
|
66
|
+
raise RequestError.from_error(exc, f"Unable to fetch {url}") from exc
|
|
69
67
|
else:
|
|
70
68
|
return res.json()
|
|
71
69
|
|
|
@@ -77,7 +75,7 @@ class LocalFileAdapter(requests.adapters.BaseAdapter):
|
|
|
77
75
|
"""
|
|
78
76
|
|
|
79
77
|
@staticmethod
|
|
80
|
-
def _chkpath(method: str, path: str) ->
|
|
78
|
+
def _chkpath(method: str, path: str) -> tuple[int, str]:
|
|
81
79
|
"""Return an HTTP status for the given filesystem path.
|
|
82
80
|
|
|
83
81
|
:param method: method of the request
|
|
@@ -102,8 +100,8 @@ class LocalFileAdapter(requests.adapters.BaseAdapter):
|
|
|
102
100
|
) -> requests.Response:
|
|
103
101
|
"""Wraps a file, described in request, in a Response object.
|
|
104
102
|
|
|
105
|
-
:param
|
|
106
|
-
:param kwargs: (not used)
|
|
103
|
+
:param request: The PreparedRequest being "sent".
|
|
104
|
+
:param kwargs: (not used) additional arguments of the request
|
|
107
105
|
:returns: a Response object containing the file
|
|
108
106
|
"""
|
|
109
107
|
response = requests.Response()
|
eodag/utils/rest.py
CHANGED
|
@@ -21,7 +21,7 @@ from __future__ import annotations
|
|
|
21
21
|
|
|
22
22
|
import datetime
|
|
23
23
|
import re
|
|
24
|
-
from typing import Any,
|
|
24
|
+
from typing import Any, Optional
|
|
25
25
|
|
|
26
26
|
import dateutil.parser
|
|
27
27
|
from dateutil import tz
|
|
@@ -35,7 +35,7 @@ RFC3339_PATTERN = (
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
def get_datetime(arguments:
|
|
38
|
+
def get_datetime(arguments: dict[str, Any]) -> tuple[Optional[str], Optional[str]]:
|
|
39
39
|
"""Get start and end dates from a dict containing `/` separated dates in `datetime` item
|
|
40
40
|
|
|
41
41
|
:param arguments: dict containing a single date or `/` separated dates in `datetime` item
|