eodag 3.0.0b2__py3-none-any.whl → 3.0.0b3__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/__init__.py +6 -8
- eodag/api/core.py +113 -169
- eodag/api/product/__init__.py +10 -4
- eodag/api/product/_assets.py +2 -14
- eodag/api/product/_product.py +16 -30
- eodag/api/product/drivers/__init__.py +7 -2
- eodag/api/product/drivers/base.py +0 -3
- eodag/api/product/metadata_mapping.py +0 -28
- eodag/api/search_result.py +4 -9
- eodag/config.py +45 -41
- eodag/plugins/apis/base.py +3 -3
- eodag/plugins/apis/ecmwf.py +2 -3
- eodag/plugins/apis/usgs.py +43 -14
- eodag/plugins/authentication/aws_auth.py +11 -2
- eodag/plugins/authentication/openid_connect.py +5 -4
- eodag/plugins/authentication/token.py +2 -1
- eodag/plugins/crunch/base.py +3 -1
- eodag/plugins/crunch/filter_date.py +3 -9
- eodag/plugins/crunch/filter_latest_intersect.py +0 -3
- eodag/plugins/crunch/filter_latest_tpl_name.py +1 -4
- eodag/plugins/crunch/filter_overlap.py +4 -8
- eodag/plugins/crunch/filter_property.py +5 -11
- eodag/plugins/download/aws.py +46 -78
- eodag/plugins/download/base.py +27 -68
- eodag/plugins/download/http.py +48 -57
- eodag/plugins/download/s3rest.py +17 -25
- eodag/plugins/manager.py +5 -18
- eodag/plugins/search/__init__.py +9 -9
- eodag/plugins/search/base.py +7 -26
- eodag/plugins/search/build_search_result.py +0 -13
- eodag/plugins/search/cop_marine.py +1 -3
- eodag/plugins/search/creodias_s3.py +0 -3
- eodag/plugins/search/data_request_search.py +10 -5
- eodag/plugins/search/qssearch.py +95 -53
- eodag/plugins/search/static_stac_search.py +6 -3
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +24 -0
- eodag/resources/providers.yml +198 -154
- eodag/resources/user_conf_template.yml +27 -27
- eodag/rest/core.py +11 -43
- eodag/rest/server.py +1 -6
- eodag/rest/stac.py +13 -87
- eodag/rest/types/eodag_search.py +4 -7
- eodag/rest/types/queryables.py +4 -12
- eodag/rest/types/stac_search.py +7 -11
- eodag/rest/utils/rfc3339.py +0 -1
- eodag/types/__init__.py +9 -3
- eodag/types/download_args.py +14 -5
- eodag/types/search_args.py +7 -8
- eodag/types/whoosh.py +0 -2
- eodag/utils/__init__.py +20 -79
- eodag/utils/constraints.py +0 -8
- eodag/utils/import_system.py +0 -4
- eodag/utils/logging.py +0 -3
- eodag/utils/notebook.py +4 -4
- eodag/utils/requests.py +12 -20
- eodag/utils/rest.py +0 -4
- eodag/utils/stac_reader.py +2 -14
- {eodag-3.0.0b2.dist-info → eodag-3.0.0b3.dist-info}/METADATA +32 -14
- eodag-3.0.0b3.dist-info/RECORD +110 -0
- {eodag-3.0.0b2.dist-info → eodag-3.0.0b3.dist-info}/WHEEL +1 -1
- eodag-3.0.0b2.dist-info/RECORD +0 -110
- {eodag-3.0.0b2.dist-info → eodag-3.0.0b3.dist-info}/LICENSE +0 -0
- {eodag-3.0.0b2.dist-info → eodag-3.0.0b3.dist-info}/entry_points.txt +0 -0
- {eodag-3.0.0b2.dist-info → eodag-3.0.0b3.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,
|
|
24
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast
|
|
25
25
|
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
|
26
26
|
|
|
27
27
|
import dateutil.parser
|
|
@@ -106,15 +106,10 @@ class StacCommon:
|
|
|
106
106
|
"""Stac common object
|
|
107
107
|
|
|
108
108
|
:param url: Requested URL
|
|
109
|
-
:type url: str
|
|
110
109
|
:param stac_config: STAC configuration from stac.yml conf file
|
|
111
|
-
:type stac_config: dict
|
|
112
110
|
:param provider: (optional) Chosen provider
|
|
113
|
-
:type provider: str
|
|
114
111
|
:param eodag_api: EODAG python API instance
|
|
115
|
-
:type eodag_api: :class:`eodag.api.core.EODataAccessGateway`
|
|
116
112
|
:param root: (optional) API root
|
|
117
|
-
:type root: str
|
|
118
113
|
"""
|
|
119
114
|
|
|
120
115
|
def __init__(
|
|
@@ -137,7 +132,6 @@ class StacCommon:
|
|
|
137
132
|
"""Updates data using given input STAC dict data
|
|
138
133
|
|
|
139
134
|
:param data: Catalog data (parsed STAC dict)
|
|
140
|
-
:type data: dict
|
|
141
135
|
"""
|
|
142
136
|
self.data.update(data)
|
|
143
137
|
|
|
@@ -149,16 +143,18 @@ class StacCommon:
|
|
|
149
143
|
):
|
|
150
144
|
for i, bbox in enumerate(self.data["extent"]["spatial"]["bbox"]):
|
|
151
145
|
self.data["extent"]["spatial"]["bbox"][i] = [float(x) for x in bbox]
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
None
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
146
|
+
|
|
147
|
+
def apply_method_none(_: str, v: str) -> Optional[str]:
|
|
148
|
+
""" "None" values to None"""
|
|
149
|
+
return None if v == "None" else v
|
|
150
|
+
|
|
151
|
+
self.data = dict_items_recursive_apply(self.data, apply_method_none)
|
|
152
|
+
|
|
153
|
+
def apply_method_ids(k, v):
|
|
154
|
+
"""ids and titles as str"""
|
|
155
|
+
return str(v) if k in ["title", "id"] else v
|
|
156
|
+
|
|
157
|
+
self.data = dict_items_recursive_apply(self.data, apply_method_ids)
|
|
162
158
|
|
|
163
159
|
# empty stac_extensions: "" to []
|
|
164
160
|
if not self.data.get("stac_extensions", True):
|
|
@@ -171,15 +167,10 @@ class StacCommon:
|
|
|
171
167
|
"""Parse STAC extension from config and return as dict
|
|
172
168
|
|
|
173
169
|
:param url: Requested URL
|
|
174
|
-
:type url: str
|
|
175
170
|
:param stac_config: STAC configuration from stac.yml conf file
|
|
176
|
-
:type stac_config: dict
|
|
177
171
|
:param extension: Extension name
|
|
178
|
-
:type extension: str
|
|
179
172
|
:param kwargs: Additional variables needed for parsing extension
|
|
180
|
-
:type kwargs: Any
|
|
181
173
|
:returns: STAC extension as dictionnary
|
|
182
|
-
:rtype: dict
|
|
183
174
|
"""
|
|
184
175
|
extension_model = deepcopy(stac_config).get("extensions", {}).get(extension, {})
|
|
185
176
|
|
|
@@ -211,15 +202,10 @@ class StacItem(StacCommon):
|
|
|
211
202
|
"""Stac item object
|
|
212
203
|
|
|
213
204
|
:param url: Requested URL
|
|
214
|
-
:type url: str
|
|
215
205
|
:param stac_config: STAC configuration from stac.yml conf file
|
|
216
|
-
:type stac_config: dict
|
|
217
206
|
:param provider: (optional) Chosen provider
|
|
218
|
-
:type provider: str
|
|
219
207
|
:param eodag_api: EODAG python API instance
|
|
220
|
-
:type eodag_api: :class:`eodag.api.core.EODataAccessGateway`
|
|
221
208
|
:param root: (optional) API root
|
|
222
|
-
:type root: str
|
|
223
209
|
"""
|
|
224
210
|
|
|
225
211
|
def __init__(
|
|
@@ -244,11 +230,8 @@ class StacItem(StacCommon):
|
|
|
244
230
|
"""Build STAC items list from EODAG search results
|
|
245
231
|
|
|
246
232
|
:param search_results: EODAG search results
|
|
247
|
-
:type search_results: :class:`~eodag.api.search_result.SearchResult`
|
|
248
233
|
:param catalog: STAC catalog dict used for parsing item metadata
|
|
249
|
-
:type catalog: dict
|
|
250
234
|
:returns: STAC item dicts list
|
|
251
|
-
:rtype: list
|
|
252
235
|
"""
|
|
253
236
|
if len(search_results) <= 0:
|
|
254
237
|
return []
|
|
@@ -464,11 +447,8 @@ class StacItem(StacCommon):
|
|
|
464
447
|
"""Build STAC items from EODAG search results
|
|
465
448
|
|
|
466
449
|
:param search_results: EODAG search results
|
|
467
|
-
:type search_results: :class:`~eodag.api.search_result.SearchResult`
|
|
468
450
|
:param catalog: STAC catalog dict used for parsing item metadata
|
|
469
|
-
:type catalog: dict
|
|
470
451
|
:returns: Items dictionnary
|
|
471
|
-
:rtype: dict
|
|
472
452
|
"""
|
|
473
453
|
items_model = deepcopy(self.stac_config["items"])
|
|
474
454
|
|
|
@@ -519,11 +499,8 @@ class StacItem(StacCommon):
|
|
|
519
499
|
part of oseo extension.
|
|
520
500
|
|
|
521
501
|
:param item_model: Item model from stac_config
|
|
522
|
-
:type item_model: dict
|
|
523
502
|
:param product_type: Product type
|
|
524
|
-
:type product_type: str
|
|
525
503
|
:returns: Filtered item model
|
|
526
|
-
:rtype: dict
|
|
527
504
|
"""
|
|
528
505
|
try:
|
|
529
506
|
product_type_dict = [
|
|
@@ -584,9 +561,7 @@ class StacItem(StacCommon):
|
|
|
584
561
|
"""Removes empty properties, unused extensions, and add missing extensions
|
|
585
562
|
|
|
586
563
|
:param item: STAC item data
|
|
587
|
-
:type item: dict
|
|
588
564
|
:returns: Filtered item model
|
|
589
|
-
:rtype: dict
|
|
590
565
|
"""
|
|
591
566
|
all_extensions_dict: Dict[str, str] = deepcopy(
|
|
592
567
|
self.stac_config["stac_extensions"]
|
|
@@ -617,9 +592,7 @@ class StacItem(StacCommon):
|
|
|
617
592
|
"""Build STAC item from EODAG product
|
|
618
593
|
|
|
619
594
|
:param product: EODAG product
|
|
620
|
-
:type product: :class:`eodag.api.product._product.EOProduct`
|
|
621
595
|
:returns: STAC item
|
|
622
|
-
:rtype: list
|
|
623
596
|
"""
|
|
624
597
|
product_type = str(product.product_type)
|
|
625
598
|
|
|
@@ -668,15 +641,10 @@ class StacCollection(StacCommon):
|
|
|
668
641
|
"""Stac collection object
|
|
669
642
|
|
|
670
643
|
:param url: Requested URL
|
|
671
|
-
:type url: str
|
|
672
644
|
:param stac_config: STAC configuration from stac.yml conf file
|
|
673
|
-
:type stac_config: dict
|
|
674
645
|
:param provider: (optional) Chosen provider
|
|
675
|
-
:type provider: str
|
|
676
646
|
:param eodag_api: EODAG python API instance
|
|
677
|
-
:type eodag_api: :class:`eodag.api.core.EODataAccessGateway`
|
|
678
647
|
:param root: (optional) API root
|
|
679
|
-
:type root: str
|
|
680
648
|
"""
|
|
681
649
|
|
|
682
650
|
# External STAC collections
|
|
@@ -687,7 +655,6 @@ class StacCollection(StacCommon):
|
|
|
687
655
|
"""Load external STAC collections
|
|
688
656
|
|
|
689
657
|
:param eodag_api: EODAG python API instance
|
|
690
|
-
:type eodag_api: :class:`eodag.api.core.EODataAccessGateway`
|
|
691
658
|
"""
|
|
692
659
|
list_product_types = eodag_api.list_product_types(fetch_providers=False)
|
|
693
660
|
for product_type in list_product_types:
|
|
@@ -727,9 +694,7 @@ class StacCollection(StacCommon):
|
|
|
727
694
|
"""Retrieve a list of providers for a given product type.
|
|
728
695
|
|
|
729
696
|
:param product_type: Dictionary containing information about the product type.
|
|
730
|
-
:type product_type: dict
|
|
731
697
|
:return: A list of provider names.
|
|
732
|
-
:rtype: list
|
|
733
698
|
"""
|
|
734
699
|
if self.provider:
|
|
735
700
|
return [self.provider]
|
|
@@ -747,11 +712,8 @@ class StacCollection(StacCommon):
|
|
|
747
712
|
"""Generate a STAC collection dictionary for a given product type.
|
|
748
713
|
|
|
749
714
|
:param collection_model: The base model for the STAC collection.
|
|
750
|
-
:type collection_model: Any
|
|
751
715
|
:param product_type: Dictionary containing information about the product type.
|
|
752
|
-
:type product_type: dict
|
|
753
716
|
:return: A dictionary representing the STAC collection for the given product type.
|
|
754
|
-
:rtype: dict
|
|
755
717
|
"""
|
|
756
718
|
providers = self.__list_product_type_providers(product_type)
|
|
757
719
|
|
|
@@ -837,9 +799,7 @@ class StacCollection(StacCommon):
|
|
|
837
799
|
"""Build STAC collections list
|
|
838
800
|
|
|
839
801
|
:param filters: (optional) Additional filters for collections search
|
|
840
|
-
:type filters: dict
|
|
841
802
|
:returns: STAC collection dicts list
|
|
842
|
-
:rtype: list
|
|
843
803
|
"""
|
|
844
804
|
collection_model = deepcopy(self.stac_config["collection"])
|
|
845
805
|
|
|
@@ -884,17 +844,11 @@ class StacCatalog(StacCommon):
|
|
|
884
844
|
"""Stac Catalog object
|
|
885
845
|
|
|
886
846
|
:param url: Requested URL
|
|
887
|
-
:type url: str
|
|
888
847
|
:param stac_config: STAC configuration from stac.yml conf file
|
|
889
|
-
:type stac_config: dict
|
|
890
848
|
:param provider: Chosen provider
|
|
891
|
-
:type provider: (optional) str
|
|
892
849
|
:param eodag_api: EODAG python API instance
|
|
893
|
-
:type eodag_api: :class:`eodag.api.core.EODataAccessGateway`
|
|
894
850
|
:param root: (optional) API root
|
|
895
|
-
:type root: str
|
|
896
851
|
:param catalogs: (optional) Catalogs list
|
|
897
|
-
:type catalogs: list
|
|
898
852
|
"""
|
|
899
853
|
|
|
900
854
|
def __init__(
|
|
@@ -937,7 +891,6 @@ class StacCatalog(StacCommon):
|
|
|
937
891
|
"""Updates configuration and data using given input catalog config
|
|
938
892
|
|
|
939
893
|
:param catalog_config: Catalog config, from yml stac_config[catalogs]
|
|
940
|
-
:type catalog_config: dict
|
|
941
894
|
"""
|
|
942
895
|
model = catalog_config["model"]
|
|
943
896
|
|
|
@@ -961,7 +914,6 @@ class StacCatalog(StacCommon):
|
|
|
961
914
|
"""Set catalog children / links
|
|
962
915
|
|
|
963
916
|
:param children: (optional) Children list
|
|
964
|
-
:type children: list
|
|
965
917
|
"""
|
|
966
918
|
self.children = children or []
|
|
967
919
|
self.data["links"] = [
|
|
@@ -976,7 +928,6 @@ class StacCatalog(StacCommon):
|
|
|
976
928
|
"""Updates catalog with given product_type
|
|
977
929
|
|
|
978
930
|
:param product_type: Product type
|
|
979
|
-
:type product_type: str
|
|
980
931
|
"""
|
|
981
932
|
collections = StacCollection(
|
|
982
933
|
url=self.url,
|
|
@@ -1013,7 +964,6 @@ class StacCatalog(StacCommon):
|
|
|
1013
964
|
"""Get catalog available years list
|
|
1014
965
|
|
|
1015
966
|
:returns: Years list
|
|
1016
|
-
:rtype: list
|
|
1017
967
|
"""
|
|
1018
968
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1019
969
|
|
|
@@ -1023,7 +973,6 @@ class StacCatalog(StacCommon):
|
|
|
1023
973
|
"""Get catalog available months list
|
|
1024
974
|
|
|
1025
975
|
:returns: Months list
|
|
1026
|
-
:rtype: list
|
|
1027
976
|
"""
|
|
1028
977
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1029
978
|
|
|
@@ -1038,7 +987,6 @@ class StacCatalog(StacCommon):
|
|
|
1038
987
|
"""Get catalog available days list
|
|
1039
988
|
|
|
1040
989
|
:returns: Days list
|
|
1041
|
-
:rtype: list
|
|
1042
990
|
"""
|
|
1043
991
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1044
992
|
|
|
@@ -1052,9 +1000,7 @@ class StacCatalog(StacCommon):
|
|
|
1052
1000
|
"""Updates and returns catalog with given year
|
|
1053
1001
|
|
|
1054
1002
|
:param year: Year number
|
|
1055
|
-
:type year: str
|
|
1056
1003
|
:returns: Updated catalog
|
|
1057
|
-
:rtype: dict
|
|
1058
1004
|
"""
|
|
1059
1005
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1060
1006
|
|
|
@@ -1079,9 +1025,7 @@ class StacCatalog(StacCommon):
|
|
|
1079
1025
|
"""Updates and returns catalog with given month
|
|
1080
1026
|
|
|
1081
1027
|
:param month: Month number
|
|
1082
|
-
:type month: str
|
|
1083
1028
|
:returns: Updated catalog
|
|
1084
|
-
:rtype: dict
|
|
1085
1029
|
"""
|
|
1086
1030
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1087
1031
|
year = extent_date_min.year
|
|
@@ -1110,9 +1054,7 @@ class StacCatalog(StacCommon):
|
|
|
1110
1054
|
"""Updates and returns catalog with given day
|
|
1111
1055
|
|
|
1112
1056
|
:param day: Day number
|
|
1113
|
-
:type day: str
|
|
1114
1057
|
:returns: Updated catalog
|
|
1115
|
-
:rtype: dict
|
|
1116
1058
|
"""
|
|
1117
1059
|
extent_date_min, extent_date_max = self.get_datetime_extent()
|
|
1118
1060
|
year = extent_date_min.year
|
|
@@ -1142,7 +1084,6 @@ class StacCatalog(StacCommon):
|
|
|
1142
1084
|
"""Returns catalog temporal extent as datetime objs
|
|
1143
1085
|
|
|
1144
1086
|
:returns: Start & stop dates
|
|
1145
|
-
:rtype: tuple
|
|
1146
1087
|
"""
|
|
1147
1088
|
extent_date_min = dateutil.parser.parse(DEFAULT_MISSION_START_DATE).replace(
|
|
1148
1089
|
tzinfo=tz.UTC
|
|
@@ -1175,13 +1116,9 @@ class StacCatalog(StacCommon):
|
|
|
1175
1116
|
"""Updates catalog data using given dates
|
|
1176
1117
|
|
|
1177
1118
|
:param datetime_min: Date min of interval
|
|
1178
|
-
:type datetime_min: :class:`datetime`
|
|
1179
1119
|
:param datetime_max: Date max of interval
|
|
1180
|
-
:type datetime_max: :class:`datetime`
|
|
1181
1120
|
:param catalog_model: Catalog model to use, from yml stac_config[catalogs]
|
|
1182
|
-
:type catalog_model: dict
|
|
1183
1121
|
:returns: Updated catalog
|
|
1184
|
-
:rtype: dict
|
|
1185
1122
|
"""
|
|
1186
1123
|
# parse f-strings
|
|
1187
1124
|
format_args = deepcopy(self.stac_config)
|
|
@@ -1215,7 +1152,6 @@ class StacCatalog(StacCommon):
|
|
|
1215
1152
|
"""Get cloud_cover list
|
|
1216
1153
|
|
|
1217
1154
|
:returns: cloud_cover list
|
|
1218
|
-
:rtype: list
|
|
1219
1155
|
"""
|
|
1220
1156
|
return list(range(0, 101, 10))
|
|
1221
1157
|
|
|
@@ -1223,9 +1159,7 @@ class StacCatalog(StacCommon):
|
|
|
1223
1159
|
"""Updates and returns catalog with given max cloud_cover
|
|
1224
1160
|
|
|
1225
1161
|
:param cloud_cover: Cloud_cover number
|
|
1226
|
-
:type cloud_cover: str
|
|
1227
1162
|
:returns: Updated catalog
|
|
1228
|
-
:rtype: dict
|
|
1229
1163
|
"""
|
|
1230
1164
|
cat_model = deepcopy(self.stac_config["catalogs"]["cloud_cover"]["model"])
|
|
1231
1165
|
# parse f-strings
|
|
@@ -1247,9 +1181,7 @@ class StacCatalog(StacCommon):
|
|
|
1247
1181
|
"""Get locations list using stac_conf & locations_config
|
|
1248
1182
|
|
|
1249
1183
|
:param catalog_name: Catalog/location name
|
|
1250
|
-
:type catalog_name: str
|
|
1251
1184
|
:returns: Locations list
|
|
1252
|
-
:rtype: list
|
|
1253
1185
|
"""
|
|
1254
1186
|
|
|
1255
1187
|
if catalog_name not in self.stac_config["catalogs"]:
|
|
@@ -1282,11 +1214,8 @@ class StacCatalog(StacCommon):
|
|
|
1282
1214
|
"""Updates and returns catalog with given location
|
|
1283
1215
|
|
|
1284
1216
|
:param location: Feature attribute value for shp filtering
|
|
1285
|
-
:type location: str
|
|
1286
1217
|
:param catalog_name: Catalog/location name
|
|
1287
|
-
:type catalog_name: str
|
|
1288
1218
|
:returns: Updated catalog
|
|
1289
|
-
:rtype: dict
|
|
1290
1219
|
"""
|
|
1291
1220
|
location_list_cat_key = catalog_name + "_list"
|
|
1292
1221
|
|
|
@@ -1339,7 +1268,6 @@ class StacCatalog(StacCommon):
|
|
|
1339
1268
|
"""Build locations config from stac_conf[locations_catalogs] & eodag_api.locations_config
|
|
1340
1269
|
|
|
1341
1270
|
:returns: Locations configuration dict
|
|
1342
|
-
:rtype: dict
|
|
1343
1271
|
"""
|
|
1344
1272
|
user_config_locations_list = self.eodag_api.locations_config
|
|
1345
1273
|
|
|
@@ -1364,9 +1292,7 @@ class StacCatalog(StacCommon):
|
|
|
1364
1292
|
"""Build nested catalog from catalag list
|
|
1365
1293
|
|
|
1366
1294
|
:param catalogs: (optional) Catalogs list
|
|
1367
|
-
:type catalogs: list
|
|
1368
1295
|
:returns: This catalog obj
|
|
1369
|
-
:rtype: :class:`eodag.stac.StacCatalog`
|
|
1370
1296
|
"""
|
|
1371
1297
|
settings = Settings.from_environment()
|
|
1372
1298
|
|
eodag/rest/types/eodag_search.py
CHANGED
|
@@ -49,10 +49,7 @@ from eodag.rest.utils.cql_evaluate import EodagEvaluator
|
|
|
49
49
|
from eodag.utils import DEFAULT_ITEMS_PER_PAGE
|
|
50
50
|
|
|
51
51
|
if TYPE_CHECKING:
|
|
52
|
-
|
|
53
|
-
from typing import Self
|
|
54
|
-
except ImportError:
|
|
55
|
-
from _typeshed import Self
|
|
52
|
+
from typing_extensions import Self
|
|
56
53
|
|
|
57
54
|
Geometry = Union[
|
|
58
55
|
Dict[str, Any],
|
|
@@ -113,7 +110,7 @@ class EODAGSearch(BaseModel):
|
|
|
113
110
|
illuminationAzimuthAngle: Optional[float] = Field(None, alias="view:sun_azimuth")
|
|
114
111
|
page: Optional[int] = Field(1)
|
|
115
112
|
items_per_page: int = Field(DEFAULT_ITEMS_PER_PAGE, alias="limit")
|
|
116
|
-
|
|
113
|
+
sort_by: Optional[List[Tuple[str, str]]] = Field(None, alias="sortby")
|
|
117
114
|
raise_errors: bool = False
|
|
118
115
|
|
|
119
116
|
_to_eodag_map: Dict[str, str]
|
|
@@ -314,14 +311,14 @@ class EODAGSearch(BaseModel):
|
|
|
314
311
|
return ",".join(v)
|
|
315
312
|
return v
|
|
316
313
|
|
|
317
|
-
@field_validator("
|
|
314
|
+
@field_validator("sort_by", mode="before")
|
|
318
315
|
@classmethod
|
|
319
316
|
def parse_sortby(
|
|
320
317
|
cls,
|
|
321
318
|
sortby_post_params: List[Dict[str, str]],
|
|
322
319
|
) -> List[Tuple[str, str]]:
|
|
323
320
|
"""
|
|
324
|
-
Convert STAC POST sortby to EODAG
|
|
321
|
+
Convert STAC POST sortby to EODAG sort_by
|
|
325
322
|
"""
|
|
326
323
|
special_fields = {
|
|
327
324
|
"start": "startTimeFromAscendingNode",
|
eodag/rest/types/queryables.py
CHANGED
|
@@ -51,14 +51,16 @@ class QueryablesGetParams(BaseModel):
|
|
|
51
51
|
dumped: Dict[str, Any] = handler(self)
|
|
52
52
|
return {EODAGSearch.to_eodag(k): v for k, v in dumped.items()}
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
# use [prop-decorator] mypy error code when mypy==1.12 is released
|
|
55
|
+
@computed_field # type: ignore[misc]
|
|
55
56
|
@property
|
|
56
57
|
def start_datetime(self) -> Optional[str]:
|
|
57
58
|
"""Extract start_datetime property from datetime"""
|
|
58
59
|
start = str_to_interval(self.datetime)[0]
|
|
59
60
|
return start.strftime("%Y-%m-%dT%H:%M:%SZ") if start else None
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
# use [prop-decorator] mypy error code when mypy==1.12 is released
|
|
63
|
+
@computed_field # type: ignore[misc]
|
|
62
64
|
@property
|
|
63
65
|
def end_datetime(self) -> Optional[str]:
|
|
64
66
|
"""Extract end_datetime property from datetime"""
|
|
@@ -70,11 +72,8 @@ class StacQueryableProperty(BaseModel):
|
|
|
70
72
|
"""A class representing a queryable property.
|
|
71
73
|
|
|
72
74
|
:param description: The description of the queryables property
|
|
73
|
-
:type description: str
|
|
74
75
|
:param ref: (optional) A reference link to the schema of the property.
|
|
75
|
-
:type ref: str
|
|
76
76
|
:param type: (optional) possible types of the property
|
|
77
|
-
:type type: list[str]
|
|
78
77
|
"""
|
|
79
78
|
|
|
80
79
|
description: str
|
|
@@ -114,19 +113,12 @@ class StacQueryables(BaseModel):
|
|
|
114
113
|
"""A class representing queryable properties for the STAC API.
|
|
115
114
|
|
|
116
115
|
:param json_schema: The URL of the JSON schema.
|
|
117
|
-
:type json_schema: str
|
|
118
116
|
:param q_id: (optional) The identifier of the queryables.
|
|
119
|
-
:type q_id: str
|
|
120
117
|
:param q_type: The type of the object.
|
|
121
|
-
:type q_type: str
|
|
122
118
|
:param title: The title of the queryables.
|
|
123
|
-
:type title: str
|
|
124
119
|
:param description: The description of the queryables
|
|
125
|
-
:type description: str
|
|
126
120
|
:param properties: A dictionary of queryable properties.
|
|
127
|
-
:type properties: dict
|
|
128
121
|
:param additional_properties: Whether additional properties are allowed.
|
|
129
|
-
:type additional_properties: bool
|
|
130
122
|
"""
|
|
131
123
|
|
|
132
124
|
json_schema: str = Field(
|
eodag/rest/types/stac_search.py
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
"""Model describing a STAC search POST request"""
|
|
19
|
+
|
|
19
20
|
from __future__ import annotations
|
|
20
21
|
|
|
21
22
|
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union
|
|
@@ -48,10 +49,7 @@ from eodag.rest.utils.rfc3339 import rfc3339_str_to_datetime, str_to_interval
|
|
|
48
49
|
from eodag.utils.exceptions import ValidationError
|
|
49
50
|
|
|
50
51
|
if TYPE_CHECKING:
|
|
51
|
-
|
|
52
|
-
from typing import Self
|
|
53
|
-
except ImportError:
|
|
54
|
-
from _typeshed import Self
|
|
52
|
+
from typing_extensions import Self
|
|
55
53
|
|
|
56
54
|
NumType = Union[float, int]
|
|
57
55
|
|
|
@@ -74,15 +72,13 @@ Geometry = Union[
|
|
|
74
72
|
Direction = Annotated[Literal["asc", "desc"], StringConstraints(min_length=1)]
|
|
75
73
|
|
|
76
74
|
|
|
77
|
-
class
|
|
75
|
+
class SortBy(BaseModel):
|
|
78
76
|
"""
|
|
79
77
|
A class representing a parameter with which we want to sort results and its sorting order in a
|
|
80
78
|
POST search
|
|
81
79
|
|
|
82
80
|
:param field: The name of the parameter with which we want to sort results
|
|
83
|
-
:type field: str
|
|
84
81
|
:param direction: The sorting order of the parameter
|
|
85
|
-
:type direction: str
|
|
86
82
|
"""
|
|
87
83
|
|
|
88
84
|
__pydantic_config__ = ConfigDict(extra="forbid")
|
|
@@ -120,7 +116,7 @@ class SearchPostRequest(BaseModel):
|
|
|
120
116
|
description="The language used for filtering.",
|
|
121
117
|
validate_default=True,
|
|
122
118
|
)
|
|
123
|
-
sortby: Optional[List[
|
|
119
|
+
sortby: Optional[List[SortBy]] = None
|
|
124
120
|
crunch: Optional[str] = None
|
|
125
121
|
|
|
126
122
|
@field_serializer("intersects")
|
|
@@ -262,16 +258,16 @@ class SearchPostRequest(BaseModel):
|
|
|
262
258
|
|
|
263
259
|
def sortby2list(
|
|
264
260
|
v: Optional[str],
|
|
265
|
-
) -> Optional[List[
|
|
261
|
+
) -> Optional[List[SortBy]]:
|
|
266
262
|
"""
|
|
267
263
|
Convert sortby filter parameter GET syntax to POST syntax
|
|
268
264
|
"""
|
|
269
265
|
if not v:
|
|
270
266
|
return None
|
|
271
|
-
sortby: List[
|
|
267
|
+
sortby: List[SortBy] = []
|
|
272
268
|
for sortby_param in v.split(","):
|
|
273
269
|
sortby_param = sortby_param.strip()
|
|
274
270
|
direction: Direction = "desc" if sortby_param.startswith("-") else "asc"
|
|
275
271
|
field = sortby_param.lstrip("+-")
|
|
276
|
-
sortby.append(
|
|
272
|
+
sortby.append(SortBy(field=field, direction=direction))
|
|
277
273
|
return sortby
|
eodag/rest/utils/rfc3339.py
CHANGED
eodag/types/__init__.py
CHANGED
|
@@ -200,7 +200,7 @@ def python_field_definition_to_json(
|
|
|
200
200
|
"%s must be an instance of Annotated" % python_field_definition
|
|
201
201
|
)
|
|
202
202
|
|
|
203
|
-
json_field_definition = dict()
|
|
203
|
+
json_field_definition: Dict[str, Any] = dict()
|
|
204
204
|
|
|
205
205
|
python_field_args = get_args(python_field_definition)
|
|
206
206
|
|
|
@@ -210,6 +210,10 @@ def python_field_definition_to_json(
|
|
|
210
210
|
type_data = python_type_to_json(type(enum_args[0]))
|
|
211
211
|
if isinstance(type_data, str):
|
|
212
212
|
json_field_definition["type"] = type_data
|
|
213
|
+
elif type_data is None:
|
|
214
|
+
json_field_definition["type"] = json_field_definition[
|
|
215
|
+
"min"
|
|
216
|
+
] = json_field_definition["max"] = None
|
|
213
217
|
else:
|
|
214
218
|
json_field_definition["type"] = [row["type"] for row in type_data]
|
|
215
219
|
json_field_definition["min"] = [
|
|
@@ -224,6 +228,10 @@ def python_field_definition_to_json(
|
|
|
224
228
|
field_type = python_type_to_json(python_field_args[0])
|
|
225
229
|
if isinstance(field_type, str):
|
|
226
230
|
json_field_definition["type"] = field_type
|
|
231
|
+
elif field_type is None:
|
|
232
|
+
json_field_definition["type"] = json_field_definition[
|
|
233
|
+
"min"
|
|
234
|
+
] = json_field_definition["max"] = None
|
|
227
235
|
else:
|
|
228
236
|
json_field_definition["type"] = [row["type"] for row in field_type]
|
|
229
237
|
json_field_definition["min"] = [
|
|
@@ -300,9 +308,7 @@ class ProviderSortables(TypedDict):
|
|
|
300
308
|
maximum number of used sortable(s) in a search request with the provider
|
|
301
309
|
|
|
302
310
|
:param sortables: The list of sortable parameter(s) of a provider
|
|
303
|
-
:type sortables: list[str]
|
|
304
311
|
:param max_sort_params: (optional) The allowed maximum number of sortable(s) in a search request with the provider
|
|
305
|
-
:type max_sort_params: int
|
|
306
312
|
"""
|
|
307
313
|
|
|
308
314
|
sortables: List[str]
|
eodag/types/download_args.py
CHANGED
|
@@ -17,15 +17,24 @@
|
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
from typing import Dict, TypedDict
|
|
20
|
+
from typing import Dict, Optional, TypedDict
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class DownloadConf(TypedDict, total=False):
|
|
24
|
-
"""Download configuration
|
|
24
|
+
"""Download configuration
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
:cvar output_prefix: where to store downloaded products, as an absolute file path
|
|
27
|
+
(Default: local temporary directory)
|
|
28
|
+
:cvar output_extension: downloaded file extension
|
|
29
|
+
:cvar extract: whether to extract the downloaded products, only applies to archived products
|
|
30
|
+
:cvar dl_url_params: additional parameters to pass over to the download url as an url parameter
|
|
31
|
+
:cvar delete_archive: whether to delete the downloaded archives
|
|
32
|
+
:cvar asset: regex filter to identify assets to download
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
output_dir: str
|
|
36
|
+
output_extension: str
|
|
28
37
|
extract: bool
|
|
29
38
|
dl_url_params: Dict[str, str]
|
|
30
39
|
delete_archive: bool
|
|
31
|
-
asset: str
|
|
40
|
+
asset: Optional[str]
|
eodag/types/search_args.py
CHANGED
|
@@ -51,7 +51,7 @@ class SearchArgs(BaseModel):
|
|
|
51
51
|
locations: Optional[Dict[str, str]] = Field(None)
|
|
52
52
|
page: Optional[int] = Field(DEFAULT_PAGE, gt=0) # type: ignore
|
|
53
53
|
items_per_page: Optional[PositiveInt] = Field(DEFAULT_ITEMS_PER_PAGE) # type: ignore
|
|
54
|
-
|
|
54
|
+
sort_by: Optional[SortByList] = Field(None) # type: ignore
|
|
55
55
|
|
|
56
56
|
@field_validator("start", "end", mode="before")
|
|
57
57
|
@classmethod
|
|
@@ -87,18 +87,17 @@ class SearchArgs(BaseModel):
|
|
|
87
87
|
|
|
88
88
|
raise TypeError(f"Invalid geometry type: {type(v)}")
|
|
89
89
|
|
|
90
|
-
@field_validator("
|
|
90
|
+
@field_validator("sort_by", mode="before")
|
|
91
91
|
@classmethod
|
|
92
92
|
def check_sort_by_arg(
|
|
93
|
-
cls,
|
|
93
|
+
cls,
|
|
94
|
+
sort_by_arg: Optional[SortByList], # type: ignore
|
|
94
95
|
) -> Optional[SortByList]: # type: ignore
|
|
95
|
-
"""Check if the
|
|
96
|
+
"""Check if the sort_by argument is correct
|
|
96
97
|
|
|
97
|
-
:param sort_by_arg: The
|
|
98
|
-
:
|
|
99
|
-
:returns: The sortBy argument with sorting order parsed (whitespace(s) are
|
|
98
|
+
:param sort_by_arg: The sort_by argument
|
|
99
|
+
:returns: The sort_by argument with sorting order parsed (whitespace(s) are
|
|
100
100
|
removed and only the 3 first letters in uppercase are kept)
|
|
101
|
-
:rtype: str
|
|
102
101
|
"""
|
|
103
102
|
if sort_by_arg is None:
|
|
104
103
|
return None
|
eodag/types/whoosh.py
CHANGED
|
@@ -56,9 +56,7 @@ class EODAGQueryParser(QueryParser):
|
|
|
56
56
|
EODAG QueryParser initialization
|
|
57
57
|
|
|
58
58
|
:param filters: list of fieldnames to filter on
|
|
59
|
-
:type filters: List[str]
|
|
60
59
|
:param schema: Whoosh Schema
|
|
61
|
-
:type schma: :class:whoosh.fields.Schema
|
|
62
60
|
"""
|
|
63
61
|
super().__init__(
|
|
64
62
|
None,
|