Skip to content

Commit c20a7dd

Browse files
committed
refactor: simplify and fix mypy
1 parent 94969a7 commit c20a7dd

File tree

11 files changed

+210
-201
lines changed

11 files changed

+210
-201
lines changed

eodag/api/core.py

Lines changed: 67 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
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
34+
from eodag.api.plugin import DiscoverProductTypes, PluginConfig, credentials_in_auth
3535
from eodag.api.product.metadata_mapping import mtd_cfg_as_conversion_and_querypath
3636
from eodag.api.provider import Provider, ProvidersDict
3737
from eodag.api.search_result import SearchResult
@@ -188,7 +188,7 @@ def get_version(self) -> str:
188188
"""Get eodag package version"""
189189
return version("eodag")
190190

191-
def set_preferred_provider(self, provider: str | Provider) -> None:
191+
def set_preferred_provider(self, provider: str) -> None:
192192
"""Set max priority for the given provider.
193193
194194
:param provider: The name of the provider that should be considered as the
@@ -204,7 +204,7 @@ def set_preferred_provider(self, provider: str | Provider) -> None:
204204
new_priority = max_priority + 1
205205
self._plugins_manager.set_priority(provider, new_priority)
206206

207-
def get_preferred_provider(self) -> tuple[Provider, int]:
207+
def get_preferred_provider(self) -> tuple[str, int]:
208208
"""Get the provider currently set as the preferred one for searching
209209
products, along with its priority.
210210
@@ -232,14 +232,14 @@ def update_providers_config(
232232
return None
233233

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

244244
self.providers.update_from_configs(conf_update)
245245

@@ -351,7 +351,7 @@ def _prune_providers_list(self) -> None:
351351
elif hasattr(conf, "search") and getattr(conf.search, "need_auth", False):
352352
if not hasattr(conf, "auth") and not hasattr(conf, "search_auth"):
353353
# credentials needed but no auth plugin was found
354-
self._pruned_providers_config[provider] = conf
354+
self._pruned_providers_config[provider.name] = conf
355355
del self.providers[provider.name]
356356

357357
update_needed = True
@@ -371,7 +371,7 @@ def _prune_providers_list(self) -> None:
371371
)
372372
if not credentials_exist:
373373
# credentials needed but not found
374-
self._pruned_providers_config[provider] = conf
374+
self._pruned_providers_config[provider.name] = conf
375375
del self.providers[provider.name]
376376

377377
update_needed = True
@@ -382,7 +382,7 @@ def _prune_providers_list(self) -> None:
382382

383383
elif not hasattr(conf, "api") and not hasattr(conf, "search"):
384384
# provider should have at least an api or search plugin
385-
self._pruned_providers_config[provider] = conf
385+
self._pruned_providers_config[provider.name] = conf
386386
del self.providers[provider.name]
387387

388388
update_needed = True
@@ -516,13 +516,13 @@ def fetch_product_types_list(self, provider: Optional[str] = None) -> None:
516516
providers_to_fetch = self.providers.filter_by_name(provider)
517517

518518
# providers discovery confs that are fetchable
519-
providers_discovery_configs_fetchable: dict[str, Any] = {}
519+
providers_discovery_configs_fetchable: dict[str, DiscoverProductTypes] = {}
520520
# check if any provider has not already been fetched for product types
521521
already_fetched = True
522522
for provider_to_fetch in providers_to_fetch.values():
523-
if provider_to_fetch.fetchable:
523+
if provider_to_fetch.fetchable and provider_to_fetch.search_config:
524524
providers_discovery_configs_fetchable[
525-
provider_to_fetch
525+
provider_to_fetch.name
526526
] = provider_to_fetch.search_config.discover_product_types
527527
if not provider_to_fetch.product_types_fetched:
528528
already_fetched = False
@@ -569,33 +569,36 @@ def fetch_product_types_list(self, provider: Optional[str] = None) -> None:
569569
if default_discovery_conf["result_type"] == "json" and isinstance(
570570
default_discovery_conf["results_entry"], str
571571
):
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-
)
572+
default_discovery_conf_parsed = cast(
573+
DiscoverProductTypes,
574+
dict(
575+
default_discovery_conf,
576+
**{
577+
"results_entry": string_to_jsonpath(
578+
default_discovery_conf["results_entry"], force=True
579+
)
580+
},
581+
**mtd_cfg_as_conversion_and_querypath(
582+
dict(
583+
generic_product_type_id=default_discovery_conf[
584+
"generic_product_type_id"
585+
]
586+
)
587+
),
588+
**dict(
589+
generic_product_type_parsable_properties=mtd_cfg_as_conversion_and_querypath(
590+
default_discovery_conf[
591+
"generic_product_type_parsable_properties"
592+
]
593+
)
594+
),
595+
**dict(
596+
generic_product_type_parsable_metadata=mtd_cfg_as_conversion_and_querypath(
597+
default_discovery_conf[
598+
"generic_product_type_parsable_metadata"
599+
]
600+
)
601+
),
599602
),
600603
)
601604
else:
@@ -650,7 +653,7 @@ def discover_product_types(
650653

651654
if p.fetchable:
652655
search_plugin: Union[Search, Api] = next(
653-
self._plugins_manager.get_search_plugins(provider=p)
656+
self._plugins_manager.get_search_plugins(provider=p.name)
654657
)
655658

656659
# check after plugin init if still fetchable
@@ -671,10 +674,10 @@ def discover_product_types(
671674
logger.debug(
672675
f"Could not authenticate on {p} for product types discovery"
673676
)
674-
ext_product_types_conf[p] = None
677+
ext_product_types_conf[p.name] = None
675678
continue
676679

677-
ext_product_types_conf[p] = search_plugin.discover_product_types(
680+
ext_product_types_conf[p.name] = search_plugin.discover_product_types(
678681
**kwargs
679682
)
680683

@@ -763,7 +766,7 @@ def update_product_types_list(
763766

764767
def available_providers(
765768
self, product_type: Optional[str] = None, by_group: bool = False
766-
) -> ProvidersDict:
769+
) -> list[str]:
767770
"""Gives the sorted list of the available providers or groups
768771
769772
The providers or groups are sorted first by their priority level in descending order,
@@ -775,32 +778,28 @@ def available_providers(
775778
of providers, mixed with other providers
776779
:returns: the sorted list of the available providers or groups
777780
"""
781+
candidates = []
778782

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-
]
783+
for key, provider in self.providers.items():
784+
if product_type and product_type not in provider.product_types:
785+
continue
786+
787+
group = getattr(provider.config, "group", None)
788+
name = group if by_group and group else key
789+
candidates.append((name, provider.priority))
790790

791-
# If by_group is True, keep only the highest priority for each group
792791
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())
792+
# Keep only the highest-priority entry per group
793+
grouped: dict[str, int] = {}
794+
for name, priority in candidates:
795+
if name not in grouped or priority > grouped[name]:
796+
grouped[name] = priority
797+
candidates = list(grouped.items())
798798

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

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

805804
def get_product_type_from_alias(self, alias_or_id: str) -> str:
806805
"""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>"""

0 commit comments

Comments
 (0)