eodag 2.12.0__py3-none-any.whl → 3.0.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/__init__.py +6 -8
- eodag/api/core.py +654 -538
- eodag/api/product/__init__.py +12 -2
- eodag/api/product/_assets.py +59 -16
- eodag/api/product/_product.py +100 -93
- eodag/api/product/drivers/__init__.py +7 -2
- eodag/api/product/drivers/base.py +0 -3
- eodag/api/product/metadata_mapping.py +192 -96
- eodag/api/search_result.py +69 -10
- eodag/cli.py +55 -25
- eodag/config.py +391 -116
- eodag/plugins/apis/base.py +11 -165
- eodag/plugins/apis/ecmwf.py +36 -25
- eodag/plugins/apis/usgs.py +80 -35
- eodag/plugins/authentication/aws_auth.py +13 -4
- eodag/plugins/authentication/base.py +10 -1
- eodag/plugins/authentication/generic.py +2 -2
- eodag/plugins/authentication/header.py +31 -6
- eodag/plugins/authentication/keycloak.py +17 -84
- eodag/plugins/authentication/oauth.py +3 -3
- eodag/plugins/authentication/openid_connect.py +268 -49
- eodag/plugins/authentication/qsauth.py +4 -1
- eodag/plugins/authentication/sas_auth.py +9 -2
- eodag/plugins/authentication/token.py +98 -47
- eodag/plugins/authentication/token_exchange.py +122 -0
- eodag/plugins/crunch/base.py +3 -1
- eodag/plugins/crunch/filter_date.py +3 -9
- eodag/plugins/crunch/filter_latest_intersect.py +0 -3
- eodag/plugins/crunch/filter_latest_tpl_name.py +1 -4
- eodag/plugins/crunch/filter_overlap.py +4 -8
- eodag/plugins/crunch/filter_property.py +5 -11
- eodag/plugins/download/aws.py +149 -185
- eodag/plugins/download/base.py +88 -97
- eodag/plugins/download/creodias_s3.py +1 -1
- eodag/plugins/download/http.py +638 -310
- eodag/plugins/download/s3rest.py +47 -45
- eodag/plugins/manager.py +228 -88
- eodag/plugins/search/__init__.py +36 -0
- eodag/plugins/search/base.py +239 -30
- eodag/plugins/search/build_search_result.py +382 -37
- eodag/plugins/search/cop_marine.py +441 -0
- eodag/plugins/search/creodias_s3.py +25 -20
- eodag/plugins/search/csw.py +5 -7
- eodag/plugins/search/data_request_search.py +61 -30
- eodag/plugins/search/qssearch.py +713 -255
- eodag/plugins/search/static_stac_search.py +106 -40
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +1921 -34
- eodag/resources/providers.yml +4091 -3655
- eodag/resources/stac.yml +50 -216
- eodag/resources/stac_api.yml +71 -25
- eodag/resources/stac_provider.yml +5 -0
- eodag/resources/user_conf_template.yml +89 -32
- eodag/rest/__init__.py +6 -0
- eodag/rest/cache.py +70 -0
- eodag/rest/config.py +68 -0
- eodag/rest/constants.py +26 -0
- eodag/rest/core.py +735 -0
- eodag/rest/errors.py +178 -0
- eodag/rest/server.py +264 -431
- eodag/rest/stac.py +442 -836
- eodag/rest/types/collections_search.py +44 -0
- eodag/rest/types/eodag_search.py +238 -47
- eodag/rest/types/queryables.py +164 -0
- eodag/rest/types/stac_search.py +273 -0
- eodag/rest/utils/__init__.py +216 -0
- eodag/rest/utils/cql_evaluate.py +119 -0
- eodag/rest/utils/rfc3339.py +64 -0
- eodag/types/__init__.py +106 -10
- eodag/types/bbox.py +15 -14
- eodag/types/download_args.py +40 -0
- eodag/types/search_args.py +57 -7
- eodag/types/whoosh.py +79 -0
- eodag/utils/__init__.py +110 -91
- eodag/utils/constraints.py +37 -45
- eodag/utils/exceptions.py +39 -22
- eodag/utils/import_system.py +0 -4
- eodag/utils/logging.py +37 -80
- eodag/utils/notebook.py +4 -4
- eodag/utils/repr.py +113 -0
- eodag/utils/requests.py +128 -0
- eodag/utils/rest.py +100 -0
- eodag/utils/stac_reader.py +93 -21
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/METADATA +88 -53
- eodag-3.0.0.dist-info/RECORD +109 -0
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/WHEEL +1 -1
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/entry_points.txt +7 -5
- eodag/plugins/apis/cds.py +0 -540
- eodag/rest/types/stac_queryables.py +0 -134
- eodag/rest/utils.py +0 -1133
- eodag-2.12.0.dist-info/RECORD +0 -94
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/LICENSE +0 -0
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/top_level.txt +0 -0
eodag/plugins/manager.py
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import logging
|
|
21
|
+
import re
|
|
21
22
|
from operator import attrgetter
|
|
22
23
|
from pathlib import Path
|
|
23
24
|
from typing import (
|
|
@@ -35,17 +36,28 @@ from typing import (
|
|
|
35
36
|
|
|
36
37
|
import pkg_resources
|
|
37
38
|
|
|
38
|
-
from eodag.config import
|
|
39
|
+
from eodag.config import (
|
|
40
|
+
AUTH_TOPIC_KEYS,
|
|
41
|
+
PLUGINS_TOPICS_KEYS,
|
|
42
|
+
load_config,
|
|
43
|
+
merge_configs,
|
|
44
|
+
)
|
|
39
45
|
from eodag.plugins.apis.base import Api
|
|
40
46
|
from eodag.plugins.authentication.base import Authentication
|
|
41
47
|
from eodag.plugins.base import EODAGPluginMount
|
|
42
48
|
from eodag.plugins.crunch.base import Crunch
|
|
43
49
|
from eodag.plugins.download.base import Download
|
|
44
50
|
from eodag.plugins.search.base import Search
|
|
45
|
-
from eodag.utils import GENERIC_PRODUCT_TYPE
|
|
46
|
-
from eodag.utils.exceptions import
|
|
51
|
+
from eodag.utils import GENERIC_PRODUCT_TYPE, deepcopy, dict_md5sum
|
|
52
|
+
from eodag.utils.exceptions import (
|
|
53
|
+
AuthenticationError,
|
|
54
|
+
MisconfiguredError,
|
|
55
|
+
UnsupportedProvider,
|
|
56
|
+
)
|
|
47
57
|
|
|
48
58
|
if TYPE_CHECKING:
|
|
59
|
+
from requests.auth import AuthBase
|
|
60
|
+
|
|
49
61
|
from eodag.api.product import EOProduct
|
|
50
62
|
from eodag.config import PluginConfig, ProviderConfig
|
|
51
63
|
from eodag.plugins.base import PluginTopic
|
|
@@ -68,12 +80,16 @@ class PluginManager:
|
|
|
68
80
|
|
|
69
81
|
:param providers_config: The configuration with all information about the providers
|
|
70
82
|
supported by ``eodag``
|
|
71
|
-
:type providers_config: dict[str, :class:`~eodag.config.ProviderConfig`]
|
|
72
83
|
"""
|
|
73
84
|
|
|
74
|
-
supported_topics =
|
|
85
|
+
supported_topics = set(PLUGINS_TOPICS_KEYS)
|
|
86
|
+
|
|
87
|
+
product_type_to_provider_config_map: Dict[str, List[ProviderConfig]]
|
|
88
|
+
|
|
89
|
+
skipped_plugins: List[str]
|
|
75
90
|
|
|
76
91
|
def __init__(self, providers_config: Dict[str, ProviderConfig]) -> None:
|
|
92
|
+
self.skipped_plugins = []
|
|
77
93
|
self.providers_config = providers_config
|
|
78
94
|
# Load all the plugins. This will make all plugin classes of a particular
|
|
79
95
|
# type to be available in the base plugin class's 'plugins' attribute.
|
|
@@ -90,6 +106,13 @@ class PluginManager:
|
|
|
90
106
|
):
|
|
91
107
|
try:
|
|
92
108
|
entry_point.load()
|
|
109
|
+
except pkg_resources.DistributionNotFound:
|
|
110
|
+
logger.debug(
|
|
111
|
+
"%s plugin skipped, eodag[%s] or eodag[all] needed",
|
|
112
|
+
entry_point.name,
|
|
113
|
+
",".join(entry_point.extras),
|
|
114
|
+
)
|
|
115
|
+
self.skipped_plugins.append(entry_point.name)
|
|
93
116
|
except ImportError:
|
|
94
117
|
import traceback as tb
|
|
95
118
|
|
|
@@ -99,7 +122,11 @@ class PluginManager:
|
|
|
99
122
|
"Check that the plugin module (%s) is importable",
|
|
100
123
|
entry_point.module_name,
|
|
101
124
|
)
|
|
102
|
-
if
|
|
125
|
+
if (
|
|
126
|
+
entry_point.dist
|
|
127
|
+
and entry_point.dist.key != "eodag"
|
|
128
|
+
and entry_point.dist.location is not None
|
|
129
|
+
):
|
|
103
130
|
# use plugin providers if any
|
|
104
131
|
plugin_providers_config_path = [
|
|
105
132
|
str(x)
|
|
@@ -116,23 +143,25 @@ class PluginManager:
|
|
|
116
143
|
self.providers_config = plugin_providers_config
|
|
117
144
|
self.rebuild()
|
|
118
145
|
|
|
119
|
-
def rebuild(
|
|
146
|
+
def rebuild(
|
|
147
|
+
self, providers_config: Optional[Dict[str, ProviderConfig]] = None
|
|
148
|
+
) -> None:
|
|
120
149
|
"""(Re)Build plugin manager mapping and cache"""
|
|
121
150
|
if providers_config is not None:
|
|
122
151
|
self.providers_config = providers_config
|
|
123
152
|
|
|
124
153
|
self.build_product_type_to_provider_config_map()
|
|
125
|
-
self._built_plugins_cache: Dict[Tuple[str, str], Any] = {}
|
|
154
|
+
self._built_plugins_cache: Dict[Tuple[str, str, str], Any] = {}
|
|
126
155
|
|
|
127
156
|
def build_product_type_to_provider_config_map(self) -> None:
|
|
128
157
|
"""Build mapping conf between product types and providers"""
|
|
129
|
-
self.product_type_to_provider_config_map
|
|
158
|
+
self.product_type_to_provider_config_map = {}
|
|
130
159
|
for provider in list(self.providers_config):
|
|
131
160
|
provider_config = self.providers_config[provider]
|
|
132
161
|
if not hasattr(provider_config, "products") or not provider_config.products:
|
|
133
162
|
logger.info(
|
|
134
|
-
"%s: provider has no product configured and will be skipped"
|
|
135
|
-
|
|
163
|
+
"%s: provider has no product configured and will be skipped",
|
|
164
|
+
provider,
|
|
136
165
|
)
|
|
137
166
|
self.providers_config.pop(provider)
|
|
138
167
|
continue
|
|
@@ -158,103 +187,211 @@ class PluginManager:
|
|
|
158
187
|
|
|
159
188
|
:param product_type: (optional) The product type that the constructed plugins
|
|
160
189
|
must support
|
|
161
|
-
:
|
|
162
|
-
|
|
163
|
-
:type provider: str
|
|
190
|
+
:param provider: (optional) The provider or the provider group on which to get
|
|
191
|
+
the search plugins
|
|
164
192
|
:returns: All the plugins supporting the product type, one by one (a generator
|
|
165
193
|
object)
|
|
166
|
-
|
|
194
|
+
or :class:`~eodag.plugins.download.Api`)
|
|
167
195
|
:raises: :class:`~eodag.utils.exceptions.UnsupportedProvider`
|
|
168
|
-
:raises: :class:`~eodag.utils.exceptions.UnsupportedProductType`
|
|
169
196
|
"""
|
|
170
197
|
|
|
171
198
|
def get_plugin() -> Union[Search, Api]:
|
|
172
199
|
plugin: Union[Search, Api]
|
|
173
|
-
|
|
200
|
+
if search := getattr(config, "search", None):
|
|
174
201
|
config.search.products = config.products
|
|
175
202
|
config.search.priority = config.priority
|
|
176
|
-
plugin = cast(
|
|
177
|
-
|
|
178
|
-
)
|
|
179
|
-
except AttributeError:
|
|
203
|
+
plugin = cast(Search, self._build_plugin(config.name, search, Search))
|
|
204
|
+
elif api := getattr(config, "api", None):
|
|
180
205
|
config.api.products = config.products
|
|
181
206
|
config.api.priority = config.priority
|
|
182
|
-
plugin = cast(Api, self._build_plugin(config.name,
|
|
207
|
+
plugin = cast(Api, self._build_plugin(config.name, api, Api))
|
|
208
|
+
else:
|
|
209
|
+
raise MisconfiguredError(
|
|
210
|
+
f"No search plugin configureed for {config.name}."
|
|
211
|
+
)
|
|
183
212
|
return plugin
|
|
184
213
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
except KeyError:
|
|
205
|
-
logger.info(
|
|
206
|
-
"UnsupportedProductType: %s, using generic settings", product_type
|
|
214
|
+
configs: Optional[List[ProviderConfig]]
|
|
215
|
+
if product_type:
|
|
216
|
+
configs = self.product_type_to_provider_config_map.get(product_type)
|
|
217
|
+
if not configs:
|
|
218
|
+
logger.info(
|
|
219
|
+
"UnsupportedProductType: %s, using generic settings", product_type
|
|
220
|
+
)
|
|
221
|
+
configs = self.product_type_to_provider_config_map[GENERIC_PRODUCT_TYPE]
|
|
222
|
+
else:
|
|
223
|
+
configs = list(self.providers_config.values())
|
|
224
|
+
|
|
225
|
+
if provider:
|
|
226
|
+
configs = [
|
|
227
|
+
c for c in configs if provider in [getattr(c, "group", None), c.name]
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
if not configs and product_type:
|
|
231
|
+
raise UnsupportedProvider(
|
|
232
|
+
f"{provider} is not (yet) supported for {product_type}"
|
|
207
233
|
)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
234
|
+
if not configs:
|
|
235
|
+
raise UnsupportedProvider(f"{provider} is not (yet) supported")
|
|
236
|
+
|
|
237
|
+
for config in sorted(configs, key=attrgetter("priority"), reverse=True):
|
|
238
|
+
yield get_plugin()
|
|
212
239
|
|
|
213
240
|
def get_download_plugin(self, product: EOProduct) -> Union[Download, Api]:
|
|
214
241
|
"""Build and return the download plugin capable of downloading the given
|
|
215
242
|
product.
|
|
216
243
|
|
|
217
244
|
:param product: The product to get a download plugin for
|
|
218
|
-
:type product: :class:`~eodag.api.product._product.EOProduct`
|
|
219
245
|
:returns: The download plugin capable of downloading the product
|
|
220
|
-
:rtype: :class:`~eodag.plugins.download.Download` or :class:`~eodag.plugins.download.Api`
|
|
221
246
|
"""
|
|
222
247
|
plugin_conf = self.providers_config[product.provider]
|
|
223
|
-
|
|
248
|
+
if download := getattr(plugin_conf, "download", None):
|
|
224
249
|
plugin_conf.download.priority = plugin_conf.priority
|
|
225
250
|
plugin = cast(
|
|
226
251
|
Download,
|
|
227
|
-
self._build_plugin(product.provider,
|
|
252
|
+
self._build_plugin(product.provider, download, Download),
|
|
228
253
|
)
|
|
229
|
-
|
|
230
|
-
|
|
254
|
+
elif api := getattr(plugin_conf, "api", None):
|
|
255
|
+
plugin_conf.api.products = plugin_conf.products
|
|
231
256
|
plugin_conf.api.priority = plugin_conf.priority
|
|
232
|
-
plugin = cast(
|
|
233
|
-
|
|
257
|
+
plugin = cast(Api, self._build_plugin(product.provider, api, Api))
|
|
258
|
+
else:
|
|
259
|
+
raise MisconfiguredError(
|
|
260
|
+
f"No download plugin configured for provider {plugin_conf.name}."
|
|
234
261
|
)
|
|
235
|
-
|
|
262
|
+
return plugin
|
|
263
|
+
|
|
264
|
+
def get_auth_plugin(
|
|
265
|
+
self, associated_plugin: PluginTopic, product: Optional[EOProduct] = None
|
|
266
|
+
) -> Optional[Authentication]:
|
|
267
|
+
"""Build and return the authentication plugin associated to the given
|
|
268
|
+
search/download plugin
|
|
269
|
+
|
|
270
|
+
.. versionchanged:: v3.0.0
|
|
271
|
+
``get_auth_plugin()`` now needs ``associated_plugin`` instead of ``provider``
|
|
272
|
+
as argument.
|
|
236
273
|
|
|
237
|
-
|
|
274
|
+
:param associated_plugin: The search/download plugin to which the authentication
|
|
275
|
+
plugin is linked
|
|
276
|
+
:param product: The product to download. ``None`` for search authentication
|
|
277
|
+
:returns: The Authentication plugin
|
|
278
|
+
"""
|
|
279
|
+
# matching url from product to download
|
|
280
|
+
if product is not None and len(product.assets) > 0:
|
|
281
|
+
matching_url = next(iter(product.assets.values()))["href"]
|
|
282
|
+
elif product is not None:
|
|
283
|
+
matching_url = product.properties.get(
|
|
284
|
+
"downloadLink"
|
|
285
|
+
) or product.properties.get("orderLink")
|
|
286
|
+
else:
|
|
287
|
+
# search auth
|
|
288
|
+
matching_url = getattr(associated_plugin.config, "api_endpoint", None)
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
auth_plugin = next(
|
|
292
|
+
self.get_auth_plugins(
|
|
293
|
+
associated_plugin.provider,
|
|
294
|
+
matching_url=matching_url,
|
|
295
|
+
matching_conf=associated_plugin.config,
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
except StopIteration:
|
|
299
|
+
auth_plugin = None
|
|
300
|
+
return auth_plugin
|
|
301
|
+
|
|
302
|
+
def get_auth_plugins(
|
|
303
|
+
self,
|
|
304
|
+
provider: str,
|
|
305
|
+
matching_url: Optional[str] = None,
|
|
306
|
+
matching_conf: Optional[PluginConfig] = None,
|
|
307
|
+
) -> Iterator[Authentication]:
|
|
238
308
|
"""Build and return the authentication plugin for the given product_type and
|
|
239
309
|
provider
|
|
240
310
|
|
|
241
311
|
:param provider: The provider for which to get the authentication plugin
|
|
242
|
-
:
|
|
243
|
-
:
|
|
244
|
-
:
|
|
312
|
+
:param matching_url: url to compare with plugin matching_url pattern
|
|
313
|
+
:param matching_conf: configuration to compare with plugin matching_conf
|
|
314
|
+
:returns: All the Authentication plugins for the given criteria
|
|
245
315
|
"""
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
316
|
+
auth_conf: Optional[PluginConfig] = None
|
|
317
|
+
|
|
318
|
+
def _is_auth_plugin_matching(
|
|
319
|
+
auth_conf: PluginConfig,
|
|
320
|
+
matching_url: Optional[str],
|
|
321
|
+
matching_conf: Optional[PluginConfig],
|
|
322
|
+
) -> bool:
|
|
323
|
+
plugin_matching_conf = getattr(auth_conf, "matching_conf", {})
|
|
324
|
+
if matching_conf:
|
|
325
|
+
if (
|
|
326
|
+
plugin_matching_conf
|
|
327
|
+
and matching_conf.__dict__.items() >= plugin_matching_conf.items()
|
|
328
|
+
):
|
|
329
|
+
# conf matches
|
|
330
|
+
return True
|
|
331
|
+
plugin_matching_url = getattr(auth_conf, "matching_url", None)
|
|
332
|
+
if matching_url:
|
|
333
|
+
if plugin_matching_url and re.match(
|
|
334
|
+
rf"{plugin_matching_url}", matching_url
|
|
335
|
+
):
|
|
336
|
+
# url matches
|
|
337
|
+
return True
|
|
338
|
+
if not plugin_matching_conf and not plugin_matching_url:
|
|
339
|
+
# plugin without match criteria
|
|
340
|
+
return True
|
|
341
|
+
else:
|
|
342
|
+
# no match
|
|
343
|
+
return False
|
|
344
|
+
|
|
345
|
+
# providers configs with given provider at first
|
|
346
|
+
sorted_providers_config = deepcopy(self.providers_config)
|
|
347
|
+
sorted_providers_config = {
|
|
348
|
+
provider: sorted_providers_config.pop(provider),
|
|
349
|
+
**sorted_providers_config,
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
for plugin_provider, provider_conf in sorted_providers_config.items():
|
|
353
|
+
for key in AUTH_TOPIC_KEYS:
|
|
354
|
+
auth_conf = getattr(provider_conf, key, None)
|
|
355
|
+
if auth_conf is None:
|
|
356
|
+
continue
|
|
357
|
+
if _is_auth_plugin_matching(auth_conf, matching_url, matching_conf):
|
|
358
|
+
auth_conf.priority = provider_conf.priority
|
|
359
|
+
plugin = cast(
|
|
360
|
+
Authentication,
|
|
361
|
+
self._build_plugin(plugin_provider, auth_conf, Authentication),
|
|
362
|
+
)
|
|
363
|
+
yield plugin
|
|
364
|
+
else:
|
|
365
|
+
continue
|
|
366
|
+
|
|
367
|
+
def get_auth(
|
|
368
|
+
self,
|
|
369
|
+
provider: str,
|
|
370
|
+
matching_url: Optional[str] = None,
|
|
371
|
+
matching_conf: Optional[PluginConfig] = None,
|
|
372
|
+
) -> Optional[Union[AuthBase, Dict[str, str]]]:
|
|
373
|
+
"""Authenticate and return the authenticated object for the first matching
|
|
374
|
+
authentication plugin
|
|
375
|
+
|
|
376
|
+
:param provider: The provider for which to get the authentication plugin
|
|
377
|
+
:param matching_url: url to compare with plugin matching_url pattern
|
|
378
|
+
:param matching_conf: configuration to compare with plugin matching_conf
|
|
379
|
+
:returns: All the Authentication plugins for the given criteria
|
|
380
|
+
"""
|
|
381
|
+
for auth_plugin in self.get_auth_plugins(provider, matching_url, matching_conf):
|
|
382
|
+
if auth_plugin and callable(getattr(auth_plugin, "authenticate", None)):
|
|
383
|
+
try:
|
|
384
|
+
auth = auth_plugin.authenticate()
|
|
385
|
+
return auth
|
|
386
|
+
except (AuthenticationError, MisconfiguredError) as e:
|
|
387
|
+
logger.debug(f"Could not authenticate on {provider}: {str(e)}")
|
|
388
|
+
continue
|
|
389
|
+
else:
|
|
390
|
+
logger.debug(
|
|
391
|
+
f"Could not authenticate on {provider} using {auth_plugin} plugin"
|
|
392
|
+
)
|
|
393
|
+
continue
|
|
394
|
+
return None
|
|
258
395
|
|
|
259
396
|
@staticmethod
|
|
260
397
|
def get_crunch_plugin(name: str, **options: Any) -> Crunch:
|
|
@@ -262,14 +399,11 @@ class PluginManager:
|
|
|
262
399
|
it with the `options`
|
|
263
400
|
|
|
264
401
|
:param name: The name of the Crunch plugin to instantiate
|
|
265
|
-
:type name: str
|
|
266
402
|
:param options: The configuration parameters of the cruncher
|
|
267
|
-
:type options: dict
|
|
268
403
|
:returns: The cruncher named `name`
|
|
269
|
-
:rtype: :class:`~eodag.plugins.crunch.Crunch`
|
|
270
404
|
"""
|
|
271
|
-
|
|
272
|
-
return
|
|
405
|
+
klass = Crunch.get_plugin_by_class_name(name)
|
|
406
|
+
return klass(options)
|
|
273
407
|
|
|
274
408
|
def sort_providers(self) -> None:
|
|
275
409
|
"""Sort providers taking into account current priority order"""
|
|
@@ -280,9 +414,7 @@ class PluginManager:
|
|
|
280
414
|
"""Set the priority of the given provider
|
|
281
415
|
|
|
282
416
|
:param provider: The provider which is assigned the priority
|
|
283
|
-
:type provider: str
|
|
284
417
|
:param priority: The priority to assign to the provider
|
|
285
|
-
:type priority: int
|
|
286
418
|
"""
|
|
287
419
|
# Update the priority in the configurations so that it is taken into account
|
|
288
420
|
# when a plugin of this provider is latterly built
|
|
@@ -296,9 +428,11 @@ class PluginManager:
|
|
|
296
428
|
# Sort the provider configs, taking into account the new priority order
|
|
297
429
|
provider_configs.sort(key=attrgetter("priority"), reverse=True)
|
|
298
430
|
# Update the priority of already built plugins of the given provider
|
|
299
|
-
for provider_name, topic_class in self._built_plugins_cache:
|
|
431
|
+
for provider_name, topic_class, auth_match_md5 in self._built_plugins_cache:
|
|
300
432
|
if provider_name == provider:
|
|
301
|
-
self._built_plugins_cache[
|
|
433
|
+
self._built_plugins_cache[
|
|
434
|
+
(provider, topic_class, auth_match_md5)
|
|
435
|
+
].priority = priority
|
|
302
436
|
|
|
303
437
|
def _build_plugin(
|
|
304
438
|
self,
|
|
@@ -310,19 +444,23 @@ class PluginManager:
|
|
|
310
444
|
registered as the given provider
|
|
311
445
|
|
|
312
446
|
:param provider: The provider for which to build the plugin
|
|
313
|
-
:type provider: str
|
|
314
447
|
:param plugin_conf: The configuration of the plugin to be built
|
|
315
|
-
:type plugin_conf: :class:`~eodag.config.PluginConfig`
|
|
316
448
|
:param topic_class: The type of plugin to build
|
|
317
|
-
:type topic_class: :class:`~eodag.plugin.base.PluginTopic`
|
|
318
449
|
:returns: The built plugin
|
|
319
|
-
:rtype: :class:`~eodag.plugin.search.Search` or
|
|
320
450
|
:class:`~eodag.plugin.download.Download` or
|
|
321
451
|
:class:`~eodag.plugin.authentication.Authentication` or
|
|
322
452
|
:class:`~eodag.plugin.crunch.Crunch`
|
|
323
453
|
"""
|
|
454
|
+
# md5 hash to helps identifying an auth plugin within several for a given provider
|
|
455
|
+
# (each has distinct matching settings)
|
|
456
|
+
auth_match_md5 = dict_md5sum(
|
|
457
|
+
{
|
|
458
|
+
"matching_url": getattr(plugin_conf, "matching_url", None),
|
|
459
|
+
"matching_conf": getattr(plugin_conf, "matching_conf", None),
|
|
460
|
+
}
|
|
461
|
+
)
|
|
324
462
|
cached_instance = self._built_plugins_cache.setdefault(
|
|
325
|
-
(provider, topic_class.__name__), None
|
|
463
|
+
(provider, topic_class.__name__, auth_match_md5), None
|
|
326
464
|
)
|
|
327
465
|
if cached_instance is not None:
|
|
328
466
|
return cached_instance
|
|
@@ -332,5 +470,7 @@ class PluginManager:
|
|
|
332
470
|
plugin: Union[Api, Search, Download, Authentication, Crunch] = plugin_class(
|
|
333
471
|
provider, plugin_conf
|
|
334
472
|
)
|
|
335
|
-
self._built_plugins_cache[
|
|
473
|
+
self._built_plugins_cache[
|
|
474
|
+
(provider, topic_class.__name__, auth_match_md5)
|
|
475
|
+
] = plugin
|
|
336
476
|
return plugin
|
eodag/plugins/search/__init__.py
CHANGED
|
@@ -16,3 +16,39 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
"""EODAG search package"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from typing import TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from typing import Any, Dict, List, Optional, Union
|
|
28
|
+
|
|
29
|
+
from requests.auth import AuthBase
|
|
30
|
+
|
|
31
|
+
from eodag.plugins.authentication.base import Authentication
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class PreparedSearch:
|
|
36
|
+
"""An object collecting needed information for search."""
|
|
37
|
+
|
|
38
|
+
product_type: Optional[str] = None
|
|
39
|
+
page: Optional[int] = DEFAULT_PAGE
|
|
40
|
+
items_per_page: Optional[int] = DEFAULT_ITEMS_PER_PAGE
|
|
41
|
+
auth: Optional[Union[AuthBase, Dict[str, str]]] = None
|
|
42
|
+
auth_plugin: Optional[Authentication] = None
|
|
43
|
+
count: bool = True
|
|
44
|
+
url: Optional[str] = None
|
|
45
|
+
info_message: Optional[str] = None
|
|
46
|
+
exception_message: Optional[str] = None
|
|
47
|
+
|
|
48
|
+
need_count: bool = field(init=False, repr=False)
|
|
49
|
+
query_params: Dict[str, Any] = field(init=False, repr=False)
|
|
50
|
+
query_string: str = field(init=False, repr=False)
|
|
51
|
+
search_urls: List[str] = field(init=False, repr=False)
|
|
52
|
+
product_type_def_params: Dict[str, Any] = field(init=False, repr=False)
|
|
53
|
+
total_items_nb: int = field(init=False, repr=False)
|
|
54
|
+
sort_by_qs: str = field(init=False, repr=False)
|