eodag 3.9.0__py3-none-any.whl → 3.10.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/product/metadata_mapping.py +26 -30
- eodag/plugins/authentication/aws_auth.py +44 -2
- eodag/plugins/authentication/base.py +17 -0
- eodag/plugins/authentication/sas_auth.py +15 -0
- eodag/plugins/download/creodias_s3.py +7 -0
- eodag/resources/ext_collections.json +1 -0
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/providers.yml +15 -5
- eodag/resources/stac_provider.yml +1 -1
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/METADATA +3 -3
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/RECORD +15 -14
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/WHEEL +0 -0
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/entry_points.txt +0 -0
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/licenses/LICENSE +0 -0
- {eodag-3.9.0.dist-info → eodag-3.10.0.dist-info}/top_level.txt +0 -0
|
@@ -149,42 +149,38 @@ def format_metadata(search_param: str, *args: Any, **kwargs: Any) -> str:
|
|
|
149
149
|
"""Format a string of form ``{<field_name>#<conversion_function>}``
|
|
150
150
|
|
|
151
151
|
The currently understood converters are:
|
|
152
|
-
- ``
|
|
153
|
-
|
|
154
|
-
- ``
|
|
155
|
-
- ``
|
|
156
|
-
- ``
|
|
157
|
-
- ``
|
|
158
|
-
- ``to_geojson``: convert to a GeoJSON (via __geo_interface__ if exists)
|
|
152
|
+
- ``ceda_collection_name``: generate a CEDA collection name from a string
|
|
153
|
+
- ``csv_list``: convert to a comma separated list
|
|
154
|
+
- ``datetime_to_timestamp_milliseconds``: converts a utc date string to a timestamp in milliseconds
|
|
155
|
+
- ``dict_filter_and_sub``: filter dict items using jsonpath and then apply recursive_sub_str
|
|
156
|
+
- ``fake_l2a_title_from_l1c``: used to generate SAFE format metadata for data from AWS
|
|
157
|
+
- ``from_alternate``: update assets using given alternate
|
|
159
158
|
- ``from_ewkt``: convert EWKT to shapely geometry / WKT in DEFAULT_PROJ
|
|
160
|
-
- ``to_ewkt``: convert to EWKT (Extended Well-Known text)
|
|
161
159
|
- ``from_georss``: convert GeoRSS to shapely geometry / WKT in DEFAULT_PROJ
|
|
162
|
-
- ``
|
|
163
|
-
- ``to_iso_utc_datetime_from_milliseconds``: convert a utc timestamp in given
|
|
164
|
-
milliseconds to a utc iso datetime
|
|
165
|
-
- ``to_iso_utc_datetime``: convert a UTC datetime string to ISO UTC datetime
|
|
166
|
-
string
|
|
167
|
-
- ``to_iso_date``: remove the time part of a iso datetime string
|
|
168
|
-
- ``remove_extension``: on a string that contains dots, only take the first
|
|
169
|
-
part of the list obtained by splitting the string on dots
|
|
160
|
+
- ``get_ecmwf_time``: get the time of a datetime string in the ECMWF format
|
|
170
161
|
- ``get_group_name``: get the matching regex group name
|
|
162
|
+
- ``recursive_sub_str``: recursively substitue in the structure (e.g. dict) values matching a regex
|
|
163
|
+
- ``remove_extension``: on a string that contains dots, only take the first part of the list obtained by
|
|
164
|
+
splitting the string on dots
|
|
171
165
|
- ``replace_str``: execute "string".replace(old, new)
|
|
172
|
-
- ``recursive_sub_str``: recursively substitue in the structure (e.g. dict)
|
|
173
|
-
values matching a regex
|
|
174
|
-
- ``slice_str``: slice a string (equivalent to s[start, end, step])
|
|
175
|
-
- ``to_lower``: Convert a string to lowercase
|
|
176
|
-
- ``to_upper``: Convert a string to uppercase
|
|
177
|
-
- ``to_title``: Convert a string to title case
|
|
178
|
-
- ``fake_l2a_title_from_l1c``: used to generate SAFE format metadata for data from AWS
|
|
179
166
|
- ``s2msil2a_title_to_aws_productinfo``: used to generate SAFE format metadata for data from AWS
|
|
167
|
+
- ``sanitize``: sanitize string
|
|
168
|
+
- ``slice_str``: slice a string (equivalent to s[start, end, step])
|
|
180
169
|
- ``split_cop_dem_id``: get the bbox by splitting the product id
|
|
181
170
|
- ``split_corine_id``: get the product type by splitting the product id
|
|
171
|
+
- ``to_bounds_lists``: convert to list(s) of bounds
|
|
182
172
|
- ``to_datetime_dict``: convert a datetime string to a dictionary where values are either a string or a list
|
|
183
|
-
- ``
|
|
184
|
-
- ``
|
|
185
|
-
- ``
|
|
186
|
-
- ``
|
|
187
|
-
- ``
|
|
173
|
+
- ``to_ewkt``: convert to EWKT (Extended Well-Known text)
|
|
174
|
+
- ``to_geojson``: convert to a GeoJSON (via __geo_interface__ if exists)
|
|
175
|
+
- ``to_iso_date``: remove the time part of a iso datetime string
|
|
176
|
+
- ``to_iso_utc_datetime_from_milliseconds``: convert a utc timestamp in given milliseconds to a utc iso datetime
|
|
177
|
+
- ``to_iso_utc_datetime``: convert a UTC datetime string to ISO UTC datetime string
|
|
178
|
+
- ``to_lower``: Convert a string to lowercase
|
|
179
|
+
- ``to_nwse_bounds_str``: convert to North,West,South,East bounds string with given separator
|
|
180
|
+
- ``to_nwse_bounds``: convert to North,West,South,East bounds
|
|
181
|
+
- ``to_rounded_wkt``: simplify the WKT of a geometry
|
|
182
|
+
- ``to_title``: Convert a string to title case
|
|
183
|
+
- ``to_upper``: Convert a string to uppercase
|
|
188
184
|
|
|
189
185
|
:param search_param: The string to be formatted
|
|
190
186
|
:param args: (optional) Additional arguments to use in the formatting process
|
|
@@ -490,9 +486,9 @@ def format_metadata(search_param: str, *args: Any, **kwargs: Any) -> str:
|
|
|
490
486
|
return {"lon": lon, "lat": lat}
|
|
491
487
|
|
|
492
488
|
@staticmethod
|
|
493
|
-
def convert_csv_list(values_list: Any) -> Any:
|
|
489
|
+
def convert_csv_list(values_list: Any, separator=",") -> Any:
|
|
494
490
|
if isinstance(values_list, list):
|
|
495
|
-
return
|
|
491
|
+
return separator.join([str(x) for x in values_list])
|
|
496
492
|
else:
|
|
497
493
|
return values_list
|
|
498
494
|
|
|
@@ -24,9 +24,11 @@ import boto3
|
|
|
24
24
|
from botocore.exceptions import ClientError, ProfileNotFound
|
|
25
25
|
from botocore.handlers import disable_signing
|
|
26
26
|
|
|
27
|
+
from eodag.api.product._assets import Asset
|
|
27
28
|
from eodag.plugins.authentication.base import Authentication
|
|
28
29
|
from eodag.types import S3SessionKwargs
|
|
29
|
-
from eodag.utils
|
|
30
|
+
from eodag.utils import get_bucket_name_and_prefix
|
|
31
|
+
from eodag.utils.exceptions import AuthenticationError, EodagError
|
|
30
32
|
|
|
31
33
|
if TYPE_CHECKING:
|
|
32
34
|
from mypy_boto3_s3 import S3Client, S3ServiceResource
|
|
@@ -106,9 +108,12 @@ class AwsAuth(Authentication):
|
|
|
106
108
|
def _create_s3_session_from_credentials(self) -> boto3.Session:
|
|
107
109
|
credentials = getattr(self.config, "credentials", {}) or {}
|
|
108
110
|
if "aws_profile" in credentials:
|
|
111
|
+
logger.debug("Authentication using AWS profile")
|
|
109
112
|
return create_s3_session(profile_name=credentials["aws_profile"])
|
|
110
113
|
# auth using aws keys
|
|
111
|
-
elif credentials
|
|
114
|
+
elif credentials.get("aws_access_key_id") and credentials.get(
|
|
115
|
+
"aws_secret_access_key"
|
|
116
|
+
):
|
|
112
117
|
s3_session_kwargs: S3SessionKwargs = {
|
|
113
118
|
"aws_access_key_id": credentials["aws_access_key_id"],
|
|
114
119
|
"aws_secret_access_key": credentials["aws_secret_access_key"],
|
|
@@ -120,6 +125,7 @@ class AwsAuth(Authentication):
|
|
|
120
125
|
return create_s3_session(**s3_session_kwargs)
|
|
121
126
|
else:
|
|
122
127
|
# auth using env variables or ~/.aws
|
|
128
|
+
logger.debug("Authentication using AWS environment")
|
|
123
129
|
return create_s3_session()
|
|
124
130
|
|
|
125
131
|
def _create_s3_resource(self) -> S3ServiceResource:
|
|
@@ -133,6 +139,9 @@ class AwsAuth(Authentication):
|
|
|
133
139
|
endpoint_url=endpoint_url,
|
|
134
140
|
)
|
|
135
141
|
# could not auth using credentials: use no-sign-request strategy
|
|
142
|
+
logger.debug(
|
|
143
|
+
"Authentication using AWS no-sign-request strategy (no credentials found)"
|
|
144
|
+
)
|
|
136
145
|
s3_resource = boto3.resource(service_name="s3", endpoint_url=endpoint_url)
|
|
137
146
|
s3_resource.meta.client.meta.events.register(
|
|
138
147
|
"choose-signer.s3.*", disable_signing
|
|
@@ -276,3 +285,36 @@ class AwsAuth(Authentication):
|
|
|
276
285
|
"session": self.s3_session,
|
|
277
286
|
**rio_env_kwargs,
|
|
278
287
|
}
|
|
288
|
+
|
|
289
|
+
def presign_url(
|
|
290
|
+
self,
|
|
291
|
+
asset: Asset,
|
|
292
|
+
expires_in: int = 3600,
|
|
293
|
+
) -> str:
|
|
294
|
+
"""This method is used to presign a url to download an asset from S3.
|
|
295
|
+
|
|
296
|
+
:param asset: asset for which the url shall be presigned
|
|
297
|
+
:param expires_in: expiration time of the presigned url in seconds
|
|
298
|
+
:returns: presigned url
|
|
299
|
+
:raises: :class:`~eodag.utils.exceptions.EodagError`
|
|
300
|
+
:raises: :class:`NotImplementedError`
|
|
301
|
+
"""
|
|
302
|
+
if not getattr(self.config, "support_presign_url", True):
|
|
303
|
+
raise NotImplementedError(
|
|
304
|
+
f"presign_url is not supported for provider {self.provider}"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
s3_client = self.get_s3_client()
|
|
308
|
+
bucket, prefix = get_bucket_name_and_prefix(asset["href"])
|
|
309
|
+
try:
|
|
310
|
+
presigned_url = s3_client.generate_presigned_url(
|
|
311
|
+
"get_object",
|
|
312
|
+
Params={
|
|
313
|
+
"Bucket": bucket,
|
|
314
|
+
"Key": prefix,
|
|
315
|
+
},
|
|
316
|
+
ExpiresIn=expires_in,
|
|
317
|
+
)
|
|
318
|
+
return presigned_url
|
|
319
|
+
except ClientError:
|
|
320
|
+
raise EodagError(f"Couldn't get a presigned URL for '{asset}'.")
|
|
@@ -19,6 +19,7 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
21
21
|
|
|
22
|
+
from eodag.api.product._assets import Asset
|
|
22
23
|
from eodag.plugins.base import PluginTopic
|
|
23
24
|
from eodag.utils.exceptions import MisconfiguredError
|
|
24
25
|
|
|
@@ -80,3 +81,19 @@ class Authentication(PluginTopic):
|
|
|
80
81
|
Authenticates with s3 and retrieves the available objects
|
|
81
82
|
"""
|
|
82
83
|
raise NotImplementedError
|
|
84
|
+
|
|
85
|
+
def presign_url(
|
|
86
|
+
self,
|
|
87
|
+
asset: Asset,
|
|
88
|
+
expires_in: int = 3600,
|
|
89
|
+
) -> str:
|
|
90
|
+
"""This method is used to presign a url to download an asset from S3.
|
|
91
|
+
|
|
92
|
+
:param asset: asset for which the url shall be presigned
|
|
93
|
+
:param expires_in: expiration time of the presigned url in seconds
|
|
94
|
+
:returns: presigned url
|
|
95
|
+
:raises: :class:`NotImplementedError`
|
|
96
|
+
"""
|
|
97
|
+
raise NotImplementedError(
|
|
98
|
+
f"presign_url is not implemented for plugin {type(self).__name__}"
|
|
99
|
+
)
|
|
@@ -25,6 +25,7 @@ from typing import TYPE_CHECKING, Optional
|
|
|
25
25
|
import requests
|
|
26
26
|
from requests.auth import AuthBase
|
|
27
27
|
|
|
28
|
+
from eodag.api.product._assets import Asset
|
|
28
29
|
from eodag.plugins.authentication.base import Authentication
|
|
29
30
|
from eodag.utils import HTTP_REQ_TIMEOUT, USER_AGENT, deepcopy, format_dict_items
|
|
30
31
|
from eodag.utils.exceptions import AuthenticationError, TimeOutError
|
|
@@ -143,3 +144,17 @@ class SASAuth(Authentication):
|
|
|
143
144
|
ssl_verify=ssl_verify,
|
|
144
145
|
matching_url=matching_url,
|
|
145
146
|
)
|
|
147
|
+
|
|
148
|
+
def presign_url(
|
|
149
|
+
self,
|
|
150
|
+
asset: Asset,
|
|
151
|
+
expires_in: int = 3600,
|
|
152
|
+
) -> str:
|
|
153
|
+
"""This method is used to presign a url to download an asset.
|
|
154
|
+
|
|
155
|
+
:param asset: asset for which the url shall be presigned
|
|
156
|
+
:param expires_in: expiration time of the presigned url in seconds
|
|
157
|
+
:returns: presigned url
|
|
158
|
+
"""
|
|
159
|
+
url = asset["href"]
|
|
160
|
+
return self.config.auth_uri.format(url=url)
|
|
@@ -15,12 +15,19 @@
|
|
|
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 __future__ import annotations
|
|
19
|
+
|
|
18
20
|
from typing import Optional
|
|
19
21
|
|
|
20
22
|
from eodag import EOProduct
|
|
21
23
|
from eodag.plugins.download.aws import AwsDownload
|
|
24
|
+
from eodag.utils import _deprecated
|
|
22
25
|
|
|
23
26
|
|
|
27
|
+
@_deprecated(
|
|
28
|
+
reason="Plugin that was used in creodias_s3 provider configuration, but not anymore",
|
|
29
|
+
version="3.10.0",
|
|
30
|
+
)
|
|
24
31
|
class CreodiasS3Download(AwsDownload):
|
|
25
32
|
"""
|
|
26
33
|
Download on creodias s3 from their VMs (extension of :class:`~eodag.plugins.download.aws.AwsDownload`)
|