eodag 3.1.0b1__py3-none-any.whl → 3.1.0b2__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 (85) hide show
  1. eodag/api/core.py +59 -52
  2. eodag/api/product/_assets.py +5 -5
  3. eodag/api/product/_product.py +27 -12
  4. eodag/api/product/drivers/__init__.py +81 -4
  5. eodag/api/product/drivers/base.py +65 -4
  6. eodag/api/product/drivers/generic.py +65 -0
  7. eodag/api/product/drivers/sentinel1.py +97 -0
  8. eodag/api/product/drivers/sentinel2.py +95 -0
  9. eodag/api/product/metadata_mapping.py +62 -74
  10. eodag/api/search_result.py +13 -23
  11. eodag/cli.py +4 -4
  12. eodag/config.py +66 -69
  13. eodag/plugins/apis/base.py +1 -1
  14. eodag/plugins/apis/ecmwf.py +10 -9
  15. eodag/plugins/apis/usgs.py +11 -10
  16. eodag/plugins/authentication/aws_auth.py +16 -13
  17. eodag/plugins/authentication/base.py +5 -3
  18. eodag/plugins/authentication/header.py +3 -3
  19. eodag/plugins/authentication/keycloak.py +4 -4
  20. eodag/plugins/authentication/oauth.py +7 -3
  21. eodag/plugins/authentication/openid_connect.py +14 -14
  22. eodag/plugins/authentication/sas_auth.py +4 -4
  23. eodag/plugins/authentication/token.py +7 -7
  24. eodag/plugins/authentication/token_exchange.py +1 -1
  25. eodag/plugins/base.py +4 -4
  26. eodag/plugins/crunch/base.py +4 -4
  27. eodag/plugins/crunch/filter_date.py +4 -4
  28. eodag/plugins/crunch/filter_latest_intersect.py +6 -6
  29. eodag/plugins/crunch/filter_latest_tpl_name.py +7 -7
  30. eodag/plugins/crunch/filter_overlap.py +4 -4
  31. eodag/plugins/crunch/filter_property.py +4 -4
  32. eodag/plugins/download/aws.py +47 -66
  33. eodag/plugins/download/base.py +8 -17
  34. eodag/plugins/download/creodias_s3.py +2 -2
  35. eodag/plugins/download/http.py +30 -32
  36. eodag/plugins/download/s3rest.py +5 -4
  37. eodag/plugins/manager.py +10 -20
  38. eodag/plugins/search/__init__.py +6 -5
  39. eodag/plugins/search/base.py +35 -40
  40. eodag/plugins/search/build_search_result.py +69 -68
  41. eodag/plugins/search/cop_marine.py +22 -12
  42. eodag/plugins/search/creodias_s3.py +8 -78
  43. eodag/plugins/search/csw.py +11 -11
  44. eodag/plugins/search/data_request_search.py +16 -15
  45. eodag/plugins/search/qssearch.py +56 -52
  46. eodag/plugins/search/stac_list_assets.py +85 -0
  47. eodag/plugins/search/static_stac_search.py +3 -3
  48. eodag/resources/ext_product_types.json +1 -1
  49. eodag/resources/product_types.yml +288 -288
  50. eodag/resources/providers.yml +146 -6
  51. eodag/resources/stac_api.yml +2 -2
  52. eodag/resources/user_conf_template.yml +11 -0
  53. eodag/rest/cache.py +2 -2
  54. eodag/rest/config.py +3 -3
  55. eodag/rest/core.py +24 -24
  56. eodag/rest/errors.py +5 -5
  57. eodag/rest/server.py +3 -11
  58. eodag/rest/stac.py +40 -38
  59. eodag/rest/types/collections_search.py +3 -3
  60. eodag/rest/types/eodag_search.py +23 -23
  61. eodag/rest/types/queryables.py +13 -13
  62. eodag/rest/types/stac_search.py +15 -25
  63. eodag/rest/utils/__init__.py +11 -21
  64. eodag/rest/utils/cql_evaluate.py +6 -6
  65. eodag/rest/utils/rfc3339.py +2 -2
  66. eodag/types/__init__.py +24 -18
  67. eodag/types/bbox.py +2 -2
  68. eodag/types/download_args.py +2 -2
  69. eodag/types/queryables.py +5 -2
  70. eodag/types/search_args.py +4 -4
  71. eodag/types/whoosh.py +1 -3
  72. eodag/utils/__init__.py +81 -40
  73. eodag/utils/exceptions.py +2 -2
  74. eodag/utils/import_system.py +2 -2
  75. eodag/utils/requests.py +2 -2
  76. eodag/utils/rest.py +2 -2
  77. eodag/utils/s3.py +208 -0
  78. eodag/utils/stac_reader.py +10 -10
  79. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/METADATA +5 -4
  80. eodag-3.1.0b2.dist-info/RECORD +113 -0
  81. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/entry_points.txt +1 -0
  82. eodag-3.1.0b1.dist-info/RECORD +0 -108
  83. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/LICENSE +0 -0
  84. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/WHEEL +0 -0
  85. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/top_level.txt +0 -0
eodag/rest/stac.py CHANGED
@@ -21,7 +21,7 @@ import logging
21
21
  import os
22
22
  from collections import defaultdict
23
23
  from datetime import datetime, timezone
24
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
24
+ from typing import TYPE_CHECKING, Any, Optional
25
25
  from urllib.parse import (
26
26
  parse_qs,
27
27
  quote,
@@ -82,6 +82,8 @@ COLLECTION_PROPERTIES = [
82
82
  "missionEndDate",
83
83
  "keywords",
84
84
  "stacCollection",
85
+ "alias",
86
+ "productType",
85
87
  ]
86
88
  IGNORED_ITEM_PROPERTIES = [
87
89
  "_id",
@@ -118,7 +120,7 @@ class StacCommon:
118
120
  def __init__(
119
121
  self,
120
122
  url: str,
121
- stac_config: Dict[str, Any],
123
+ stac_config: dict[str, Any],
122
124
  provider: Optional[str],
123
125
  eodag_api: EODataAccessGateway,
124
126
  root: str = "/",
@@ -129,9 +131,9 @@ class StacCommon:
129
131
  self.eodag_api = eodag_api
130
132
  self.root = root.rstrip("/") if len(root) > 1 else root
131
133
 
132
- self.data: Dict[str, Any] = {}
134
+ self.data: dict[str, Any] = {}
133
135
 
134
- def update_data(self, data: Dict[str, Any]) -> None:
136
+ def update_data(self, data: dict[str, Any]) -> None:
135
137
  """Updates data using given input STAC dict data
136
138
 
137
139
  :param data: Catalog data (parsed STAC dict)
@@ -165,8 +167,8 @@ class StacCommon:
165
167
 
166
168
  @staticmethod
167
169
  def get_stac_extension(
168
- url: str, stac_config: Dict[str, Any], extension: str, **kwargs: Any
169
- ) -> Dict[str, str]:
170
+ url: str, stac_config: dict[str, Any], extension: str, **kwargs: Any
171
+ ) -> dict[str, str]:
170
172
  """Parse STAC extension from config and return as dict
171
173
 
172
174
  :param url: Requested URL
@@ -185,7 +187,7 @@ class StacCommon:
185
187
  }
186
188
  return format_dict_items(extension_model, **format_args)
187
189
 
188
- def get_provider_dict(self, provider: str) -> Dict[str, Any]:
190
+ def get_provider_dict(self, provider: str) -> dict[str, Any]:
189
191
  """Generate STAC provider dict"""
190
192
  provider_config = next(
191
193
  p
@@ -214,7 +216,7 @@ class StacItem(StacCommon):
214
216
  def __init__(
215
217
  self,
216
218
  url: str,
217
- stac_config: Dict[str, Any],
219
+ stac_config: dict[str, Any],
218
220
  provider: Optional[str],
219
221
  eodag_api: EODataAccessGateway,
220
222
  root: str = "/",
@@ -228,8 +230,8 @@ class StacItem(StacCommon):
228
230
  )
229
231
 
230
232
  def __get_item_list(
231
- self, search_results: SearchResult, catalog: Dict[str, Any]
232
- ) -> List[Dict[str, Any]]:
233
+ self, search_results: SearchResult, catalog: dict[str, Any]
234
+ ) -> list[dict[str, Any]]:
233
235
  """Build STAC items list from EODAG search results
234
236
 
235
237
  :param search_results: EODAG search results
@@ -244,7 +246,7 @@ class StacItem(StacCommon):
244
246
  )
245
247
 
246
248
  # check if some items need to be converted
247
- need_conversion: Dict[str, Any] = {}
249
+ need_conversion: dict[str, Any] = {}
248
250
  for k, v in item_model["properties"].items():
249
251
  if isinstance(v, str):
250
252
  conversion, item_model["properties"][k] = get_metadata_path(
@@ -264,11 +266,11 @@ class StacItem(StacCommon):
264
266
  ]
265
267
  ignored_props = COLLECTION_PROPERTIES + item_props + IGNORED_ITEM_PROPERTIES
266
268
 
267
- item_list: List[Dict[str, Any]] = []
269
+ item_list: list[dict[str, Any]] = []
268
270
  for product in search_results:
269
271
  product_dict = deepcopy(product.__dict__)
270
272
 
271
- product_item: Dict[str, Any] = jsonpath_parse_dict_items(
273
+ product_item: dict[str, Any] = jsonpath_parse_dict_items(
272
274
  item_model,
273
275
  {
274
276
  "product": product_dict,
@@ -370,10 +372,10 @@ class StacItem(StacCommon):
370
372
  product: EOProduct,
371
373
  downloadlink_href: str,
372
374
  without_arg_url: str,
373
- query_dict: Optional[Dict[str, Any]] = None,
375
+ query_dict: Optional[dict[str, Any]] = None,
374
376
  _dc_qs: Optional[str] = None,
375
- ) -> Dict[str, Any]:
376
- assets: Dict[str, Any] = {}
377
+ ) -> dict[str, Any]:
378
+ assets: dict[str, Any] = {}
377
379
  settings = Settings.from_environment()
378
380
 
379
381
  if _dc_qs:
@@ -452,9 +454,9 @@ class StacItem(StacCommon):
452
454
  self,
453
455
  search_results: SearchResult,
454
456
  total: int,
455
- catalog: Dict[str, Any],
456
- next_link: Optional[Dict[str, Any]],
457
- ) -> Dict[str, Any]:
457
+ catalog: dict[str, Any],
458
+ next_link: Optional[dict[str, Any]],
459
+ ) -> dict[str, Any]:
458
460
  """Build STAC items from EODAG search results
459
461
 
460
462
  :param search_results: EODAG search results
@@ -503,8 +505,8 @@ class StacItem(StacCommon):
503
505
  return self.data
504
506
 
505
507
  def __filter_item_model_properties(
506
- self, item_model: Dict[str, Any], product_type: str
507
- ) -> Dict[str, Any]:
508
+ self, item_model: dict[str, Any], product_type: str
509
+ ) -> dict[str, Any]:
508
510
  """Filter item model depending on product type metadata and its extensions.
509
511
  Removes not needed parameters, and adds supplementary ones as
510
512
  part of oseo extension.
@@ -568,13 +570,13 @@ class StacItem(StacCommon):
568
570
 
569
571
  return result_item_model
570
572
 
571
- def __filter_item_properties_values(self, item: Dict[str, Any]) -> Dict[str, Any]:
573
+ def __filter_item_properties_values(self, item: dict[str, Any]) -> dict[str, Any]:
572
574
  """Removes empty properties, unused extensions, and add missing extensions
573
575
 
574
576
  :param item: STAC item data
575
577
  :returns: Filtered item model
576
578
  """
577
- all_extensions_dict: Dict[str, str] = deepcopy(
579
+ all_extensions_dict: dict[str, str] = deepcopy(
578
580
  self.stac_config["stac_extensions"]
579
581
  )
580
582
  # parse f-strings with root
@@ -599,7 +601,7 @@ class StacItem(StacCommon):
599
601
 
600
602
  return item
601
603
 
602
- def get_stac_item_from_product(self, product: EOProduct) -> Dict[str, Any]:
604
+ def get_stac_item_from_product(self, product: EOProduct) -> dict[str, Any]:
603
605
  """Build STAC item from EODAG product
604
606
 
605
607
  :param product: EODAG product
@@ -659,7 +661,7 @@ class StacCollection(StacCommon):
659
661
  """
660
662
 
661
663
  # External STAC collections
662
- ext_stac_collections: Dict[str, Dict[str, Any]] = dict()
664
+ ext_stac_collections: dict[str, dict[str, Any]] = dict()
663
665
 
664
666
  @classmethod
665
667
  def fetch_external_stac_collections(cls, eodag_api: EODataAccessGateway) -> None:
@@ -688,7 +690,7 @@ class StacCollection(StacCommon):
688
690
  def __init__(
689
691
  self,
690
692
  url: str,
691
- stac_config: Dict[str, Any],
693
+ stac_config: dict[str, Any],
692
694
  provider: Optional[str],
693
695
  eodag_api: EODataAccessGateway,
694
696
  root: str = "/",
@@ -701,7 +703,7 @@ class StacCollection(StacCommon):
701
703
  root=root,
702
704
  )
703
705
 
704
- def __list_product_type_providers(self, product_type: Dict[str, Any]) -> List[str]:
706
+ def __list_product_type_providers(self, product_type: dict[str, Any]) -> list[str]:
705
707
  """Retrieve a list of providers for a given product type.
706
708
 
707
709
  :param product_type: Dictionary containing information about the product type.
@@ -718,8 +720,8 @@ class StacCollection(StacCommon):
718
720
  ]
719
721
 
720
722
  def __generate_stac_collection(
721
- self, collection_model: Any, product_type: Dict[str, Any]
722
- ) -> Dict[str, Any]:
723
+ self, collection_model: Any, product_type: dict[str, Any]
724
+ ) -> dict[str, Any]:
723
725
  """Generate a STAC collection dictionary for a given product type.
724
726
 
725
727
  :param collection_model: The base model for the STAC collection.
@@ -728,7 +730,7 @@ class StacCollection(StacCommon):
728
730
  """
729
731
  providers = self.__list_product_type_providers(product_type)
730
732
 
731
- providers_dict: Dict[str, Dict[str, Any]] = {}
733
+ providers_dict: dict[str, dict[str, Any]] = {}
732
734
  for provider in providers:
733
735
  p_dict = self.get_provider_dict(provider)
734
736
  providers_dict.setdefault(p_dict["name"], p_dict)
@@ -815,7 +817,7 @@ class StacCollection(StacCommon):
815
817
  instrument: Optional[str] = None,
816
818
  constellation: Optional[str] = None,
817
819
  datetime: Optional[str] = None,
818
- ) -> List[Dict[str, Any]]:
820
+ ) -> list[dict[str, Any]]:
819
821
  """Build STAC collections list
820
822
 
821
823
  :param filters: (optional) Additional filters for collections search
@@ -850,7 +852,7 @@ class StacCollection(StacCommon):
850
852
  product_types = all_pt
851
853
 
852
854
  # list product types with all metadata using guessed ids
853
- collection_list: List[Dict[str, Any]] = []
855
+ collection_list: list[dict[str, Any]] = []
854
856
  for product_type in product_types:
855
857
  stac_collection = self.__generate_stac_collection(
856
858
  collection_model, product_type
@@ -874,7 +876,7 @@ class StacCatalog(StacCommon):
874
876
  def __init__(
875
877
  self,
876
878
  url: str,
877
- stac_config: Dict[str, Any],
879
+ stac_config: dict[str, Any],
878
880
  provider: Optional[str],
879
881
  eodag_api: EODataAccessGateway,
880
882
  root: str = "/",
@@ -890,8 +892,8 @@ class StacCatalog(StacCommon):
890
892
  self.data = {}
891
893
 
892
894
  self.shp_location_config = eodag_api.locations_config
893
- self.search_args: Dict[str, Any] = {}
894
- self.children: List[Dict[str, Any]] = []
895
+ self.search_args: dict[str, Any] = {}
896
+ self.children: list[dict[str, Any]] = []
895
897
 
896
898
  self.catalog_config = deepcopy(stac_config["catalog"])
897
899
 
@@ -907,7 +909,7 @@ class StacCatalog(StacCommon):
907
909
  # build catalog
908
910
  self.__build_stac_catalog(collection)
909
911
 
910
- def __update_data_from_catalog_config(self, catalog_config: Dict[str, Any]) -> bool:
912
+ def __update_data_from_catalog_config(self, catalog_config: dict[str, Any]) -> bool:
911
913
  """Updates configuration and data using given input catalog config
912
914
 
913
915
  :param catalog_config: Catalog config, from yml stac_config[catalogs]
@@ -959,7 +961,7 @@ class StacCatalog(StacCommon):
959
961
 
960
962
  def set_stac_product_type_by_id(
961
963
  self, product_type: str, **_: Any
962
- ) -> Dict[str, Any]:
964
+ ) -> dict[str, Any]:
963
965
  """Updates catalog with given product_type
964
966
 
965
967
  :param product_type: Product type
@@ -991,7 +993,7 @@ class StacCatalog(StacCommon):
991
993
  format_args["catalog"] = defaultdict(str, **self.data)
992
994
  format_args["collection"] = collections[0]
993
995
  try:
994
- parsed_dict: Dict[str, Any] = format_dict_items(cat_model, **format_args)
996
+ parsed_dict: dict[str, Any] = format_dict_items(cat_model, **format_args)
995
997
  except Exception:
996
998
  logger.error("Could not format product_type catalog")
997
999
  raise
@@ -15,7 +15,7 @@
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
- from typing import Any, Dict, Optional
18
+ from typing import Any, Optional
19
19
 
20
20
  from pydantic import (
21
21
  BaseModel,
@@ -39,6 +39,6 @@ class CollectionsSearchRequest(BaseModel):
39
39
  constellation: Optional[str] = Field(default=None)
40
40
 
41
41
  @model_serializer(mode="wrap")
42
- def _serialize(self, handler: SerializerFunctionWrapHandler) -> Dict[str, Any]:
43
- dumped: Dict[str, Any] = handler(self)
42
+ def _serialize(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]:
43
+ dumped: dict[str, Any] = handler(self)
44
44
  return {EODAGSearch.to_eodag(k): v for k, v in dumped.items()}
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
  from __future__ import annotations
19
19
 
20
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union, cast
20
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast
21
21
 
22
22
  from pydantic import (
23
23
  AliasChoices,
@@ -52,7 +52,7 @@ if TYPE_CHECKING:
52
52
  from typing_extensions import Self
53
53
 
54
54
  Geometry = Union[
55
- Dict[str, Any],
55
+ dict[str, Any],
56
56
  Point,
57
57
  MultiPoint,
58
58
  LineString,
@@ -73,8 +73,8 @@ class EODAGSearch(BaseModel):
73
73
 
74
74
  productType: Optional[str] = Field(None, alias="collections", validate_default=True)
75
75
  provider: Optional[str] = Field(None)
76
- ids: Optional[List[str]] = Field(None)
77
- id: Optional[List[str]] = Field(
76
+ ids: Optional[list[str]] = Field(None)
77
+ id: Optional[list[str]] = Field(
78
78
  None, alias="ids"
79
79
  ) # TODO: remove when updating queryables
80
80
  geom: Optional[Geometry] = Field(None, alias="geometry")
@@ -101,7 +101,7 @@ class EODAGSearch(BaseModel):
101
101
  orbitNumber: Optional[int] = Field(None, alias="sat:absolute_orbit")
102
102
  # TODO: colision in property name. Need to handle "sar:product_type"
103
103
  sensorMode: Optional[str] = Field(None, alias="sar:instrument_mode")
104
- polarizationChannels: Optional[List[str]] = Field(None, alias="sar:polarizations")
104
+ polarizationChannels: Optional[list[str]] = Field(None, alias="sar:polarizations")
105
105
  dopplerFrequency: Optional[str] = Field(None, alias="sar:frequency_band")
106
106
  doi: Optional[str] = Field(None, alias="sci:doi")
107
107
  illuminationElevationAngle: Optional[float] = Field(
@@ -110,10 +110,10 @@ class EODAGSearch(BaseModel):
110
110
  illuminationAzimuthAngle: Optional[float] = Field(None, alias="view:sun_azimuth")
111
111
  page: Optional[int] = Field(1)
112
112
  items_per_page: int = Field(DEFAULT_ITEMS_PER_PAGE, alias="limit")
113
- sort_by: Optional[List[Tuple[str, str]]] = Field(None, alias="sortby")
113
+ sort_by: Optional[list[tuple[str, str]]] = Field(None, alias="sortby")
114
114
  raise_errors: bool = False
115
115
 
116
- _to_eodag_map: Dict[str, str]
116
+ _to_eodag_map: dict[str, str]
117
117
 
118
118
  @model_validator(mode="after")
119
119
  def remove_timeFromAscendingNode(self) -> Self: # pylint: disable=invalid-name
@@ -129,7 +129,7 @@ class EODAGSearch(BaseModel):
129
129
  if not self.__pydantic_extra__:
130
130
  return self
131
131
 
132
- keys_to_update: Dict[str, str] = {}
132
+ keys_to_update: dict[str, str] = {}
133
133
  for key in self.__pydantic_extra__.keys():
134
134
  if key.startswith("unk:"):
135
135
  keys_to_update[key] = key[len("unk:") :]
@@ -145,7 +145,7 @@ class EODAGSearch(BaseModel):
145
145
 
146
146
  @model_validator(mode="before")
147
147
  @classmethod
148
- def remove_keys(cls, values: Dict[str, Any]) -> Dict[str, Any]:
148
+ def remove_keys(cls, values: dict[str, Any]) -> dict[str, Any]:
149
149
  """Remove 'datetime', 'crunch', 'intersects', and 'bbox' keys"""
150
150
  for key in ["datetime", "crunch", "intersects", "bbox", "filter_lang"]:
151
151
  values.pop(key, None)
@@ -154,8 +154,8 @@ class EODAGSearch(BaseModel):
154
154
  @model_validator(mode="before")
155
155
  @classmethod
156
156
  def parse_collections(
157
- cls, values: Dict[str, Any], info: ValidationInfo
158
- ) -> Dict[str, Any]:
157
+ cls, values: dict[str, Any], info: ValidationInfo
158
+ ) -> dict[str, Any]:
159
159
  """convert collections to productType"""
160
160
 
161
161
  if collections := values.pop("collections", None):
@@ -172,7 +172,7 @@ class EODAGSearch(BaseModel):
172
172
 
173
173
  @model_validator(mode="before")
174
174
  @classmethod
175
- def parse_query(cls, values: Dict[str, Any]) -> Dict[str, Any]:
175
+ def parse_query(cls, values: dict[str, Any]) -> dict[str, Any]:
176
176
  """
177
177
  Convert a STAC query parameter filter with the "eq" operator to a dict.
178
178
  """
@@ -190,9 +190,9 @@ class EODAGSearch(BaseModel):
190
190
  if not query:
191
191
  return values
192
192
 
193
- query_props: Dict[str, Any] = {}
194
- errors: List[InitErrorDetails] = []
195
- for property_name, conditions in cast(Dict[str, Any], query).items():
193
+ query_props: dict[str, Any] = {}
194
+ errors: list[InitErrorDetails] = []
195
+ for property_name, conditions in cast(dict[str, Any], query).items():
196
196
  # Remove the prefix "properties." if present
197
197
  prop = property_name.replace("properties.", "", 1)
198
198
 
@@ -205,7 +205,7 @@ class EODAGSearch(BaseModel):
205
205
  continue
206
206
 
207
207
  # Retrieve the operator and its value
208
- operator, value = next(iter(cast(Dict[str, Any], conditions).items()))
208
+ operator, value = next(iter(cast(dict[str, Any], conditions).items()))
209
209
 
210
210
  # Validate the operator
211
211
  # only eq, in and lte are allowed
@@ -239,7 +239,7 @@ class EODAGSearch(BaseModel):
239
239
 
240
240
  @model_validator(mode="before")
241
241
  @classmethod
242
- def parse_cql(cls, values: Dict[str, Any]) -> Dict[str, Any]:
242
+ def parse_cql(cls, values: dict[str, Any]) -> dict[str, Any]:
243
243
  """
244
244
  Process cql2 filter
245
245
  """
@@ -256,7 +256,7 @@ class EODAGSearch(BaseModel):
256
256
  if not filter_:
257
257
  return values
258
258
 
259
- errors: List[InitErrorDetails] = []
259
+ errors: list[InitErrorDetails] = []
260
260
  try:
261
261
  parsing_result = EodagEvaluator().evaluate(parse_json(filter_)) # type: ignore
262
262
  except (ValueError, NotImplementedError) as e:
@@ -271,7 +271,7 @@ class EODAGSearch(BaseModel):
271
271
  title=cls.__name__, line_errors=errors
272
272
  )
273
273
 
274
- cql_args: Dict[str, Any] = cast(Dict[str, Any], parsing_result)
274
+ cql_args: dict[str, Any] = cast(dict[str, Any], parsing_result)
275
275
 
276
276
  invalid_keys = {
277
277
  "collections": 'Use "collection" instead of "collections"',
@@ -298,7 +298,7 @@ class EODAGSearch(BaseModel):
298
298
 
299
299
  @field_validator("instrument", mode="before")
300
300
  @classmethod
301
- def join_instruments(cls, v: Union[str, List[str]]) -> str:
301
+ def join_instruments(cls, v: Union[str, list[str]]) -> str:
302
302
  """convert instruments to instrument"""
303
303
  if isinstance(v, list):
304
304
  return ",".join(v)
@@ -308,8 +308,8 @@ class EODAGSearch(BaseModel):
308
308
  @classmethod
309
309
  def parse_sortby(
310
310
  cls,
311
- sortby_post_params: List[Dict[str, str]],
312
- ) -> List[Tuple[str, str]]:
311
+ sortby_post_params: list[dict[str, str]],
312
+ ) -> list[tuple[str, str]]:
313
313
  """
314
314
  Convert STAC POST sortby to EODAG sort_by
315
315
  """
@@ -363,7 +363,7 @@ class EODAGSearch(BaseModel):
363
363
  def to_stac(
364
364
  cls,
365
365
  field_name: str,
366
- stac_item_properties: Optional[List[str]] = None,
366
+ stac_item_properties: Optional[list[str]] = None,
367
367
  provider: Optional[str] = None,
368
368
  ) -> str:
369
369
  """Get the alias of a field in a Pydantic model"""
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
  from __future__ import annotations
19
19
 
20
- from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Dict, List, Optional, Union
20
+ from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Optional, Union
21
21
 
22
22
  from pydantic import (
23
23
  BaseModel,
@@ -46,8 +46,8 @@ class QueryablesGetParams(BaseModel):
46
46
  model_config = ConfigDict(extra="allow", frozen=True)
47
47
 
48
48
  @model_serializer(mode="wrap")
49
- def _serialize(self, handler: SerializerFunctionWrapHandler) -> Dict[str, Any]:
50
- dumped: Dict[str, Any] = handler(self)
49
+ def _serialize(self, handler: SerializerFunctionWrapHandler) -> dict[str, Any]:
50
+ dumped: dict[str, Any] = handler(self)
51
51
  return {EODAGSearch.to_eodag(k): v for k, v in dumped.items()}
52
52
 
53
53
  # use [prop-decorator] mypy error code when mypy==1.12 is released
@@ -77,12 +77,12 @@ class StacQueryableProperty(BaseModel):
77
77
 
78
78
  description: str
79
79
  ref: Optional[str] = Field(default=None, serialization_alias="$ref")
80
- type: Optional[Union[str, List[str]]] = None
81
- enum: Optional[List[Any]] = None
80
+ type: Optional[Union[str, list[str]]] = None
81
+ enum: Optional[list[Any]] = None
82
82
  value: Optional[Any] = None
83
- min: Optional[Union[int, List[Union[int, None]]]] = None
84
- max: Optional[Union[int, List[Union[int, None]]]] = None
85
- oneOf: Optional[List[Any]] = None
83
+ min: Optional[Union[int, list[Union[int, None]]]] = None
84
+ max: Optional[Union[int, list[Union[int, None]]]] = None
85
+ oneOf: Optional[list[Any]] = None
86
86
  items: Optional[Any] = None
87
87
 
88
88
  @classmethod
@@ -104,7 +104,7 @@ class StacQueryableProperty(BaseModel):
104
104
  _: SerializationInfo,
105
105
  ):
106
106
  """Remove none value property fields during serialization"""
107
- props: Dict[str, Any] = handler(self)
107
+ props: dict[str, Any] = handler(self)
108
108
  return {k: v for k, v in props.items() if v is not None}
109
109
 
110
110
 
@@ -130,13 +130,13 @@ class StacQueryables(BaseModel):
130
130
  description: str = Field(
131
131
  default="Queryable names for the EODAG STAC API Item Search filter."
132
132
  )
133
- default_properties: ClassVar[Dict[str, StacQueryableProperty]] = {
133
+ default_properties: ClassVar[dict[str, StacQueryableProperty]] = {
134
134
  "collection": StacQueryableProperty(
135
135
  description="Collection",
136
136
  ref="https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json#/collection",
137
137
  )
138
138
  }
139
- possible_properties: ClassVar[Dict[str, StacQueryableProperty]] = {
139
+ possible_properties: ClassVar[dict[str, StacQueryableProperty]] = {
140
140
  "geometry": StacQueryableProperty(
141
141
  description="Geometry",
142
142
  ref="https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json#/geometry",
@@ -152,8 +152,8 @@ class StacQueryables(BaseModel):
152
152
  items={"type": "number"},
153
153
  ),
154
154
  }
155
- properties: Dict[str, Any] = Field()
156
- required: Optional[List[str]] = Field(None)
155
+ properties: dict[str, Any] = Field()
156
+ required: Optional[list[str]] = Field(None)
157
157
  additional_properties: bool = Field(
158
158
  default=True, serialization_alias="additionalProperties"
159
159
  )
@@ -19,17 +19,7 @@
19
19
 
20
20
  from __future__ import annotations
21
21
 
22
- from typing import (
23
- TYPE_CHECKING,
24
- Annotated,
25
- Any,
26
- Dict,
27
- List,
28
- Literal,
29
- Optional,
30
- Tuple,
31
- Union,
32
- )
22
+ from typing import TYPE_CHECKING, Annotated, Any, Literal, Optional, Union
33
23
 
34
24
  import geojson
35
25
  from pydantic import (
@@ -63,8 +53,8 @@ if TYPE_CHECKING:
63
53
  NumType = Union[float, int]
64
54
 
65
55
  BBox = Union[
66
- Tuple[NumType, NumType, NumType, NumType],
67
- Tuple[NumType, NumType, NumType, NumType, NumType, NumType],
56
+ tuple[NumType, NumType, NumType, NumType],
57
+ tuple[NumType, NumType, NumType, NumType, NumType, NumType],
68
58
  ]
69
59
 
70
60
  Geometry = Union[
@@ -106,8 +96,8 @@ class SearchPostRequest(BaseModel):
106
96
  model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True)
107
97
 
108
98
  provider: Optional[str] = None
109
- collections: Optional[List[str]] = None
110
- ids: Optional[List[str]] = None
99
+ collections: Optional[list[str]] = None
100
+ ids: Optional[list[str]] = None
111
101
  bbox: Optional[BBox] = None
112
102
  intersects: Optional[Geometry] = None
113
103
  datetime: Optional[str] = None
@@ -117,21 +107,21 @@ class SearchPostRequest(BaseModel):
117
107
  page: Optional[PositiveInt] = Field( # type: ignore
118
108
  default=None, description="Page number, must be a positive integer."
119
109
  )
120
- query: Optional[Dict[str, Any]] = None
121
- filter: Optional[Dict[str, Any]] = None
110
+ query: Optional[dict[str, Any]] = None
111
+ filter: Optional[dict[str, Any]] = None
122
112
  filter_lang: Optional[str] = Field(
123
113
  default=None,
124
114
  alias="filter-lang",
125
115
  description="The language used for filtering.",
126
116
  validate_default=True,
127
117
  )
128
- sortby: Optional[List[SortBy]] = None
118
+ sortby: Optional[list[SortBy]] = None
129
119
  crunch: Optional[str] = None
130
120
 
131
121
  @field_serializer("intersects")
132
122
  def serialize_intersects(
133
123
  self, intersects: Optional[Geometry]
134
- ) -> Optional[Dict[str, Any]]:
124
+ ) -> Optional[dict[str, Any]]:
135
125
  """Serialize intersects from shapely to a proper dict"""
136
126
  if intersects:
137
127
  return geojson.loads(geojson.dumps(intersects)) # type: ignore
@@ -150,7 +140,7 @@ class SearchPostRequest(BaseModel):
150
140
 
151
141
  @model_validator(mode="before")
152
142
  @classmethod
153
- def only_one_spatial(cls, values: Dict[str, Any]) -> Dict[str, Any]:
143
+ def only_one_spatial(cls, values: dict[str, Any]) -> dict[str, Any]:
154
144
  """Check bbox and intersects are not both supplied."""
155
145
  if "intersects" in values and "bbox" in values:
156
146
  raise ValueError("intersects and bbox parameters are mutually exclusive")
@@ -170,7 +160,7 @@ class SearchPostRequest(BaseModel):
170
160
 
171
161
  @field_validator("ids", "collections", mode="before")
172
162
  @classmethod
173
- def str_to_str_list(cls, v: Union[str, List[str]]) -> List[str]:
163
+ def str_to_str_list(cls, v: Union[str, list[str]]) -> list[str]:
174
164
  """Convert ids and collections strings to list of strings"""
175
165
  if isinstance(v, str):
176
166
  return [i.strip() for i in v.split(",")]
@@ -178,7 +168,7 @@ class SearchPostRequest(BaseModel):
178
168
 
179
169
  @field_validator("intersects", mode="before")
180
170
  @classmethod
181
- def validate_intersects(cls, v: Union[Dict[str, Any], Geometry]) -> Geometry:
171
+ def validate_intersects(cls, v: Union[dict[str, Any], Geometry]) -> Geometry:
182
172
  """Verify format of intersects"""
183
173
  if isinstance(v, BaseGeometry):
184
174
  return v
@@ -224,7 +214,7 @@ class SearchPostRequest(BaseModel):
224
214
  # Single date is interpreted as end date
225
215
  values = ["..", v]
226
216
 
227
- dates: List[str] = []
217
+ dates: list[str] = []
228
218
  for value in values:
229
219
  if value == ".." or value == "":
230
220
  dates.append("..")
@@ -267,13 +257,13 @@ class SearchPostRequest(BaseModel):
267
257
 
268
258
  def sortby2list(
269
259
  v: Optional[str],
270
- ) -> Optional[List[SortBy]]:
260
+ ) -> Optional[list[SortBy]]:
271
261
  """
272
262
  Convert sortby filter parameter GET syntax to POST syntax
273
263
  """
274
264
  if not v:
275
265
  return None
276
- sortby: List[SortBy] = []
266
+ sortby: list[SortBy] = []
277
267
  for sortby_param in v.split(","):
278
268
  sortby_param = sortby_param.strip()
279
269
  direction: Direction = "desc" if sortby_param.startswith("-") else "asc"