eodag 3.3.2__py3-none-any.whl → 3.4.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/plugins/manager.py CHANGED
@@ -20,10 +20,9 @@ from __future__ import annotations
20
20
  import logging
21
21
  import re
22
22
  from operator import attrgetter
23
- from pathlib import Path
24
23
  from typing import TYPE_CHECKING, Any, Iterator, Optional, Union, cast
25
24
 
26
- import pkg_resources
25
+ import importlib_metadata
27
26
 
28
27
  from eodag.config import (
29
28
  AUTH_TOPIC_KEYS,
@@ -91,12 +90,12 @@ class PluginManager:
91
90
  # have it discovered as long as they declare an entry point of the type
92
91
  # 'eodag.plugins.search' for example in its setup script. See the setup
93
92
  # script of eodag for an example of how to do this.
94
- for entry_point in pkg_resources.iter_entry_points(
95
- "eodag.plugins.{}".format(topic)
93
+ for entry_point in importlib_metadata.entry_points(
94
+ group="eodag.plugins.{}".format(topic)
96
95
  ):
97
96
  try:
98
97
  entry_point.load()
99
- except pkg_resources.DistributionNotFound:
98
+ except ModuleNotFoundError:
100
99
  logger.debug(
101
100
  "%s plugin skipped, eodag[%s] or eodag[all] needed",
102
101
  entry_point.name,
@@ -112,18 +111,12 @@ class PluginManager:
112
111
  "Check that the plugin module (%s) is importable",
113
112
  entry_point.module_name,
114
113
  )
115
- if (
116
- entry_point.dist
117
- and entry_point.dist.key != "eodag"
118
- and entry_point.dist.location is not None
119
- ):
114
+ if entry_point.dist and entry_point.dist.name != "eodag":
120
115
  # use plugin providers if any
116
+ name = entry_point.dist.name
117
+ dist = entry_point.dist
121
118
  plugin_providers_config_path = [
122
- str(x)
123
- for x in Path(
124
- entry_point.dist.location,
125
- pkg_resources.to_filename(entry_point.dist.key),
126
- ).rglob("providers.yml")
119
+ str(x) for x in dist.locate_file(name).rglob("providers.yml")
127
120
  ]
128
121
  if plugin_providers_config_path:
129
122
  plugin_providers_config = load_config(
@@ -37,7 +37,7 @@ from eodag.api.product import AssetsDict
37
37
  from eodag.config import PluginConfig
38
38
  from eodag.plugins.search import PreparedSearch
39
39
  from eodag.plugins.search.static_stac_search import StaticStacSearch
40
- from eodag.utils import get_bucket_name_and_prefix
40
+ from eodag.utils import get_bucket_name_and_prefix, get_geometry_from_various
41
41
  from eodag.utils.exceptions import RequestError, UnsupportedProductType, ValidationError
42
42
 
43
43
  if TYPE_CHECKING:
@@ -215,10 +215,14 @@ class CopMarineSearch(StaticStacSearch):
215
215
 
216
216
  item_id = os.path.splitext(item_key.split("/")[-1])[0]
217
217
  download_url = s3_url + "/" + item_key
218
+ geometry = (
219
+ get_geometry_from_various(**dataset_item)
220
+ or self.config.metadata_mapping["defaultGeometry"]
221
+ )
218
222
  properties = {
219
223
  "id": item_id,
220
224
  "title": item_id,
221
- "geometry": self.config.metadata_mapping["defaultGeometry"],
225
+ "geometry": geometry,
222
226
  "downloadLink": download_url,
223
227
  "dataset": dataset_item["id"],
224
228
  }
@@ -308,10 +312,16 @@ class CopMarineSearch(StaticStacSearch):
308
312
  "parameter product type is required for search with cop_marine provider"
309
313
  )
310
314
  collection_dict, datasets_items_list = self._get_product_type_info(product_type)
315
+ geometry = kwargs.pop("geometry", None)
311
316
  products: list[EOProduct] = []
312
317
  start_index = items_per_page * (page - 1) + 1
313
318
  num_total = 0
314
319
  for i, dataset_item in enumerate(datasets_items_list):
320
+ # Filter by geometry
321
+ if "id" not in kwargs and geometry:
322
+ dataset_geom = get_geometry_from_various(**dataset_item)
323
+ if dataset_geom and not dataset_geom.intersects(geometry):
324
+ continue
315
325
  try:
316
326
  logger.debug("searching data for dataset %s", dataset_item["id"])
317
327
 
@@ -70,6 +70,7 @@ from eodag.api.search_result import RawSearchResult
70
70
  from eodag.plugins.search import PreparedSearch
71
71
  from eodag.plugins.search.base import Search
72
72
  from eodag.types import json_field_definition_to_python, model_fields_to_annotated
73
+ from eodag.types.queryables import Queryables
73
74
  from eodag.types.search_args import SortByList
74
75
  from eodag.utils import (
75
76
  DEFAULT_SEARCH_TIMEOUT,
@@ -80,6 +81,7 @@ from eodag.utils import (
80
81
  REQ_RETRY_TOTAL,
81
82
  USER_AGENT,
82
83
  _deprecated,
84
+ copy_deepcopy,
83
85
  deepcopy,
84
86
  dict_items_recursive_apply,
85
87
  format_dict_items,
@@ -1896,30 +1898,47 @@ class StacSearch(PostJsonSearch):
1896
1898
  "No queryable found for %s on %s", product_type, self.provider
1897
1899
  )
1898
1900
  return None
1899
-
1900
1901
  # convert json results to pydantic model fields
1901
1902
  field_definitions: dict[str, Any] = dict()
1903
+ STAC_TO_EODAG_QUERYABLES = {
1904
+ "start_datetime": "start",
1905
+ "end_datetime": "end",
1906
+ "datetime": None,
1907
+ "bbox": "geom",
1908
+ }
1902
1909
  for json_param, json_mtd in json_queryables.items():
1903
- param = (
1910
+ param = STAC_TO_EODAG_QUERYABLES.get(
1911
+ json_param,
1904
1912
  get_queryable_from_provider(
1905
1913
  json_param, self.get_metadata_mapping(product_type)
1906
1914
  )
1907
- or json_param
1915
+ or json_param,
1908
1916
  )
1917
+ if param is None:
1918
+ continue
1909
1919
 
1910
- default = kwargs.get(param, None)
1920
+ default = kwargs.get(param, json_mtd.get("default"))
1911
1921
  annotated_def = json_field_definition_to_python(
1912
1922
  json_mtd, default_value=default
1913
1923
  )
1914
1924
  field_definitions[param] = get_args(annotated_def)
1915
1925
 
1916
1926
  python_queryables = create_model("m", **field_definitions).model_fields
1917
- # replace geometry by geom
1918
1927
  geom_queryable = python_queryables.pop("geometry", None)
1919
1928
  if geom_queryable:
1920
1929
  python_queryables["geom"] = geom_queryable
1921
1930
 
1922
- return model_fields_to_annotated(python_queryables)
1931
+ queryables_dict = model_fields_to_annotated(python_queryables)
1932
+
1933
+ # append "datetime" as "start" & "end" if needed
1934
+ if "datetime" in json_queryables:
1935
+ eodag_queryables = copy_deepcopy(
1936
+ model_fields_to_annotated(Queryables.model_fields)
1937
+ )
1938
+ queryables_dict.setdefault("start", eodag_queryables["start"])
1939
+ queryables_dict.setdefault("end", eodag_queryables["end"])
1940
+
1941
+ return queryables_dict
1923
1942
 
1924
1943
 
1925
1944
  class PostJsonSearchWithStacQueryables(StacSearch, PostJsonSearch):
@@ -18,10 +18,11 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import logging
21
- from typing import TYPE_CHECKING, Any, Optional
21
+ from typing import TYPE_CHECKING, Annotated, Any, Optional
22
22
  from unittest import mock
23
23
 
24
24
  import geojson
25
+ from pydantic.fields import FieldInfo
25
26
 
26
27
  from eodag.api.product.metadata_mapping import get_metadata_path_value
27
28
  from eodag.api.search_result import SearchResult
@@ -30,6 +31,7 @@ from eodag.plugins.crunch.filter_overlap import FilterOverlap
30
31
  from eodag.plugins.crunch.filter_property import FilterProperty
31
32
  from eodag.plugins.search import PreparedSearch
32
33
  from eodag.plugins.search.qssearch import StacSearch
34
+ from eodag.types.queryables import Queryables
33
35
  from eodag.utils import HTTP_REQ_TIMEOUT, MockResponse
34
36
  from eodag.utils.stac_reader import fetch_stac_collections, fetch_stac_items
35
37
 
@@ -123,6 +125,34 @@ class StaticStacSearch(StacSearch):
123
125
 
124
126
  return conf_update_dict
125
127
 
128
+ def discover_queryables(
129
+ self, **kwargs: Any
130
+ ) -> dict[str, Annotated[Any, FieldInfo]]:
131
+ """Set static available queryables for :class:`~eodag.plugins.search.static_stac_search.StaticStacSearch`
132
+ search plugin
133
+
134
+ :param kwargs: additional filters for queryables (`productType` and other search
135
+ arguments)
136
+ :returns: queryable parameters dict
137
+ """
138
+ return {
139
+ "productType": Queryables.get_with_default(
140
+ "productType", kwargs.get("productType")
141
+ ),
142
+ "id": Queryables.get_with_default("id", kwargs.get("id")),
143
+ "start": Queryables.get_with_default(
144
+ "start", kwargs.get("start") or kwargs.get("startTimeFromAscendingNode")
145
+ ),
146
+ "end": Queryables.get_with_default(
147
+ "end",
148
+ kwargs.get("end") or kwargs.get("completionTimeFromAscendingNode"),
149
+ ),
150
+ "geom": Queryables.get_with_default(
151
+ "geom",
152
+ kwargs.get("geom") or kwargs.get("geometry") or kwargs.get("area"),
153
+ ),
154
+ }
155
+
126
156
  def query(
127
157
  self,
128
158
  prep: PreparedSearch = PreparedSearch(),