eodag 3.0.0b2__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/__init__.py +6 -8
- eodag/api/core.py +295 -287
- eodag/api/product/__init__.py +10 -4
- eodag/api/product/_assets.py +2 -14
- eodag/api/product/_product.py +16 -30
- eodag/api/product/drivers/__init__.py +7 -2
- eodag/api/product/drivers/base.py +0 -3
- eodag/api/product/metadata_mapping.py +12 -31
- eodag/api/search_result.py +33 -12
- eodag/cli.py +35 -19
- eodag/config.py +455 -155
- eodag/plugins/apis/base.py +13 -7
- eodag/plugins/apis/ecmwf.py +16 -7
- eodag/plugins/apis/usgs.py +68 -16
- eodag/plugins/authentication/aws_auth.py +25 -7
- 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 +183 -167
- eodag/plugins/authentication/qsauth.py +12 -4
- eodag/plugins/authentication/sas_auth.py +19 -2
- eodag/plugins/authentication/token.py +59 -11
- eodag/plugins/authentication/token_exchange.py +19 -19
- eodag/plugins/crunch/base.py +7 -2
- eodag/plugins/crunch/filter_date.py +8 -11
- eodag/plugins/crunch/filter_latest_intersect.py +5 -7
- eodag/plugins/crunch/filter_latest_tpl_name.py +2 -5
- eodag/plugins/crunch/filter_overlap.py +9 -15
- eodag/plugins/crunch/filter_property.py +9 -14
- eodag/plugins/download/aws.py +84 -99
- eodag/plugins/download/base.py +36 -77
- eodag/plugins/download/creodias_s3.py +11 -2
- eodag/plugins/download/http.py +134 -109
- eodag/plugins/download/s3rest.py +37 -43
- eodag/plugins/manager.py +173 -41
- eodag/plugins/search/__init__.py +9 -9
- eodag/plugins/search/base.py +35 -35
- eodag/plugins/search/build_search_result.py +55 -64
- eodag/plugins/search/cop_marine.py +113 -32
- eodag/plugins/search/creodias_s3.py +20 -8
- eodag/plugins/search/csw.py +41 -1
- eodag/plugins/search/data_request_search.py +119 -14
- eodag/plugins/search/qssearch.py +619 -197
- eodag/plugins/search/static_stac_search.py +25 -23
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +211 -56
- eodag/resources/providers.yml +1762 -1809
- eodag/resources/stac.yml +3 -163
- eodag/resources/user_conf_template.yml +134 -119
- eodag/rest/config.py +1 -2
- eodag/rest/constants.py +0 -1
- eodag/rest/core.py +70 -92
- eodag/rest/errors.py +181 -0
- eodag/rest/server.py +24 -330
- eodag/rest/stac.py +105 -630
- eodag/rest/types/eodag_search.py +17 -15
- eodag/rest/types/queryables.py +5 -14
- eodag/rest/types/stac_search.py +18 -13
- eodag/rest/utils/rfc3339.py +0 -1
- eodag/types/__init__.py +24 -6
- eodag/types/download_args.py +14 -5
- eodag/types/queryables.py +1 -2
- eodag/types/search_args.py +10 -11
- eodag/types/whoosh.py +0 -2
- eodag/utils/__init__.py +97 -136
- eodag/utils/constraints.py +0 -8
- eodag/utils/exceptions.py +23 -9
- eodag/utils/import_system.py +0 -4
- eodag/utils/logging.py +37 -80
- eodag/utils/notebook.py +4 -4
- eodag/utils/requests.py +13 -23
- eodag/utils/rest.py +0 -4
- eodag/utils/stac_reader.py +3 -15
- {eodag-3.0.0b2.dist-info → eodag-3.0.1.dist-info}/METADATA +41 -24
- eodag-3.0.1.dist-info/RECORD +109 -0
- {eodag-3.0.0b2.dist-info → eodag-3.0.1.dist-info}/WHEEL +1 -1
- {eodag-3.0.0b2.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.0b2.dist-info/RECORD +0 -110
- {eodag-3.0.0b2.dist-info → eodag-3.0.1.dist-info}/LICENSE +0 -0
- {eodag-3.0.0b2.dist-info → eodag-3.0.1.dist-info}/top_level.txt +0 -0
eodag/plugins/download/aws.py
CHANGED
|
@@ -34,6 +34,7 @@ from typing import (
|
|
|
34
34
|
Optional,
|
|
35
35
|
Set,
|
|
36
36
|
Tuple,
|
|
37
|
+
TypedDict,
|
|
37
38
|
Union,
|
|
38
39
|
cast,
|
|
39
40
|
)
|
|
@@ -69,6 +70,7 @@ from eodag.utils.exceptions import (
|
|
|
69
70
|
AuthenticationError,
|
|
70
71
|
DownloadError,
|
|
71
72
|
MisconfiguredError,
|
|
73
|
+
NoMatchingProductType,
|
|
72
74
|
NotAvailableError,
|
|
73
75
|
TimeOutError,
|
|
74
76
|
)
|
|
@@ -213,23 +215,36 @@ class AwsDownload(Download):
|
|
|
213
215
|
"""Download on AWS using S3 protocol.
|
|
214
216
|
|
|
215
217
|
:param provider: provider name
|
|
216
|
-
:type provider: str
|
|
217
218
|
:param config: Download plugin configuration:
|
|
218
219
|
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
*
|
|
224
|
-
|
|
220
|
+
* :attr:`~eodag.config.PluginConfig.type` (``str``) (**mandatory**): AwsDownload
|
|
221
|
+
* :attr:`~eodag.config.PluginConfig.base_uri` (``str``) (**mandatory**): s3 endpoint url
|
|
222
|
+
* :attr:`~eodag.config.PluginConfig.requester_pays` (``bool``): whether download is done
|
|
223
|
+
from a requester-pays bucket or not; default: ``False``
|
|
224
|
+
* :attr:`~eodag.config.PluginConfig.flatten_top_dirs` (``bool``): if the directory structure
|
|
225
|
+
should be flattened; default: ``True``
|
|
226
|
+
* :attr:`~eodag.config.PluginConfig.ignore_assets` (``bool``): ignore assets and download
|
|
227
|
+
using ``downloadLink``; default: ``False``
|
|
228
|
+
* :attr:`~eodag.config.PluginConfig.ssl_verify` (``bool``): if the ssl certificates should
|
|
229
|
+
be verified in requests; default: ``True``
|
|
230
|
+
* :attr:`~eodag.config.PluginConfig.bucket_path_level` (``int``): at which level of the
|
|
231
|
+
path part of the url the bucket can be found; If no bucket_path_level is given, the bucket
|
|
232
|
+
is taken from the first element of the netloc part.
|
|
233
|
+
* :attr:`~eodag.config.PluginConfig.products` (``Dict[str, Dict[str, Any]``): product type
|
|
234
|
+
specific config; the keys are the product types, the values are dictionaries which can contain the keys:
|
|
235
|
+
|
|
236
|
+
* **default_bucket** (``str``): bucket where the product type can be found
|
|
237
|
+
* **complementary_url_key** (``str``): keys to add additional urls
|
|
238
|
+
* **build_safe** (``bool``): if a SAFE (Standard Archive Format for Europe) product should
|
|
239
|
+
be created; used for Sentinel products; default: False
|
|
240
|
+
* **fetch_metadata** (``Dict[str, Any]``): config for metadata to be fetched for the SAFE product
|
|
225
241
|
|
|
226
|
-
:type config: :class:`~eodag.config.PluginConfig`
|
|
227
242
|
"""
|
|
228
243
|
|
|
229
244
|
def __init__(self, provider: str, config: PluginConfig) -> None:
|
|
230
245
|
super(AwsDownload, self).__init__(provider, config)
|
|
231
246
|
self.requester_pays = getattr(self.config, "requester_pays", False)
|
|
232
|
-
self.s3_session = None
|
|
247
|
+
self.s3_session: Optional[boto3.session.Session] = None
|
|
233
248
|
|
|
234
249
|
def download(
|
|
235
250
|
self,
|
|
@@ -246,25 +261,20 @@ class AwsDownload(Download):
|
|
|
246
261
|
SAFE-build is configured for a given provider and product type.
|
|
247
262
|
If the product title is configured to be updated during download and
|
|
248
263
|
SAFE-formatted, its destination path will be:
|
|
249
|
-
`{
|
|
264
|
+
`{output_dir}/{title}`
|
|
250
265
|
|
|
251
266
|
:param product: The EO product to download
|
|
252
|
-
:type product: :class:`~eodag.api.product._product.EOProduct`
|
|
253
267
|
:param auth: (optional) authenticated object
|
|
254
|
-
:type auth: Union[AuthBase, Dict[str, str]]
|
|
255
268
|
:param progress_callback: (optional) A method or a callable object
|
|
256
269
|
which takes a current size and a maximum
|
|
257
270
|
size as inputs and handle progress bar
|
|
258
271
|
creation and update to give the user a
|
|
259
272
|
feedback on the download progress
|
|
260
|
-
:
|
|
261
|
-
:param kwargs: `outputs_prefix` (str), `extract` (bool), `delete_archive` (bool)
|
|
273
|
+
:param kwargs: `output_dir` (str), `extract` (bool), `delete_archive` (bool)
|
|
262
274
|
and `dl_url_params` (dict) can be provided as additional kwargs
|
|
263
275
|
and will override any other values defined in a configuration
|
|
264
276
|
file or with environment variables.
|
|
265
|
-
:type kwargs: Union[str, bool, dict]
|
|
266
277
|
:returns: The absolute path to the downloaded product in the local filesystem
|
|
267
|
-
:rtype: str
|
|
268
278
|
"""
|
|
269
279
|
if auth is None:
|
|
270
280
|
auth = {}
|
|
@@ -404,13 +414,9 @@ class AwsDownload(Download):
|
|
|
404
414
|
- get file path
|
|
405
415
|
- create directories
|
|
406
416
|
:param product: product to be downloaded
|
|
407
|
-
:type product: EOProduct
|
|
408
417
|
:param progress_callback: progress callback to be used
|
|
409
|
-
:type progress_callback: ProgressCallback
|
|
410
418
|
:param kwargs: additional arguments
|
|
411
|
-
:type kwargs: Any
|
|
412
419
|
:return: local path and file name
|
|
413
|
-
:rtype: Tuple[str, Optional[str]]
|
|
414
420
|
"""
|
|
415
421
|
product_local_path, record_filename = self._prepare_download(
|
|
416
422
|
product, progress_callback=progress_callback, **kwargs
|
|
@@ -432,9 +438,7 @@ class AwsDownload(Download):
|
|
|
432
438
|
"""
|
|
433
439
|
updates the product properties with fetch metadata if safe build is enabled
|
|
434
440
|
:param build_safe: if safe build is enabled
|
|
435
|
-
:type build_safe: bool
|
|
436
441
|
:param product: product to be updated
|
|
437
|
-
:type product: EOProduct
|
|
438
442
|
"""
|
|
439
443
|
product_conf = getattr(self.config, "products", {}).get(
|
|
440
444
|
product.product_type, {}
|
|
@@ -480,13 +484,9 @@ class AwsDownload(Download):
|
|
|
480
484
|
"""
|
|
481
485
|
retrieves the bucket names and path prefixes for the assets
|
|
482
486
|
:param product: product for which the assets shall be downloaded
|
|
483
|
-
:type product: EOProduct
|
|
484
487
|
:param asset_filter: text for which the assets should be filtered
|
|
485
|
-
:type asset_filter: str
|
|
486
488
|
:param ignore_assets: if product instead of individual assets should be used
|
|
487
|
-
:type ignore_assets: bool
|
|
488
489
|
:return: tuples of bucket names and prefixes
|
|
489
|
-
:rtype: List[Tuple[str, Optional[str]]]
|
|
490
490
|
"""
|
|
491
491
|
# if assets are defined, use them instead of scanning product.location
|
|
492
492
|
if len(product.assets) > 0 and not ignore_assets:
|
|
@@ -528,11 +528,8 @@ class AwsDownload(Download):
|
|
|
528
528
|
authenticates with s3 and retrieves the available objects
|
|
529
529
|
raises an error when authentication is not possible
|
|
530
530
|
:param bucket_names_and_prefixes: list of bucket names and corresponding path prefixes
|
|
531
|
-
:type bucket_names_and_prefixes: List[Tuple[str, Optional[str]]]
|
|
532
531
|
:param auth: authentication information
|
|
533
|
-
:type auth: Dict[str, str]
|
|
534
532
|
:return: authenticated objects per bucket, list of available objects
|
|
535
|
-
:rtype: Tuple[Dict[str, Any], ResourceCollection[Any]]
|
|
536
533
|
"""
|
|
537
534
|
if not isinstance(auth, (dict, type(None))):
|
|
538
535
|
raise AuthenticationError(
|
|
@@ -602,17 +599,11 @@ class AwsDownload(Download):
|
|
|
602
599
|
"""
|
|
603
600
|
retrieve unique product chunks based on authenticated objects and asset filters
|
|
604
601
|
:param bucket_names_and_prefixes: list of bucket names and corresponding path prefixes
|
|
605
|
-
:type bucket_names_and_prefixes: List[Tuple[str, Optional[str]]]
|
|
606
602
|
:param authenticated_objects: available objects per bucket
|
|
607
|
-
:type authenticated_objects: Dict[str, Any]
|
|
608
603
|
:param asset_filter: text for which assets should be filtered
|
|
609
|
-
:type asset_filter: str
|
|
610
604
|
:param ignore_assets: if product instead of individual assets should be used
|
|
611
|
-
:type ignore_assets: bool
|
|
612
605
|
:param product: product that shall be downloaded
|
|
613
|
-
:type product: EOProduct
|
|
614
606
|
:return: set of product chunks that can be downloaded
|
|
615
|
-
:rtype: Set[Any]
|
|
616
607
|
"""
|
|
617
608
|
product_chunks: List[Any] = []
|
|
618
609
|
for bucket_name, prefix in bucket_names_and_prefixes:
|
|
@@ -637,19 +628,20 @@ class AwsDownload(Download):
|
|
|
637
628
|
raise NotAvailableError(
|
|
638
629
|
rf"No file basename matching re.fullmatch(r'{asset_filter}') was found in {product.remote_location}"
|
|
639
630
|
)
|
|
631
|
+
|
|
632
|
+
if not unique_product_chunks:
|
|
633
|
+
raise NoMatchingProductType("No product found to download.")
|
|
634
|
+
|
|
640
635
|
return unique_product_chunks
|
|
641
636
|
|
|
642
637
|
def _raise_if_auth_error(self, exception: ClientError) -> None:
|
|
643
638
|
"""Raises an error if given exception is an authentication error"""
|
|
644
|
-
err = exception.response["Error"]
|
|
639
|
+
err = cast(Dict[str, str], exception.response["Error"])
|
|
645
640
|
if err["Code"] in AWS_AUTH_ERROR_MESSAGES and "key" in err["Message"].lower():
|
|
646
641
|
raise AuthenticationError(
|
|
647
|
-
"
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
err["Message"],
|
|
651
|
-
self.provider,
|
|
652
|
-
)
|
|
642
|
+
f"Please check your credentials for {self.provider}.",
|
|
643
|
+
f"HTTP Error {exception.response['ResponseMetadata']['HTTPStatusCode']} returned.",
|
|
644
|
+
err["Code"] + ": " + err["Message"],
|
|
653
645
|
)
|
|
654
646
|
|
|
655
647
|
def _stream_download_dict(
|
|
@@ -662,27 +654,20 @@ class AwsDownload(Download):
|
|
|
662
654
|
**kwargs: Unpack[DownloadConf],
|
|
663
655
|
) -> StreamResponse:
|
|
664
656
|
r"""
|
|
665
|
-
Returns
|
|
657
|
+
Returns dictionary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
|
|
666
658
|
It contains a generator to streamed download chunks and the response headers.
|
|
667
659
|
|
|
668
660
|
:param product: The EO product to download
|
|
669
|
-
:type product: :class:`~eodag.api.product._product.EOProduct`
|
|
670
661
|
:param auth: (optional) The configuration of a plugin of type Authentication
|
|
671
|
-
:type auth: :class:`~eodag.config.PluginConfig`
|
|
672
662
|
:param progress_callback: (optional) A progress callback
|
|
673
|
-
:type progress_callback: :class:`~eodag.utils.ProgressCallback`
|
|
674
663
|
:param wait: (optional) If download fails, wait time in minutes between two download tries
|
|
675
|
-
:type wait: int
|
|
676
664
|
:param timeout: (optional) If download fails, maximum time in minutes before stop retrying
|
|
677
665
|
to download
|
|
678
|
-
:
|
|
679
|
-
:param kwargs: `outputs_prefix` (str), `extract` (bool), `delete_archive` (bool)
|
|
666
|
+
:param kwargs: `output_dir` (str), `extract` (bool), `delete_archive` (bool)
|
|
680
667
|
and `dl_url_params` (dict) can be provided as additional kwargs
|
|
681
668
|
and will override any other values defined in a configuration
|
|
682
669
|
file or with environment variables.
|
|
683
|
-
:
|
|
684
|
-
:returns: Dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments
|
|
685
|
-
:rtype: dict
|
|
670
|
+
:returns: Dictionary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments
|
|
686
671
|
"""
|
|
687
672
|
if progress_callback is None:
|
|
688
673
|
logger.info(
|
|
@@ -773,7 +758,7 @@ class AwsDownload(Download):
|
|
|
773
758
|
build_safe: bool,
|
|
774
759
|
progress_callback: ProgressCallback,
|
|
775
760
|
assets_values: List[Dict[str, Any]],
|
|
776
|
-
) -> Iterator[
|
|
761
|
+
) -> Iterator[Any]:
|
|
777
762
|
"""Yield product data chunks"""
|
|
778
763
|
|
|
779
764
|
chunk_size = 4096 * 1024
|
|
@@ -784,7 +769,6 @@ class AwsDownload(Download):
|
|
|
784
769
|
product_chunk: Any, progress_callback: ProgressCallback
|
|
785
770
|
) -> Any:
|
|
786
771
|
try:
|
|
787
|
-
|
|
788
772
|
chunk_start = 0
|
|
789
773
|
chunk_end = chunk_start + chunk_size - 1
|
|
790
774
|
|
|
@@ -861,13 +845,9 @@ class AwsDownload(Download):
|
|
|
861
845
|
"""Get rasterio environment variables needed for data access authentication.
|
|
862
846
|
|
|
863
847
|
:param bucket_name: Bucket containg objects
|
|
864
|
-
:type bucket_name: str
|
|
865
848
|
:param prefix: Prefix used to try auth
|
|
866
|
-
:
|
|
867
|
-
:param auth_dict: Dictionnary containing authentication keys
|
|
868
|
-
:type auth_dict: dict
|
|
849
|
+
:param auth_dict: Dictionary containing authentication keys
|
|
869
850
|
:returns: The rasterio environement variables
|
|
870
|
-
:rtype: dict
|
|
871
851
|
"""
|
|
872
852
|
if self.s3_session is not None:
|
|
873
853
|
if self.requester_pays:
|
|
@@ -892,14 +872,10 @@ class AwsDownload(Download):
|
|
|
892
872
|
Also expose ``s3_session`` as class variable if available.
|
|
893
873
|
|
|
894
874
|
:param bucket_name: Bucket containg objects
|
|
895
|
-
:type bucket_name: str
|
|
896
875
|
:param prefix: Prefix used to filter objects on auth try
|
|
897
876
|
(not used to filter returned objects)
|
|
898
|
-
:
|
|
899
|
-
:param auth_dict: Dictionnary containing authentication keys
|
|
900
|
-
:type auth_dict: dict
|
|
877
|
+
:param auth_dict: Dictionary containing authentication keys
|
|
901
878
|
:returns: The boto3 authenticated objects
|
|
902
|
-
:rtype: :class:`~boto3.resources.collection.s3.Bucket.objectsCollection`
|
|
903
879
|
"""
|
|
904
880
|
auth_methods: List[
|
|
905
881
|
Callable[[str, str, Dict[str, str]], Optional[ResourceCollection]]
|
|
@@ -941,15 +917,15 @@ class AwsDownload(Download):
|
|
|
941
917
|
) -> Optional[ResourceCollection]:
|
|
942
918
|
"""Auth strategy using no-sign-request"""
|
|
943
919
|
|
|
944
|
-
s3_resource = boto3.resource(
|
|
945
|
-
service_name="s3", endpoint_url=getattr(self.config, "
|
|
920
|
+
s3_resource = boto3.resource(
|
|
921
|
+
service_name="s3", endpoint_url=getattr(self.config, "s3_endpoint", None)
|
|
946
922
|
)
|
|
947
|
-
s3_resource.meta.client.meta.events.register(
|
|
923
|
+
s3_resource.meta.client.meta.events.register(
|
|
948
924
|
"choose-signer.s3.*", disable_signing
|
|
949
925
|
)
|
|
950
|
-
objects = s3_resource.Bucket(bucket_name).objects
|
|
951
|
-
list(objects.filter(Prefix=prefix).limit(1))
|
|
952
|
-
return objects
|
|
926
|
+
objects = s3_resource.Bucket(bucket_name).objects
|
|
927
|
+
list(objects.filter(Prefix=prefix).limit(1))
|
|
928
|
+
return objects
|
|
953
929
|
|
|
954
930
|
def _get_authenticated_objects_from_auth_profile(
|
|
955
931
|
self, bucket_name: str, prefix: str, auth_dict: Dict[str, str]
|
|
@@ -957,20 +933,20 @@ class AwsDownload(Download):
|
|
|
957
933
|
"""Auth strategy using RequestPayer=requester and ``aws_profile`` from provided credentials"""
|
|
958
934
|
|
|
959
935
|
if "profile_name" in auth_dict.keys():
|
|
960
|
-
s3_session = boto3.session.Session(profile_name=auth_dict["profile_name"])
|
|
961
|
-
s3_resource = s3_session.resource(
|
|
936
|
+
s3_session = boto3.session.Session(profile_name=auth_dict["profile_name"])
|
|
937
|
+
s3_resource = s3_session.resource(
|
|
962
938
|
service_name="s3",
|
|
963
|
-
endpoint_url=getattr(self.config, "
|
|
939
|
+
endpoint_url=getattr(self.config, "s3_endpoint", None),
|
|
964
940
|
)
|
|
965
941
|
if self.requester_pays:
|
|
966
|
-
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
942
|
+
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
967
943
|
RequestPayer="requester"
|
|
968
944
|
)
|
|
969
945
|
else:
|
|
970
|
-
objects = s3_resource.Bucket(bucket_name).objects
|
|
971
|
-
list(objects.filter(Prefix=prefix).limit(1))
|
|
972
|
-
self.s3_session = s3_session
|
|
973
|
-
return objects
|
|
946
|
+
objects = s3_resource.Bucket(bucket_name).objects
|
|
947
|
+
list(objects.filter(Prefix=prefix).limit(1))
|
|
948
|
+
self.s3_session = s3_session
|
|
949
|
+
return objects
|
|
974
950
|
else:
|
|
975
951
|
return None
|
|
976
952
|
|
|
@@ -981,23 +957,35 @@ class AwsDownload(Download):
|
|
|
981
957
|
from provided credentials"""
|
|
982
958
|
|
|
983
959
|
if all(k in auth_dict for k in ("aws_access_key_id", "aws_secret_access_key")):
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
960
|
+
S3SessionKwargs = TypedDict(
|
|
961
|
+
"S3SessionKwargs",
|
|
962
|
+
{
|
|
963
|
+
"aws_access_key_id": str,
|
|
964
|
+
"aws_secret_access_key": str,
|
|
965
|
+
"aws_session_token": str,
|
|
966
|
+
},
|
|
967
|
+
total=False,
|
|
987
968
|
)
|
|
988
|
-
|
|
969
|
+
s3_session_kwargs: S3SessionKwargs = {
|
|
970
|
+
"aws_access_key_id": auth_dict["aws_access_key_id"],
|
|
971
|
+
"aws_secret_access_key": auth_dict["aws_secret_access_key"],
|
|
972
|
+
}
|
|
973
|
+
if auth_dict.get("aws_session_token"):
|
|
974
|
+
s3_session_kwargs["aws_session_token"] = auth_dict["aws_session_token"]
|
|
975
|
+
s3_session = boto3.session.Session(**s3_session_kwargs)
|
|
976
|
+
s3_resource = s3_session.resource(
|
|
989
977
|
service_name="s3",
|
|
990
|
-
endpoint_url=getattr(self.config, "
|
|
978
|
+
endpoint_url=getattr(self.config, "s3_endpoint", None),
|
|
991
979
|
)
|
|
992
980
|
if self.requester_pays:
|
|
993
|
-
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
981
|
+
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
994
982
|
RequestPayer="requester"
|
|
995
983
|
)
|
|
996
984
|
else:
|
|
997
|
-
objects = s3_resource.Bucket(bucket_name).objects
|
|
998
|
-
list(objects.filter(Prefix=prefix).limit(1))
|
|
999
|
-
self.s3_session = s3_session
|
|
1000
|
-
return objects
|
|
985
|
+
objects = s3_resource.Bucket(bucket_name).objects
|
|
986
|
+
list(objects.filter(Prefix=prefix).limit(1))
|
|
987
|
+
self.s3_session = s3_session
|
|
988
|
+
return objects
|
|
1001
989
|
else:
|
|
1002
990
|
return None
|
|
1003
991
|
|
|
@@ -1006,19 +994,19 @@ class AwsDownload(Download):
|
|
|
1006
994
|
) -> Optional[ResourceCollection]:
|
|
1007
995
|
"""Auth strategy using RequestPayer=requester and current environment"""
|
|
1008
996
|
|
|
1009
|
-
s3_session = boto3.session.Session()
|
|
1010
|
-
s3_resource = s3_session.resource(
|
|
1011
|
-
service_name="s3", endpoint_url=getattr(self.config, "
|
|
997
|
+
s3_session = boto3.session.Session()
|
|
998
|
+
s3_resource = s3_session.resource(
|
|
999
|
+
service_name="s3", endpoint_url=getattr(self.config, "s3_endpoint", None)
|
|
1012
1000
|
)
|
|
1013
1001
|
if self.requester_pays:
|
|
1014
|
-
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
1002
|
+
objects = s3_resource.Bucket(bucket_name).objects.filter(
|
|
1015
1003
|
RequestPayer="requester"
|
|
1016
1004
|
)
|
|
1017
1005
|
else:
|
|
1018
|
-
objects = s3_resource.Bucket(bucket_name).objects
|
|
1019
|
-
list(objects.filter(Prefix=prefix).limit(1))
|
|
1020
|
-
self.s3_session = s3_session
|
|
1021
|
-
return objects
|
|
1006
|
+
objects = s3_resource.Bucket(bucket_name).objects
|
|
1007
|
+
list(objects.filter(Prefix=prefix).limit(1))
|
|
1008
|
+
self.s3_session = s3_session
|
|
1009
|
+
return objects
|
|
1022
1010
|
|
|
1023
1011
|
def get_product_bucket_name_and_prefix(
|
|
1024
1012
|
self, product: EOProduct, url: Optional[str] = None
|
|
@@ -1026,11 +1014,8 @@ class AwsDownload(Download):
|
|
|
1026
1014
|
"""Extract bucket name and prefix from product URL
|
|
1027
1015
|
|
|
1028
1016
|
:param product: The EO product to download
|
|
1029
|
-
:type product: :class:`~eodag.api.product._product.EOProduct`
|
|
1030
1017
|
:param url: (optional) URL to use as product.location
|
|
1031
|
-
:type url: str
|
|
1032
1018
|
:returns: bucket_name and prefix as str
|
|
1033
|
-
:rtype: tuple
|
|
1034
1019
|
"""
|
|
1035
1020
|
if url is None:
|
|
1036
1021
|
url = product.location
|