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.
Files changed (87) hide show
  1. eodag/api/core.py +174 -138
  2. eodag/api/product/_assets.py +44 -15
  3. eodag/api/product/_product.py +58 -47
  4. eodag/api/product/drivers/__init__.py +81 -4
  5. eodag/api/product/drivers/base.py +65 -4
  6. eodag/api/product/drivers/generic.py +65 -0
  7. eodag/api/product/drivers/sentinel1.py +97 -0
  8. eodag/api/product/drivers/sentinel2.py +95 -0
  9. eodag/api/product/metadata_mapping.py +117 -90
  10. eodag/api/search_result.py +13 -23
  11. eodag/cli.py +26 -5
  12. eodag/config.py +86 -92
  13. eodag/plugins/apis/base.py +1 -1
  14. eodag/plugins/apis/ecmwf.py +42 -22
  15. eodag/plugins/apis/usgs.py +17 -16
  16. eodag/plugins/authentication/aws_auth.py +16 -13
  17. eodag/plugins/authentication/base.py +5 -3
  18. eodag/plugins/authentication/header.py +3 -3
  19. eodag/plugins/authentication/keycloak.py +4 -4
  20. eodag/plugins/authentication/oauth.py +7 -3
  21. eodag/plugins/authentication/openid_connect.py +22 -16
  22. eodag/plugins/authentication/sas_auth.py +4 -4
  23. eodag/plugins/authentication/token.py +41 -10
  24. eodag/plugins/authentication/token_exchange.py +1 -1
  25. eodag/plugins/base.py +4 -4
  26. eodag/plugins/crunch/base.py +4 -4
  27. eodag/plugins/crunch/filter_date.py +4 -4
  28. eodag/plugins/crunch/filter_latest_intersect.py +6 -6
  29. eodag/plugins/crunch/filter_latest_tpl_name.py +7 -7
  30. eodag/plugins/crunch/filter_overlap.py +4 -4
  31. eodag/plugins/crunch/filter_property.py +6 -7
  32. eodag/plugins/download/aws.py +146 -87
  33. eodag/plugins/download/base.py +38 -56
  34. eodag/plugins/download/creodias_s3.py +29 -0
  35. eodag/plugins/download/http.py +173 -183
  36. eodag/plugins/download/s3rest.py +10 -11
  37. eodag/plugins/manager.py +10 -20
  38. eodag/plugins/search/__init__.py +6 -5
  39. eodag/plugins/search/base.py +90 -46
  40. eodag/plugins/search/build_search_result.py +1048 -361
  41. eodag/plugins/search/cop_marine.py +22 -12
  42. eodag/plugins/search/creodias_s3.py +9 -73
  43. eodag/plugins/search/csw.py +11 -11
  44. eodag/plugins/search/data_request_search.py +19 -18
  45. eodag/plugins/search/qssearch.py +99 -258
  46. eodag/plugins/search/stac_list_assets.py +85 -0
  47. eodag/plugins/search/static_stac_search.py +4 -4
  48. eodag/resources/ext_product_types.json +1 -1
  49. eodag/resources/product_types.yml +1134 -325
  50. eodag/resources/providers.yml +906 -2006
  51. eodag/resources/stac_api.yml +2 -2
  52. eodag/resources/user_conf_template.yml +10 -9
  53. eodag/rest/cache.py +2 -2
  54. eodag/rest/config.py +3 -3
  55. eodag/rest/core.py +112 -82
  56. eodag/rest/errors.py +5 -5
  57. eodag/rest/server.py +33 -14
  58. eodag/rest/stac.py +41 -38
  59. eodag/rest/types/collections_search.py +3 -3
  60. eodag/rest/types/eodag_search.py +29 -23
  61. eodag/rest/types/queryables.py +42 -31
  62. eodag/rest/types/stac_search.py +15 -25
  63. eodag/rest/utils/__init__.py +14 -21
  64. eodag/rest/utils/cql_evaluate.py +6 -6
  65. eodag/rest/utils/rfc3339.py +2 -2
  66. eodag/types/__init__.py +141 -32
  67. eodag/types/bbox.py +2 -2
  68. eodag/types/download_args.py +3 -3
  69. eodag/types/queryables.py +183 -72
  70. eodag/types/search_args.py +4 -4
  71. eodag/types/whoosh.py +127 -3
  72. eodag/utils/__init__.py +153 -51
  73. eodag/utils/exceptions.py +28 -21
  74. eodag/utils/import_system.py +2 -2
  75. eodag/utils/repr.py +65 -6
  76. eodag/utils/requests.py +13 -13
  77. eodag/utils/rest.py +2 -2
  78. eodag/utils/s3.py +231 -0
  79. eodag/utils/stac_reader.py +10 -10
  80. {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/METADATA +77 -76
  81. eodag-3.1.0.dist-info/RECORD +113 -0
  82. {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/WHEEL +1 -1
  83. {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/entry_points.txt +4 -2
  84. eodag/utils/constraints.py +0 -244
  85. eodag-3.0.1.dist-info/RECORD +0 -109
  86. {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/LICENSE +0 -0
  87. {eodag-3.0.1.dist-info → eodag-3.1.0.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,7 @@ import logging
22
22
  import os
23
23
  import re
24
24
  from datetime import datetime
25
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast
25
+ from typing import TYPE_CHECKING, Any, Optional, cast
26
26
  from urllib.parse import urlsplit
27
27
 
28
28
  import boto3
@@ -69,8 +69,8 @@ def _get_date_from_yyyymmdd(date_str: str, item_key: str) -> Optional[datetime]:
69
69
 
70
70
 
71
71
  def _get_dates_from_dataset_data(
72
- dataset_item: Dict[str, Any]
73
- ) -> Optional[Dict[str, str]]:
72
+ dataset_item: dict[str, Any]
73
+ ) -> Optional[dict[str, str]]:
74
74
  dates = {}
75
75
  if "start_datetime" in dataset_item["properties"]:
76
76
  dates["start"] = dataset_item["properties"]["start_datetime"]
@@ -96,7 +96,7 @@ def _get_s3_client(endpoint_url: str) -> S3Client:
96
96
  )
97
97
 
98
98
 
99
- def _check_int_values_properties(properties: Dict[str, Any]):
99
+ def _check_int_values_properties(properties: dict[str, Any]):
100
100
  # remove int values with a bit length of more than 64 from the properties
101
101
  invalid = []
102
102
  for prop, prop_value in properties.items():
@@ -134,7 +134,7 @@ class CopMarineSearch(StaticStacSearch):
134
134
 
135
135
  def _get_product_type_info(
136
136
  self, product_type: str
137
- ) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
137
+ ) -> tuple[dict[str, Any], list[dict[str, Any]]]:
138
138
  """Fetch product type and associated datasets info"""
139
139
 
140
140
  fetch_url = cast(str, self.config.discover_product_types["fetch_url"]).format(
@@ -183,13 +183,23 @@ class CopMarineSearch(StaticStacSearch):
183
183
  product_id: str,
184
184
  s3_url: str,
185
185
  product_type: str,
186
- dataset_item: Dict[str, Any],
187
- collection_dict: Dict[str, Any],
186
+ dataset_item: dict[str, Any],
187
+ collection_dict: dict[str, Any],
188
188
  ):
189
+ # try to find date(s) in product id
190
+ item_dates = re.findall(r"(\d{4})(0[1-9]|1[0-2])([0-3]\d)", product_id)
191
+ if not item_dates:
192
+ item_dates = re.findall(r"_(\d{4})(0[1-9]|1[0-2])", product_id)
193
+ use_dataset_dates = not bool(item_dates)
189
194
  for obj in collection_objects["Contents"]:
190
195
  if product_id in obj["Key"]:
191
196
  return self._create_product(
192
- product_type, obj["Key"], s3_url, dataset_item, collection_dict
197
+ product_type,
198
+ obj["Key"],
199
+ s3_url,
200
+ dataset_item,
201
+ collection_dict,
202
+ use_dataset_dates,
193
203
  )
194
204
  return None
195
205
 
@@ -198,8 +208,8 @@ class CopMarineSearch(StaticStacSearch):
198
208
  product_type: str,
199
209
  item_key: str,
200
210
  s3_url: str,
201
- dataset_item: Dict[str, Any],
202
- collection_dict: Dict[str, Any],
211
+ dataset_item: dict[str, Any],
212
+ collection_dict: dict[str, Any],
203
213
  use_dataset_dates: bool = False,
204
214
  ) -> Optional[EOProduct]:
205
215
 
@@ -278,7 +288,7 @@ class CopMarineSearch(StaticStacSearch):
278
288
  self,
279
289
  prep: PreparedSearch = PreparedSearch(),
280
290
  **kwargs: Any,
281
- ) -> Tuple[List[EOProduct], Optional[int]]:
291
+ ) -> tuple[list[EOProduct], Optional[int]]:
282
292
  """
283
293
  Implementation of search for the Copernicus Marine provider
284
294
  :param prep: object containing search parameterds
@@ -298,7 +308,7 @@ class CopMarineSearch(StaticStacSearch):
298
308
  "parameter product type is required for search with cop_marine provider"
299
309
  )
300
310
  collection_dict, datasets_items_list = self._get_product_type_info(product_type)
301
- products: List[EOProduct] = []
311
+ products: list[EOProduct] = []
302
312
  start_index = items_per_page * (page - 1) + 1
303
313
  num_total = 0
304
314
  for i, dataset_item in enumerate(datasets_items_list):
@@ -17,31 +17,22 @@
17
17
  # limitations under the License.
18
18
  import logging
19
19
  from types import MethodType
20
- from typing import Any, List
20
+ from typing import Any
21
21
 
22
- import boto3
23
- import botocore
24
22
  from botocore.exceptions import BotoCoreError
25
23
 
26
- from eodag.api.product import AssetsDict, EOProduct # type: ignore
24
+ from eodag.api.product import EOProduct # type: ignore
27
25
  from eodag.api.search_result import RawSearchResult
28
- from eodag.config import PluginConfig
29
- from eodag.plugins.authentication.aws_auth import AwsAuth
30
26
  from eodag.plugins.search.qssearch import ODataV4Search
31
- from eodag.utils import guess_file_type
32
- from eodag.utils.exceptions import (
33
- AuthenticationError,
34
- MisconfiguredError,
35
- NotAvailableError,
36
- RequestError,
37
- )
27
+ from eodag.utils.exceptions import RequestError
28
+ from eodag.utils.s3 import update_assets_from_s3
38
29
 
39
- DATA_EXTENSIONS = ["jp2", "tiff", "nc", "grib"]
40
30
  logger = logging.getLogger("eodag.search.creodiass3")
41
31
 
42
32
 
43
33
  def patched_register_downloader(self, downloader, authenticator):
44
34
  """Add the download information to the product.
35
+
45
36
  :param self: product to which information should be added
46
37
  :param downloader: The download method that it can use
47
38
  :class:`~eodag.plugins.download.base.Download` or
@@ -53,68 +44,13 @@ def patched_register_downloader(self, downloader, authenticator):
53
44
  self.register_downloader_only(downloader, authenticator)
54
45
  # and also update assets
55
46
  try:
56
- _update_assets(self, downloader.config, authenticator)
47
+ update_assets_from_s3(
48
+ self, authenticator, getattr(downloader.config, "s3_endpoint", None)
49
+ )
57
50
  except BotoCoreError as e:
58
51
  raise RequestError.from_error(e, "could not update assets") from e
59
52
 
60
53
 
61
- def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
62
- product.assets = {}
63
- prefix = (
64
- product.properties.get("productIdentifier", None).replace("/eodata/", "") + "/"
65
- )
66
- if prefix:
67
- try:
68
- auth_dict = auth.authenticate()
69
- required_creds = ["aws_access_key_id", "aws_secret_access_key"]
70
- if not all(x in auth_dict for x in required_creds):
71
- raise MisconfiguredError(
72
- f"Incomplete credentials for {product.provider}, missing "
73
- f"{[x for x in required_creds if x not in auth_dict]}"
74
- )
75
- if not getattr(auth, "s3_client", None):
76
- auth.s3_client = boto3.client(
77
- "s3",
78
- endpoint_url=config.s3_endpoint,
79
- aws_access_key_id=auth_dict["aws_access_key_id"],
80
- aws_secret_access_key=auth_dict["aws_secret_access_key"],
81
- )
82
- logger.debug("Listing assets in %s", prefix)
83
- product.assets = AssetsDict(product)
84
- for asset in auth.s3_client.list_objects(
85
- Bucket=config.s3_bucket, Prefix=prefix, MaxKeys=300
86
- )["Contents"]:
87
- asset_basename = (
88
- asset["Key"].split("/")[-1] if "/" in asset["Key"] else asset["Key"]
89
- )
90
-
91
- if len(asset_basename) > 0 and asset_basename not in product.assets:
92
- role = (
93
- "data"
94
- if asset_basename.split(".")[-1] in DATA_EXTENSIONS
95
- else "metadata"
96
- )
97
-
98
- product.assets[asset_basename] = {
99
- "title": asset_basename,
100
- "roles": [role],
101
- "href": f"s3://{config.s3_bucket}/{asset['Key']}",
102
- }
103
- if mime_type := guess_file_type(asset["Key"]):
104
- product.assets[asset_basename]["type"] = mime_type
105
- # update driver
106
- product.driver = product.get_driver()
107
-
108
- except botocore.exceptions.ClientError as e:
109
- if str(auth.config.auth_error_code) in str(e):
110
- raise AuthenticationError(
111
- f"Authentication failed on {config.base_uri} s3"
112
- ) from e
113
- raise NotAvailableError(
114
- f"assets for product {prefix} could not be found"
115
- ) from e
116
-
117
-
118
54
  class CreodiasS3Search(ODataV4Search):
119
55
  """
120
56
  ``CreodiasS3Search`` is an extension of :class:`~eodag.plugins.search.qssearch.ODataV4Search`,
@@ -133,7 +69,7 @@ class CreodiasS3Search(ODataV4Search):
133
69
 
134
70
  def normalize_results(
135
71
  self, results: RawSearchResult, **kwargs: Any
136
- ) -> List[EOProduct]:
72
+ ) -> list[EOProduct]:
137
73
  """Build EOProducts from provider results"""
138
74
 
139
75
  products = super(CreodiasS3Search, self).normalize_results(results, **kwargs)
@@ -19,7 +19,7 @@ from __future__ import annotations
19
19
 
20
20
  import logging
21
21
  import re
22
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
22
+ from typing import TYPE_CHECKING, Any, Optional, Union
23
23
 
24
24
  import pyproj
25
25
  from owslib.csw import CatalogueServiceWeb
@@ -60,13 +60,13 @@ class CSWSearch(Search):
60
60
  * :attr:`~eodag.config.PluginConfig.api_endpoint` (``str``) (**mandatory**): The endpoint of the
61
61
  provider's search interface
62
62
  * :attr:`~eodag.config.PluginConfig.version` (``str``): OGC Catalogue Service version; default: ``2.0.2``
63
- * :attr:`~eodag.config.PluginConfig.search_definition` (``Dict[str, Any]``) (**mandatory**):
63
+ * :attr:`~eodag.config.PluginConfig.search_definition` (``dict[str, Any]``) (**mandatory**):
64
64
 
65
- * **product_type_tags** (``List[Dict[str, Any]``): dict of product type tags
65
+ * **product_type_tags** (``list[dict[str, Any]``): dict of product type tags
66
66
  * **resource_location_filter** (``str``): regex string
67
- * **date_tags** (``Dict[str, Any]``): tags for start and end
67
+ * **date_tags** (``dict[str, Any]``): tags for start and end
68
68
 
69
- * :attr:`~eodag.config.PluginConfig.metadata_mapping` (``Dict[str, Any]``): The search plugins of this kind can
69
+ * :attr:`~eodag.config.PluginConfig.metadata_mapping` (``dict[str, Any]``): The search plugins of this kind can
70
70
  detect when a metadata mapping is "query-able", and get the semantics of how to format the query string
71
71
  parameter that enables to make a query on the corresponding metadata. To make a metadata query-able,
72
72
  just configure it in the metadata mapping to be a list of 2 items, the first one being the
@@ -107,7 +107,7 @@ class CSWSearch(Search):
107
107
  self,
108
108
  prep: PreparedSearch = PreparedSearch(),
109
109
  **kwargs: Any,
110
- ) -> Tuple[List[EOProduct], Optional[int]]:
110
+ ) -> tuple[list[EOProduct], Optional[int]]:
111
111
  """Perform a search on a OGC/CSW-like interface"""
112
112
  product_type = kwargs.get("productType")
113
113
  if product_type is None:
@@ -117,7 +117,7 @@ class CSWSearch(Search):
117
117
  self.__init_catalog(**getattr(auth.config, "credentials", {}))
118
118
  else:
119
119
  self.__init_catalog()
120
- results: List[EOProduct] = []
120
+ results: list[EOProduct] = []
121
121
  if self.catalog:
122
122
  provider_product_type = self.config.products[product_type]["productType"]
123
123
  for product_type_def in self.config.search_definition["product_type_tags"]:
@@ -229,12 +229,12 @@ class CSWSearch(Search):
229
229
 
230
230
  def __convert_query_params(
231
231
  self,
232
- product_type_def: Dict[str, Any],
232
+ product_type_def: dict[str, Any],
233
233
  product_type: str,
234
- params: Dict[str, Any],
235
- ) -> Union[List[OgcExpression], List[List[OgcExpression]]]:
234
+ params: dict[str, Any],
235
+ ) -> Union[list[OgcExpression], list[list[OgcExpression]]]:
236
236
  """Translates eodag search to CSW constraints using owslib constraint classes"""
237
- constraints: List[OgcExpression] = []
237
+ constraints: list[OgcExpression] = []
238
238
  # How the match should be performed (fuzzy, prefix, postfix or exact).
239
239
  # defaults to fuzzy
240
240
  pt_tag, matching = (
@@ -20,7 +20,7 @@ from __future__ import annotations
20
20
  import logging
21
21
  import time
22
22
  from datetime import datetime, timedelta, timezone
23
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast
23
+ from typing import TYPE_CHECKING, Any, Optional, cast
24
24
 
25
25
  import requests
26
26
 
@@ -36,6 +36,7 @@ from eodag.utils import (
36
36
  DEFAULT_ITEMS_PER_PAGE,
37
37
  DEFAULT_MISSION_START_DATE,
38
38
  DEFAULT_PAGE,
39
+ DEFAULT_SEARCH_TIMEOUT,
39
40
  GENERIC_PRODUCT_TYPE,
40
41
  HTTP_REQ_TIMEOUT,
41
42
  USER_AGENT,
@@ -113,10 +114,10 @@ class DataRequestSearch(Search):
113
114
  * :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.generic_product_type_id` (``str``): mapping for the
114
115
  product type id
115
116
  * :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.generic_product_type_parsable_metadata`
116
- (``Dict[str, str]``): mapping for product type metadata (e.g. ``abstract``, ``licence``) which can be parsed
117
+ (``dict[str, str]``): mapping for product type metadata (e.g. ``abstract``, ``licence``) which can be parsed
117
118
  from the provider result
118
119
  * :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.generic_product_type_parsable_properties`
119
- (``Dict[str, str]``): mapping for product type properties which can be parsed from the result that are not
120
+ (``dict[str, str]``): mapping for product type properties which can be parsed from the result and are not
120
121
  product type metadata
121
122
  * :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.single_collection_fetch_url` (``str``): url to fetch
122
123
  data for a single collection; used if product type metadata is not available from the endpoint given in
@@ -125,7 +126,7 @@ class DataRequestSearch(Search):
125
126
  to be added to the :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.fetch_url` to filter for a
126
127
  collection
127
128
  * :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.single_product_type_parsable_metadata`
128
- (``Dict[str, str]``): mapping for product type metadata returned by the endpoint given in
129
+ (``dict[str, str]``): mapping for product type metadata returned by the endpoint given in
129
130
  :attr:`~eodag.config.PluginConfig.DiscoverProductTypes.single_collection_fetch_url`.
130
131
 
131
132
  * :attr:`~eodag.config.PluginConfig.constraints_file_url` (``str``): url to fetch the constraints for a specific
@@ -133,7 +134,7 @@ class DataRequestSearch(Search):
133
134
  * :attr:`~eodag.config.PluginConfig.constraints_entry` (``str``): key in the json result where the constraints
134
135
  can be found; if not given, it is assumed that the constraints are on top level of the result, i.e.
135
136
  the result is an array of constraints
136
- * :attr:`~eodag.config.PluginConfig.metadata_mapping` (``Dict[str, Any]``): The search plugins of this kind can
137
+ * :attr:`~eodag.config.PluginConfig.metadata_mapping` (``dict[str, Any]``): The search plugins of this kind can
137
138
  detect when a metadata mapping is "query-able", and get the semantics of how to format the query string
138
139
  parameter that enables to make a query on the corresponding metadata. To make a metadata query-able,
139
140
  just configure it in the metadata mapping to be a list of 2 items, the first one being the
@@ -186,7 +187,7 @@ class DataRequestSearch(Search):
186
187
  )
187
188
  if other_product_for_mapping:
188
189
  other_product_type_def_params = self.get_product_type_def_params(
189
- other_product_for_mapping, # **kwargs
190
+ other_product_for_mapping,
190
191
  )
191
192
  product_type_metadata_mapping.update(
192
193
  other_product_type_def_params.get("metadata_mapping", {})
@@ -207,10 +208,10 @@ class DataRequestSearch(Search):
207
208
  self.config.pagination["next_page_url_key_path"] = string_to_jsonpath(
208
209
  self.config.pagination.get("next_page_url_key_path", None)
209
210
  )
210
- self.download_info: Dict[str, Any] = {}
211
+ self.download_info: dict[str, Any] = {}
211
212
  self.data_request_id = None
212
213
 
213
- def discover_product_types(self, **kwargs: Any) -> Optional[Dict[str, Any]]:
214
+ def discover_product_types(self, **kwargs: Any) -> Optional[dict[str, Any]]:
214
215
  """Fetch product types is disabled for `DataRequestSearch`
215
216
 
216
217
  :returns: empty dict
@@ -226,7 +227,7 @@ class DataRequestSearch(Search):
226
227
  self,
227
228
  prep: PreparedSearch = PreparedSearch(),
228
229
  **kwargs: Any,
229
- ) -> Tuple[List[EOProduct], Optional[int]]:
230
+ ) -> tuple[list[EOProduct], Optional[int]]:
230
231
  """
231
232
  performs the search for a provider where several steps are required to fetch the data
232
233
  """
@@ -252,7 +253,7 @@ class DataRequestSearch(Search):
252
253
 
253
254
  # provider product type specific conf
254
255
  self.product_type_def_params = self.get_product_type_def_params(
255
- product_type, **kwargs
256
+ product_type, format_variables=kwargs
256
257
  )
257
258
 
258
259
  # update config using provider product type definition metadata_mapping
@@ -262,7 +263,7 @@ class DataRequestSearch(Search):
262
263
  )
263
264
  if other_product_for_mapping:
264
265
  other_product_type_def_params = self.get_product_type_def_params(
265
- other_product_for_mapping, **kwargs
266
+ other_product_for_mapping, format_variables=kwargs
266
267
  )
267
268
  self.config.metadata_mapping.update(
268
269
  other_product_type_def_params.get("metadata_mapping", {})
@@ -308,7 +309,7 @@ class DataRequestSearch(Search):
308
309
  request_finished = True
309
310
 
310
311
  # loop to check search job status
311
- search_timeout = int(getattr(self.config, "timeout", HTTP_REQ_TIMEOUT))
312
+ search_timeout = int(getattr(self.config, "timeout", DEFAULT_SEARCH_TIMEOUT))
312
313
  logger.info(
313
314
  f"checking status of request job {data_request_id} (timeout={search_timeout}s)"
314
315
  )
@@ -431,7 +432,7 @@ class DataRequestSearch(Search):
431
432
 
432
433
  def _get_result_data(
433
434
  self, data_request_id: str, items_per_page: int, page: int
434
- ) -> Dict[str, Any]:
435
+ ) -> dict[str, Any]:
435
436
  page = page - 1 + self.config.pagination.get("start_page", 1)
436
437
  url = self.config.result_url.format(
437
438
  jobId=data_request_id, items_per_page=items_per_page, page=page
@@ -450,18 +451,18 @@ class DataRequestSearch(Search):
450
451
 
451
452
  def _convert_result_data(
452
453
  self,
453
- result_data: Dict[str, Any],
454
+ result_data: dict[str, Any],
454
455
  data_request_id: str,
455
456
  product_type: str,
456
457
  **kwargs: Any,
457
- ) -> Tuple[List[EOProduct], int]:
458
+ ) -> tuple[list[EOProduct], int]:
458
459
  """Build EOProducts from provider results"""
459
460
  results_entry = self.config.results_entry
460
461
  results = result_data[results_entry]
461
462
  logger.debug(
462
463
  "Adapting %s plugin results to eodag product representation" % len(results)
463
464
  )
464
- products: List[EOProduct] = []
465
+ products: list[EOProduct] = []
465
466
  for result in results:
466
467
  product = EOProduct(
467
468
  self.provider,
@@ -517,8 +518,8 @@ class DataRequestSearch(Search):
517
518
  return False
518
519
 
519
520
  def _apply_additional_filters(
520
- self, result: Dict[str, Any], custom_filters: Dict[str, str]
521
- ) -> Dict[str, Any]:
521
+ self, result: dict[str, Any], custom_filters: dict[str, str]
522
+ ) -> dict[str, Any]:
522
523
  filtered_result = []
523
524
  results_entry = self.config.results_entry
524
525
  results = result[results_entry]