eodag 4.0.0a1__py3-none-any.whl → 4.0.0a3__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 (37) hide show
  1. eodag/__init__.py +6 -1
  2. eodag/api/collection.py +354 -0
  3. eodag/api/core.py +324 -303
  4. eodag/api/product/_product.py +15 -29
  5. eodag/api/product/drivers/__init__.py +2 -42
  6. eodag/api/product/drivers/base.py +0 -11
  7. eodag/api/product/metadata_mapping.py +34 -5
  8. eodag/api/search_result.py +144 -9
  9. eodag/cli.py +18 -15
  10. eodag/config.py +37 -3
  11. eodag/plugins/apis/ecmwf.py +16 -4
  12. eodag/plugins/apis/usgs.py +18 -7
  13. eodag/plugins/crunch/filter_latest_intersect.py +1 -0
  14. eodag/plugins/crunch/filter_overlap.py +3 -7
  15. eodag/plugins/search/__init__.py +3 -0
  16. eodag/plugins/search/base.py +6 -6
  17. eodag/plugins/search/build_search_result.py +157 -56
  18. eodag/plugins/search/cop_marine.py +48 -8
  19. eodag/plugins/search/csw.py +18 -8
  20. eodag/plugins/search/qssearch.py +331 -88
  21. eodag/plugins/search/static_stac_search.py +11 -12
  22. eodag/resources/collections.yml +610 -348
  23. eodag/resources/ext_collections.json +1 -1
  24. eodag/resources/ext_product_types.json +1 -1
  25. eodag/resources/providers.yml +334 -62
  26. eodag/resources/stac_provider.yml +4 -2
  27. eodag/resources/user_conf_template.yml +9 -0
  28. eodag/types/__init__.py +2 -0
  29. eodag/types/queryables.py +16 -0
  30. eodag/utils/__init__.py +47 -2
  31. eodag/utils/repr.py +2 -0
  32. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/METADATA +4 -2
  33. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/RECORD +37 -36
  34. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/WHEEL +0 -0
  35. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/entry_points.txt +0 -0
  36. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/licenses/LICENSE +0 -0
  37. {eodag-4.0.0a1.dist-info → eodag-4.0.0a3.dist-info}/top_level.txt +0 -0
@@ -34,6 +34,7 @@ from dateutil.utils import today
34
34
 
35
35
  from eodag import EOProduct
36
36
  from eodag.api.product import AssetsDict
37
+ from eodag.api.search_result import SearchResult
37
38
  from eodag.config import PluginConfig
38
39
  from eodag.plugins.search import PreparedSearch
39
40
  from eodag.plugins.search.static_stac_search import StaticStacSearch
@@ -211,9 +212,12 @@ class CopMarineSearch(StaticStacSearch):
211
212
  dataset_item: dict[str, Any],
212
213
  collection_dict: dict[str, Any],
213
214
  use_dataset_dates: bool = False,
215
+ product_id: Optional[str] = None,
214
216
  ) -> Optional[EOProduct]:
215
217
 
216
218
  item_id = os.path.splitext(item_key.split("/")[-1])[0]
219
+ if product_id and product_id != item_id:
220
+ return None
217
221
  download_url = s3_url + "/" + item_key
218
222
  geometry = (
219
223
  get_geometry_from_various(**dataset_item)
@@ -294,19 +298,29 @@ class CopMarineSearch(StaticStacSearch):
294
298
  self,
295
299
  prep: PreparedSearch = PreparedSearch(),
296
300
  **kwargs: Any,
297
- ) -> tuple[list[EOProduct], Optional[int]]:
301
+ ) -> SearchResult:
298
302
  """
299
303
  Implementation of search for the Copernicus Marine provider
300
304
  :param prep: object containing search parameterds
301
305
  :param kwargs: additional search arguments
302
306
  :returns: list of products and total number of products
303
307
  """
304
- page = prep.page
305
308
  items_per_page = prep.items_per_page
309
+ token_value = getattr(prep, "next_page_token") or prep.page
306
310
 
307
311
  # only return 1 page if pagination is disabled
308
- if page is None or items_per_page is None or page > 1 and items_per_page <= 0:
309
- return ([], 0) if prep.count else ([], None)
312
+ if (
313
+ token_value is None
314
+ or items_per_page is None
315
+ or int(token_value) > 1
316
+ and items_per_page <= 0
317
+ ):
318
+ result = SearchResult([])
319
+ if prep.count:
320
+ result.number_matched = 0
321
+ return result
322
+
323
+ token = int(token_value)
310
324
 
311
325
  collection = kwargs.get("collection", prep.collection)
312
326
  if not collection:
@@ -316,7 +330,7 @@ class CopMarineSearch(StaticStacSearch):
316
330
  collection_dict, datasets_items_list = self._get_collection_info(collection)
317
331
  geometry = kwargs.pop("geometry", None)
318
332
  products: list[EOProduct] = []
319
- start_index = items_per_page * (page - 1) + 1
333
+ start_index = items_per_page * (token - 1) + 1
320
334
  num_total = 0
321
335
  for i, dataset_item in enumerate(datasets_items_list):
322
336
  # Filter by geometry
@@ -374,9 +388,12 @@ class CopMarineSearch(StaticStacSearch):
374
388
  dataset_item,
375
389
  collection_dict,
376
390
  True,
391
+ kwargs.get("id"),
377
392
  )
378
393
  if product:
379
394
  products.append(product)
395
+ if product and kwargs.get("id"):
396
+ break
380
397
  continue
381
398
 
382
399
  s3_client = _get_s3_client(endpoint_url)
@@ -394,7 +411,10 @@ class CopMarineSearch(StaticStacSearch):
394
411
  )
395
412
  if "Contents" not in s3_objects:
396
413
  if len(products) == 0 and i == len(datasets_items_list) - 1:
397
- return ([], 0) if prep.count else ([], None)
414
+ result = SearchResult([])
415
+ if prep.count:
416
+ result.number_matched = 0
417
+ return result
398
418
  else:
399
419
  break
400
420
 
@@ -408,7 +428,11 @@ class CopMarineSearch(StaticStacSearch):
408
428
  collection_dict,
409
429
  )
410
430
  if product:
411
- return [product], 1
431
+ formated_result = SearchResult(
432
+ [product],
433
+ 1,
434
+ )
435
+ return formated_result
412
436
  current_object = s3_objects["Contents"][-1]["Key"]
413
437
  continue
414
438
 
@@ -478,4 +502,20 @@ class CopMarineSearch(StaticStacSearch):
478
502
  products.append(product)
479
503
  current_object = item_key
480
504
 
481
- return products, num_total
505
+ search_params = (
506
+ kwargs
507
+ | {"items_per_page": prep.items_per_page}
508
+ | {"collection": collection}
509
+ | {"provider": self.provider}
510
+ | {"geometry": geometry}
511
+ if geometry
512
+ else {}
513
+ )
514
+
515
+ formated_result = SearchResult(
516
+ products,
517
+ num_total,
518
+ search_params=search_params,
519
+ next_page_token=str(start_index + 1),
520
+ )
521
+ return formated_result
@@ -35,6 +35,7 @@ from shapely import geometry, wkt
35
35
 
36
36
  from eodag.api.product import EOProduct
37
37
  from eodag.api.product.metadata_mapping import properties_from_xml
38
+ from eodag.api.search_result import SearchResult
38
39
  from eodag.plugins.search import PreparedSearch
39
40
  from eodag.plugins.search.base import Search
40
41
  from eodag.utils import DEFAULT_PROJ
@@ -107,11 +108,14 @@ class CSWSearch(Search):
107
108
  self,
108
109
  prep: PreparedSearch = PreparedSearch(),
109
110
  **kwargs: Any,
110
- ) -> tuple[list[EOProduct], Optional[int]]:
111
+ ) -> SearchResult:
111
112
  """Perform a search on a OGC/CSW-like interface"""
112
113
  collection = kwargs.get("collection")
113
114
  if collection is None:
114
- return ([], 0) if prep.count else ([], None)
115
+ result = SearchResult([])
116
+ if prep.count:
117
+ result.number_matched = 0
118
+ return result
115
119
  auth = kwargs.get("auth")
116
120
  if auth:
117
121
  self.__init_catalog(**getattr(auth.config, "credentials", {}))
@@ -157,7 +161,13 @@ class CSWSearch(Search):
157
161
  results.extend(partial_results)
158
162
  logger.info("Found %s overall results", len(results))
159
163
  total_results = len(results) if prep.count else None
160
- return results, total_results
164
+ if not prep.count and "number_matched" in kwargs:
165
+ total_results = kwargs["number_matched"]
166
+ formated_result = SearchResult(
167
+ results,
168
+ total_results,
169
+ )
170
+ return formated_result
161
171
 
162
172
  def __init_catalog(
163
173
  self, username: Optional[str] = None, password: Optional[str] = None
@@ -237,18 +247,18 @@ class CSWSearch(Search):
237
247
  constraints: list[OgcExpression] = []
238
248
  # How the match should be performed (fuzzy, prefix, postfix or exact).
239
249
  # defaults to fuzzy
240
- pt_tag, matching = (
250
+ col_tag, matching = (
241
251
  collection_def["name"],
242
252
  collection_def.get("matching", "fuzzy"),
243
253
  )
244
254
  if matching == "prefix":
245
- constraints.append(PropertyIsLike(pt_tag, "{}%".format(collection)))
255
+ constraints.append(PropertyIsLike(col_tag, "{}%".format(collection)))
246
256
  elif matching == "postfix":
247
- constraints.append(PropertyIsLike(pt_tag, "%{}".format(collection)))
257
+ constraints.append(PropertyIsLike(col_tag, "%{}".format(collection)))
248
258
  elif matching == "exact":
249
- constraints.append(PropertyIsEqualTo(pt_tag, collection))
259
+ constraints.append(PropertyIsEqualTo(col_tag, collection))
250
260
  else: # unknown matching is considered to be equal to 'fuzzy'
251
- constraints.append(PropertyIsLike(pt_tag, "%{}%".format(collection)))
261
+ constraints.append(PropertyIsLike(col_tag, "%{}%".format(collection)))
252
262
 
253
263
  # `footprint`
254
264
  fp = params.get("geometry")