eodag 3.0.1__py3-none-any.whl → 3.1.0b1__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 (44) hide show
  1. eodag/api/core.py +116 -86
  2. eodag/api/product/_assets.py +6 -6
  3. eodag/api/product/_product.py +18 -18
  4. eodag/api/product/metadata_mapping.py +39 -11
  5. eodag/cli.py +22 -1
  6. eodag/config.py +14 -14
  7. eodag/plugins/apis/ecmwf.py +37 -14
  8. eodag/plugins/apis/usgs.py +5 -5
  9. eodag/plugins/authentication/openid_connect.py +2 -2
  10. eodag/plugins/authentication/token.py +37 -6
  11. eodag/plugins/crunch/filter_property.py +2 -3
  12. eodag/plugins/download/aws.py +11 -12
  13. eodag/plugins/download/base.py +30 -39
  14. eodag/plugins/download/creodias_s3.py +29 -0
  15. eodag/plugins/download/http.py +144 -152
  16. eodag/plugins/download/s3rest.py +5 -7
  17. eodag/plugins/search/base.py +73 -25
  18. eodag/plugins/search/build_search_result.py +1047 -310
  19. eodag/plugins/search/creodias_s3.py +25 -19
  20. eodag/plugins/search/data_request_search.py +1 -1
  21. eodag/plugins/search/qssearch.py +51 -139
  22. eodag/resources/ext_product_types.json +1 -1
  23. eodag/resources/product_types.yml +391 -32
  24. eodag/resources/providers.yml +678 -1744
  25. eodag/rest/core.py +92 -62
  26. eodag/rest/server.py +31 -4
  27. eodag/rest/types/eodag_search.py +6 -0
  28. eodag/rest/types/queryables.py +5 -6
  29. eodag/rest/utils/__init__.py +3 -0
  30. eodag/types/__init__.py +56 -15
  31. eodag/types/download_args.py +2 -2
  32. eodag/types/queryables.py +180 -72
  33. eodag/types/whoosh.py +126 -0
  34. eodag/utils/__init__.py +71 -10
  35. eodag/utils/exceptions.py +27 -20
  36. eodag/utils/repr.py +65 -6
  37. eodag/utils/requests.py +11 -11
  38. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/METADATA +76 -76
  39. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/RECORD +43 -44
  40. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/WHEEL +1 -1
  41. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/entry_points.txt +3 -2
  42. eodag/utils/constraints.py +0 -244
  43. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/LICENSE +0 -0
  44. {eodag-3.0.1.dist-info → eodag-3.1.0b1.dist-info}/top_level.txt +0 -0
@@ -1,244 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Copyright 2024, CS Systemes d'Information, https://www.csgroup.eu/
3
- #
4
- # This file is part of EODAG project
5
- # https://www.github.com/CS-SI/EODAG
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- import copy
19
- import logging
20
- from typing import Any, Dict, List, Set, Union
21
-
22
- from requests.auth import AuthBase
23
-
24
- from eodag.api.product.metadata_mapping import get_provider_queryable_key
25
- from eodag.plugins.apis.base import Api
26
- from eodag.plugins.search.base import Search
27
- from eodag.utils import deepcopy
28
- from eodag.utils.exceptions import RequestError, ValidationError
29
- from eodag.utils.requests import fetch_json
30
-
31
- logger = logging.getLogger("eodag.constraints")
32
-
33
-
34
- def get_constraint_queryables_with_additional_params(
35
- constraints: List[Any],
36
- input_params: Dict[str, Any],
37
- plugin: Union[Search, Api],
38
- product_type: str,
39
- ) -> Dict[str, Dict[str, Set[Any]]]:
40
- """
41
- gets the queryables from the constraints using the given parameters
42
- For all queryables only values matching the given parameters based on the constraints will be returned
43
- :param constraints: list of constraints fetched from the provider
44
- :param input_params: conditions the constraints should fulfil
45
- :param plugin: search or api plugin that is used
46
- :param product_type: product type for which the data should be fetched
47
- :returns: dict containing queryable data
48
- """
49
- defaults = copy.deepcopy(input_params)
50
- constraint_matches = {}
51
- params = {k: v for k, v in defaults.items() if v}
52
- for p in params.keys():
53
- defaults.pop(p, None)
54
- params_available = {k: False for k in params.keys()}
55
- # check which constraints match the given parameters
56
- eodag_provider_key_mapping = {}
57
- values_available: Dict[str, Set[Any]] = {k: set() for k in params.keys()}
58
- metadata_mapping = plugin.config.products.get(product_type, {}).get(
59
- "metadata_mapping", {}
60
- )
61
- if not metadata_mapping:
62
- metadata_mapping = plugin.config.metadata_mapping
63
- for i, constraint in enumerate(constraints):
64
- params_matched = {k: False for k in params.keys()}
65
- for param, value in params.items():
66
- provider_key = get_provider_queryable_key(
67
- param, constraint, metadata_mapping
68
- )
69
- if provider_key and provider_key in constraint:
70
- eodag_provider_key_mapping[provider_key] = param
71
- params_available[param] = True
72
- if (
73
- isinstance(value, list)
74
- and all([v in constraint[provider_key] for v in value])
75
- or not isinstance(value, list)
76
- and value in constraint[provider_key]
77
- ):
78
- params_matched[param] = True
79
- elif isinstance(value, str):
80
- # for Copernicus providers, values can be multiple and represented with a string
81
- # separated by slashes (example: time = "0000/0100/0200")
82
- values = value.split("/")
83
- params_matched[param] = all(
84
- [v in constraint[provider_key] for v in values]
85
- )
86
- values_available[param].update(constraint[provider_key])
87
- # match with default values of params
88
- for default_param, default_value in defaults.items():
89
- provider_key = get_provider_queryable_key(
90
- default_param,
91
- constraint,
92
- metadata_mapping,
93
- )
94
- if provider_key and provider_key in constraint:
95
- eodag_provider_key_mapping[provider_key] = default_param
96
- params_matched[default_param] = False
97
- if default_value in constraint[provider_key]:
98
- params_matched[default_param] = True
99
- constraint_matches[i] = params_matched
100
-
101
- # check if all parameters are available in the constraints
102
- not_available_params = set()
103
- for param, available in params_available.items():
104
- if not available:
105
- not_available_params.add(param)
106
- if not_available_params:
107
- return {"not_available": {"enum": not_available_params}}
108
-
109
- # clear constraint_matches if no combination matches
110
- matching_combinations = [
111
- False not in v.values() for v in constraint_matches.values()
112
- ]
113
- if not any(matching_combinations):
114
- constraint_matches = {}
115
-
116
- # add values of constraints matching params
117
- queryables: Dict[str, Dict[str, Set[Any]]] = {}
118
- for num, matches in constraint_matches.items():
119
- for key in constraints[num]:
120
- other_keys_matching = [v for k, v in matches.items() if k != key]
121
- key_matches_a_constraint = any(
122
- v.get(key, False) for v in constraint_matches.values()
123
- )
124
- if False in other_keys_matching or (
125
- not key_matches_a_constraint and key in matches
126
- ):
127
- continue
128
- if key in queryables:
129
- queryables[key]["enum"].update(constraints[num][key])
130
- else:
131
- queryables[key] = {}
132
- queryables[key]["enum"] = set(constraints[num][key])
133
-
134
- other_values = _get_other_possible_values_for_values_with_defaults(
135
- defaults, params, constraints, metadata_mapping
136
- )
137
- for key in queryables:
138
- if key in other_values:
139
- queryables[key]["enum"].update(other_values[key])
140
-
141
- # check if constraints matching params have been found
142
- if len(queryables) == 0:
143
- if len(params) > 1:
144
- raise ValidationError(
145
- f"combination of values {str(params)} is not possible"
146
- )
147
- elif len(params) == 1 and len(defaults) > 0:
148
- raise ValidationError(
149
- f"value {list(params.values())[0]} not available for param {list(params.keys())[0]} "
150
- f"with default values {str(defaults)}"
151
- )
152
-
153
- elif len(params) == 1:
154
- raise ValidationError(
155
- f"value {list(params.values())[0]} not available for param {list(params.keys())[0]}, "
156
- f"possible values: {str(sorted(values_available[list(params.keys())[0]]))}"
157
- )
158
- else:
159
- raise ValidationError(
160
- f"no constraints matching default params {str(defaults)} found"
161
- )
162
-
163
- return queryables
164
-
165
-
166
- def fetch_constraints(
167
- constraints_url: str, plugin: Union[Search, Api]
168
- ) -> List[Dict[Any, Any]]:
169
- """
170
- fetches the constraints from a provider
171
- :param constraints_url: url from which the constraints can be fetched
172
- :param plugin: api or search plugin of the provider
173
- :returns: list of constraints fetched from the provider
174
- """
175
- auth = (
176
- plugin.auth
177
- if hasattr(plugin, "auth") and isinstance(plugin.auth, AuthBase)
178
- else None
179
- )
180
- try:
181
- constraints_data = fetch_json(constraints_url, auth=auth)
182
- except RequestError as err:
183
- logger.error(str(err))
184
- return []
185
-
186
- config = plugin.config.__dict__
187
- if (
188
- "constraints_entry" in config
189
- and config["constraints_entry"]
190
- and config["constraints_entry"] in constraints_data
191
- ):
192
- constraints = constraints_data[config["constraints_entry"]]
193
- elif config.get("stop_without_constraints_entry_key", False):
194
- return []
195
- else:
196
- constraints = constraints_data
197
- return constraints
198
-
199
-
200
- def _get_other_possible_values_for_values_with_defaults(
201
- defaults: Dict[str, Any],
202
- params: Dict[str, Any],
203
- constraints: List[Dict[Any, Any]],
204
- metadata_mapping: Dict[str, Union[str, list]],
205
- ) -> Dict[str, Set[Any]]:
206
- possible_values = {}
207
- for param, default_value in defaults.items():
208
- fixed_params = deepcopy(params)
209
- param_values = set()
210
- for p in defaults:
211
- if p != param:
212
- fixed_params[p] = defaults[p]
213
- for constraint in constraints:
214
- provider_key = get_provider_queryable_key(
215
- param, constraint, metadata_mapping
216
- )
217
- if not provider_key:
218
- provider_key = param
219
- if (
220
- _matches_constraint(constraint, fixed_params, metadata_mapping)
221
- and provider_key in constraint
222
- ):
223
- param_values.update(constraint[provider_key])
224
- possible_values[provider_key] = param_values
225
- return possible_values
226
-
227
-
228
- def _matches_constraint(
229
- constraint: Dict[Any, Any],
230
- params: Dict[str, Any],
231
- metadata_mapping: Dict[str, Union[str, list]],
232
- ) -> bool:
233
- for p in params:
234
- provider_key = get_provider_queryable_key(p, constraint, metadata_mapping)
235
- if provider_key not in constraint:
236
- continue
237
- if isinstance(params[p], list):
238
- for value in params[p]:
239
- if value not in constraint[provider_key]:
240
- return False
241
- else:
242
- if params[p] not in constraint[provider_key]:
243
- return False
244
- return True