Skip to content

Commit c59a562

Browse files
committed
refactor: simplify and fix mypy
bring back PluginConfig to config
1 parent 94969a7 commit c59a562

39 files changed

+789
-229
lines changed

eodag/api/core.py

Lines changed: 69 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,20 @@
2626
from importlib.metadata import version
2727
from importlib.resources import files as res_files
2828
from operator import itemgetter
29-
from typing import TYPE_CHECKING, Any, Iterator, Optional, Union
29+
from typing import TYPE_CHECKING, Any, Iterator, Optional, Union, cast
3030

3131
import geojson
3232
import yaml
3333

34-
from eodag.api.plugin import PluginConfig, credentials_in_auth
3534
from eodag.api.product.metadata_mapping import mtd_cfg_as_conversion_and_querypath
3635
from eodag.api.provider import Provider, ProvidersDict
3736
from eodag.api.search_result import SearchResult
3837
from eodag.config import (
3938
PLUGINS_TOPICS_KEYS,
39+
DiscoverProductTypes,
40+
PluginConfig,
4041
SimpleYamlProxyConfig,
42+
credentials_in_auth,
4143
get_ext_product_types_conf,
4244
load_default_config,
4345
load_yml_config,
@@ -188,7 +190,7 @@ def get_version(self) -> str:
188190
"""Get eodag package version"""
189191
return version("eodag")
190192

191-
def set_preferred_provider(self, provider: str | Provider) -> None:
193+
def set_preferred_provider(self, provider: str) -> None:
192194
"""Set max priority for the given provider.
193195
194196
:param provider: The name of the provider that should be considered as the
@@ -204,7 +206,7 @@ def set_preferred_provider(self, provider: str | Provider) -> None:
204206
new_priority = max_priority + 1
205207
self._plugins_manager.set_priority(provider, new_priority)
206208

207-
def get_preferred_provider(self) -> tuple[Provider, int]:
209+
def get_preferred_provider(self) -> tuple[str, int]:
208210
"""Get the provider currently set as the preferred one for searching
209211
products, along with its priority.
210212
@@ -232,14 +234,14 @@ def update_providers_config(
232234
return None
233235

234236
# restore the pruned configuration
235-
for provider, config in self._pruned_providers_config.items():
236-
if provider in conf_update:
237+
for name in list(self._pruned_providers_config):
238+
config = self._pruned_providers_config[name]
239+
if name in conf_update:
237240
logger.info(
238-
"%s: provider restored from the pruned configurations",
239-
provider,
241+
"%s: provider restored from the pruned configurations", name
240242
)
241-
self.providers[provider] = Provider(provider, config)
242-
self._pruned_providers_config.pop(provider)
243+
self.providers[name] = Provider(config, name)
244+
self._pruned_providers_config.pop(name)
243245

244246
self.providers.update_from_configs(conf_update)
245247

@@ -351,7 +353,7 @@ def _prune_providers_list(self) -> None:
351353
elif hasattr(conf, "search") and getattr(conf.search, "need_auth", False):
352354
if not hasattr(conf, "auth") and not hasattr(conf, "search_auth"):
353355
# credentials needed but no auth plugin was found
354-
self._pruned_providers_config[provider] = conf
356+
self._pruned_providers_config[provider.name] = conf
355357
del self.providers[provider.name]
356358

357359
update_needed = True
@@ -371,7 +373,7 @@ def _prune_providers_list(self) -> None:
371373
)
372374
if not credentials_exist:
373375
# credentials needed but not found
374-
self._pruned_providers_config[provider] = conf
376+
self._pruned_providers_config[provider.name] = conf
375377
del self.providers[provider.name]
376378

377379
update_needed = True
@@ -382,7 +384,7 @@ def _prune_providers_list(self) -> None:
382384

383385
elif not hasattr(conf, "api") and not hasattr(conf, "search"):
384386
# provider should have at least an api or search plugin
385-
self._pruned_providers_config[provider] = conf
387+
self._pruned_providers_config[provider.name] = conf
386388
del self.providers[provider.name]
387389

388390
update_needed = True
@@ -516,13 +518,13 @@ def fetch_product_types_list(self, provider: Optional[str] = None) -> None:
516518
providers_to_fetch = self.providers.filter_by_name(provider)
517519

518520
# providers discovery confs that are fetchable
519-
providers_discovery_configs_fetchable: dict[str, Any] = {}
521+
providers_discovery_configs_fetchable: dict[str, DiscoverProductTypes] = {}
520522
# check if any provider has not already been fetched for product types
521523
already_fetched = True
522524
for provider_to_fetch in providers_to_fetch.values():
523-
if provider_to_fetch.fetchable:
525+
if provider_to_fetch.fetchable and provider_to_fetch.search_config:
524526
providers_discovery_configs_fetchable[
525-
provider_to_fetch
527+
provider_to_fetch.name
526528
] = provider_to_fetch.search_config.discover_product_types
527529
if not provider_to_fetch.product_types_fetched:
528530
already_fetched = False
@@ -569,33 +571,36 @@ def fetch_product_types_list(self, provider: Optional[str] = None) -> None:
569571
if default_discovery_conf["result_type"] == "json" and isinstance(
570572
default_discovery_conf["results_entry"], str
571573
):
572-
default_discovery_conf_parsed = dict(
573-
default_discovery_conf,
574-
**{
575-
"results_entry": string_to_jsonpath(
576-
default_discovery_conf["results_entry"], force=True
577-
)
578-
},
579-
**mtd_cfg_as_conversion_and_querypath(
580-
dict(
581-
generic_product_type_id=default_discovery_conf[
582-
"generic_product_type_id"
583-
]
584-
)
585-
),
586-
**dict(
587-
generic_product_type_parsable_properties=mtd_cfg_as_conversion_and_querypath(
588-
default_discovery_conf[
589-
"generic_product_type_parsable_properties"
590-
]
591-
)
592-
),
593-
**dict(
594-
generic_product_type_parsable_metadata=mtd_cfg_as_conversion_and_querypath(
595-
default_discovery_conf[
596-
"generic_product_type_parsable_metadata"
597-
]
598-
)
574+
default_discovery_conf_parsed = cast(
575+
DiscoverProductTypes,
576+
dict(
577+
default_discovery_conf,
578+
**{
579+
"results_entry": string_to_jsonpath(
580+
default_discovery_conf["results_entry"], force=True
581+
)
582+
},
583+
**mtd_cfg_as_conversion_and_querypath(
584+
dict(
585+
generic_product_type_id=default_discovery_conf[
586+
"generic_product_type_id"
587+
]
588+
)
589+
),
590+
**dict(
591+
generic_product_type_parsable_properties=mtd_cfg_as_conversion_and_querypath(
592+
default_discovery_conf[
593+
"generic_product_type_parsable_properties"
594+
]
595+
)
596+
),
597+
**dict(
598+
generic_product_type_parsable_metadata=mtd_cfg_as_conversion_and_querypath(
599+
default_discovery_conf[
600+
"generic_product_type_parsable_metadata"
601+
]
602+
)
603+
),
599604
),
600605
)
601606
else:
@@ -650,7 +655,7 @@ def discover_product_types(
650655

651656
if p.fetchable:
652657
search_plugin: Union[Search, Api] = next(
653-
self._plugins_manager.get_search_plugins(provider=p)
658+
self._plugins_manager.get_search_plugins(provider=p.name)
654659
)
655660

656661
# check after plugin init if still fetchable
@@ -671,10 +676,10 @@ def discover_product_types(
671676
logger.debug(
672677
f"Could not authenticate on {p} for product types discovery"
673678
)
674-
ext_product_types_conf[p] = None
679+
ext_product_types_conf[p.name] = None
675680
continue
676681

677-
ext_product_types_conf[p] = search_plugin.discover_product_types(
682+
ext_product_types_conf[p.name] = search_plugin.discover_product_types(
678683
**kwargs
679684
)
680685

@@ -763,7 +768,7 @@ def update_product_types_list(
763768

764769
def available_providers(
765770
self, product_type: Optional[str] = None, by_group: bool = False
766-
) -> ProvidersDict:
771+
) -> list[str]:
767772
"""Gives the sorted list of the available providers or groups
768773
769774
The providers or groups are sorted first by their priority level in descending order,
@@ -775,32 +780,28 @@ def available_providers(
775780
of providers, mixed with other providers
776781
:returns: the sorted list of the available providers or groups
777782
"""
783+
candidates = []
778784

779-
if product_type:
780-
providers = [
781-
(v.group if by_group and hasattr(v.config, "group") else k, v.priority)
782-
for k, v in self.providers.items()
783-
if product_type in v.products
784-
]
785-
else:
786-
providers = [
787-
(v.group if by_group and hasattr(v.config, "group") else k, v.priority)
788-
for k, v in self.providers.items()
789-
]
785+
for key, provider in self.providers.items():
786+
if product_type and product_type not in provider.product_types:
787+
continue
788+
789+
group = getattr(provider.config, "group", None)
790+
name = group if by_group and group else key
791+
candidates.append((name, provider.priority))
790792

791-
# If by_group is True, keep only the highest priority for each group
792793
if by_group:
793-
group_priority: dict[str, int] = {}
794-
for name, priority in providers:
795-
if name not in group_priority or priority > group_priority[name]:
796-
group_priority[name] = priority
797-
providers = list(group_priority.items())
794+
# Keep only the highest-priority entry per group
795+
grouped: dict[str, int] = {}
796+
for name, priority in candidates:
797+
if name not in grouped or priority > grouped[name]:
798+
grouped[name] = priority
799+
candidates = list(grouped.items())
798800

799-
# Sort by priority (descending) and then by name (ascending)
800-
providers.sort(key=lambda x: (-x[1], x[0]))
801+
# Sort: priority descending, then name ascending
802+
candidates.sort(key=lambda item: (-item[1], item[0]))
801803

802-
# Return only the names of the providers or groups
803-
return [name for name, _ in providers]
804+
return [name for name, _ in candidates]
804805

805806
def get_product_type_from_alias(self, alias_or_id: str) -> str:
806807
"""Return the ID of a product type by either its ID or alias

eodag/api/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def from_yaml(cls, loader: yaml.Loader, node: Any) -> Self:
513513
return loader.construct_yaml_object(node, cls)
514514

515515
@classmethod
516-
def from_mapping(cls, mapping: Self | dict[str, Any]) -> Self:
516+
def from_mapping(cls, mapping: dict[str, Any]) -> Self:
517517
"""Build a :class:`~eodag.config.PluginConfig` from a mapping"""
518518
cls.validate(tuple(mapping.keys()))
519519
c = cls()

eodag/api/product/_product.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import os
2323
import re
2424
import tempfile
25+
from datetime import datetime
2526
from typing import TYPE_CHECKING, Any, Optional, Union
2627

2728
import requests
@@ -122,6 +123,8 @@ class EOProduct:
122123
filename: str
123124
#: Product search keyword arguments, stored during search
124125
search_kwargs: Any
126+
#: Datetime for download next try
127+
next_try: datetime
125128

126129
def __init__(
127130
self, provider: str, properties: dict[str, Any], **kwargs: Any
@@ -407,7 +410,6 @@ def _download_quicklook(
407410
ssl_verify: Optional[bool] = None,
408411
auth: Optional[AuthBase] = None,
409412
):
410-
411413
"""Download the quicklook image from the EOProduct's quicklook URL.
412414
413415
This method performs an HTTP GET request to retrieve the quicklook image and saves it
@@ -505,7 +507,6 @@ def format_quicklook_address() -> None:
505507
)
506508

507509
if not os.path.isfile(quicklook_file):
508-
509510
# progress bar init
510511
if progress_callback is None:
511512
progress_callback = ProgressCallback()
@@ -548,7 +549,6 @@ def format_quicklook_address() -> None:
548549
quicklook_file, progress_callback, ssl_verify, auth
549550
)
550551
except RequestException as e:
551-
552552
logger.debug(
553553
f"Error while getting resource with authentication. {e} \nTrying without authentication..."
554554
)
@@ -606,24 +606,34 @@ def _repr_html_(self):
606606
607607
<tr style='background-color: transparent;'>
608608
<td style='text-align: left; vertical-align: top;'>
609-
{dict_to_html_table({
610-
"provider": self.provider,
611-
"product_type": self.product_type,
612-
"properties[&quot;id&quot;]": self.properties.get('id'),
613-
"properties[&quot;startTimeFromAscendingNode&quot;]": self.properties.get(
614-
'startTimeFromAscendingNode'
615-
),
616-
"properties[&quot;completionTimeFromAscendingNode&quot;]": self.properties.get(
617-
'completionTimeFromAscendingNode'
618-
),
619-
}, brackets=False)}
620-
<details><summary style='color: grey; margin-top: 10px;'>properties:&ensp;({len(
621-
self.properties)})</summary>{
622-
dict_to_html_table(self.properties, depth=1)}</details>
623-
<details><summary style='color: grey; margin-top: 10px;'>assets:&ensp;({len(
624-
self.assets)})</summary>{self.assets._repr_html_(embeded=True)}</details>
609+
{
610+
dict_to_html_table(
611+
{
612+
"provider": self.provider,
613+
"product_type": self.product_type,
614+
"properties[&quot;id&quot;]": self.properties.get("id"),
615+
"properties[&quot;startTimeFromAscendingNode&quot;]": self.properties.get(
616+
"startTimeFromAscendingNode"
617+
),
618+
"properties[&quot;completionTimeFromAscendingNode&quot;]": self.properties.get(
619+
"completionTimeFromAscendingNode"
620+
),
621+
},
622+
brackets=False,
623+
)
624+
}
625+
<details><summary style='color: grey; margin-top: 10px;'>properties:&ensp;({
626+
len(self.properties)
627+
})</summary>{dict_to_html_table(self.properties, depth=1)}</details>
628+
<details><summary style='color: grey; margin-top: 10px;'>assets:&ensp;({
629+
len(self.assets)
630+
})</summary>{self.assets._repr_html_(embeded=True)}</details>
625631
</td>
626-
<td {geom_style} title='geometry'>geometry<br />{self.geometry._repr_svg_()}</td>
627-
<td {thumbnail_style} title='properties[&quot;thumbnail&quot;]'>{thumbnail_html}</td>
632+
<td {geom_style} title='geometry'>geometry<br />{
633+
self.geometry._repr_svg_()
634+
}</td>
635+
<td {thumbnail_style} title='properties[&quot;thumbnail&quot;]'>{
636+
thumbnail_html
637+
}</td>
628638
</tr>
629639
</table>"""

eodag/api/product/metadata_mapping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
if TYPE_CHECKING:
6161
from shapely.geometry.base import BaseGeometry
6262

63-
from eodag.api.plugin import PluginConfig
63+
from eodag.config import PluginConfig
6464

6565
logger = logging.getLogger("eodag.product.metadata_mapping")
6666

0 commit comments

Comments
 (0)