eodag 3.0.0b3__py3-none-any.whl → 3.1.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.
Files changed (94) hide show
  1. eodag/api/core.py +347 -247
  2. eodag/api/product/_assets.py +44 -15
  3. eodag/api/product/_product.py +58 -47
  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 +129 -93
  10. eodag/api/search_result.py +28 -12
  11. eodag/cli.py +61 -24
  12. eodag/config.py +457 -167
  13. eodag/plugins/apis/base.py +10 -4
  14. eodag/plugins/apis/ecmwf.py +53 -23
  15. eodag/plugins/apis/usgs.py +41 -17
  16. eodag/plugins/authentication/aws_auth.py +30 -18
  17. eodag/plugins/authentication/base.py +14 -3
  18. eodag/plugins/authentication/generic.py +14 -3
  19. eodag/plugins/authentication/header.py +14 -6
  20. eodag/plugins/authentication/keycloak.py +44 -25
  21. eodag/plugins/authentication/oauth.py +18 -4
  22. eodag/plugins/authentication/openid_connect.py +192 -171
  23. eodag/plugins/authentication/qsauth.py +12 -4
  24. eodag/plugins/authentication/sas_auth.py +22 -5
  25. eodag/plugins/authentication/token.py +95 -17
  26. eodag/plugins/authentication/token_exchange.py +19 -19
  27. eodag/plugins/base.py +4 -4
  28. eodag/plugins/crunch/base.py +8 -5
  29. eodag/plugins/crunch/filter_date.py +9 -6
  30. eodag/plugins/crunch/filter_latest_intersect.py +9 -8
  31. eodag/plugins/crunch/filter_latest_tpl_name.py +8 -8
  32. eodag/plugins/crunch/filter_overlap.py +9 -11
  33. eodag/plugins/crunch/filter_property.py +10 -10
  34. eodag/plugins/download/aws.py +181 -105
  35. eodag/plugins/download/base.py +49 -67
  36. eodag/plugins/download/creodias_s3.py +40 -2
  37. eodag/plugins/download/http.py +247 -223
  38. eodag/plugins/download/s3rest.py +29 -28
  39. eodag/plugins/manager.py +176 -41
  40. eodag/plugins/search/__init__.py +6 -5
  41. eodag/plugins/search/base.py +123 -60
  42. eodag/plugins/search/build_search_result.py +1046 -355
  43. eodag/plugins/search/cop_marine.py +132 -39
  44. eodag/plugins/search/creodias_s3.py +19 -68
  45. eodag/plugins/search/csw.py +48 -8
  46. eodag/plugins/search/data_request_search.py +124 -23
  47. eodag/plugins/search/qssearch.py +531 -310
  48. eodag/plugins/search/stac_list_assets.py +85 -0
  49. eodag/plugins/search/static_stac_search.py +23 -24
  50. eodag/resources/ext_product_types.json +1 -1
  51. eodag/resources/product_types.yml +1295 -355
  52. eodag/resources/providers.yml +1819 -3010
  53. eodag/resources/stac.yml +3 -163
  54. eodag/resources/stac_api.yml +2 -2
  55. eodag/resources/user_conf_template.yml +115 -99
  56. eodag/rest/cache.py +2 -2
  57. eodag/rest/config.py +3 -4
  58. eodag/rest/constants.py +0 -1
  59. eodag/rest/core.py +157 -117
  60. eodag/rest/errors.py +181 -0
  61. eodag/rest/server.py +57 -339
  62. eodag/rest/stac.py +133 -581
  63. eodag/rest/types/collections_search.py +3 -3
  64. eodag/rest/types/eodag_search.py +41 -30
  65. eodag/rest/types/queryables.py +42 -32
  66. eodag/rest/types/stac_search.py +15 -16
  67. eodag/rest/utils/__init__.py +14 -21
  68. eodag/rest/utils/cql_evaluate.py +6 -6
  69. eodag/rest/utils/rfc3339.py +2 -2
  70. eodag/types/__init__.py +153 -32
  71. eodag/types/bbox.py +2 -2
  72. eodag/types/download_args.py +4 -4
  73. eodag/types/queryables.py +183 -73
  74. eodag/types/search_args.py +6 -6
  75. eodag/types/whoosh.py +127 -3
  76. eodag/utils/__init__.py +228 -106
  77. eodag/utils/exceptions.py +47 -26
  78. eodag/utils/import_system.py +2 -2
  79. eodag/utils/logging.py +37 -77
  80. eodag/utils/repr.py +65 -6
  81. eodag/utils/requests.py +13 -15
  82. eodag/utils/rest.py +2 -2
  83. eodag/utils/s3.py +231 -0
  84. eodag/utils/stac_reader.py +11 -11
  85. {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/METADATA +81 -81
  86. eodag-3.1.0.dist-info/RECORD +113 -0
  87. {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/WHEEL +1 -1
  88. {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/entry_points.txt +5 -2
  89. eodag/resources/constraints/climate-dt.json +0 -13
  90. eodag/resources/constraints/extremes-dt.json +0 -8
  91. eodag/utils/constraints.py +0 -244
  92. eodag-3.0.0b3.dist-info/RECORD +0 -110
  93. {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/LICENSE +0 -0
  94. {eodag-3.0.0b3.dist-info → eodag-3.1.0.dist-info}/top_level.txt +0 -0
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
  import re
19
19
  from datetime import datetime
20
- from typing import Any, Dict, List, Optional, Tuple, Union, cast
20
+ from typing import Annotated, Any, Optional, Union, cast
21
21
 
22
22
  from annotated_types import MinLen
23
23
  from pydantic import BaseModel, ConfigDict, Field, conint, field_validator
@@ -27,14 +27,14 @@ from shapely.geometry import Polygon, shape
27
27
  from shapely.geometry.base import GEOMETRY_TYPES, BaseGeometry
28
28
 
29
29
  from eodag.types.bbox import BBox
30
- from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE, Annotated
30
+ from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE
31
31
  from eodag.utils.exceptions import ValidationError
32
32
 
33
33
  NumType = Union[float, int]
34
- GeomArgs = Union[List[NumType], Tuple[NumType], Dict[str, NumType], str, BaseGeometry]
34
+ GeomArgs = Union[list[NumType], tuple[NumType], dict[str, NumType], str, BaseGeometry]
35
35
 
36
36
  PositiveInt = conint(gt=0)
37
- SortByList = Annotated[List[Tuple[str, str]], MinLen(1)]
37
+ SortByList = Annotated[list[tuple[str, str]], MinLen(1)]
38
38
 
39
39
 
40
40
  class SearchArgs(BaseModel):
@@ -48,7 +48,7 @@ class SearchArgs(BaseModel):
48
48
  start: Optional[str] = Field(None)
49
49
  end: Optional[str] = Field(None)
50
50
  geom: Optional[BaseGeometry] = Field(None)
51
- locations: Optional[Dict[str, str]] = Field(None)
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
@@ -119,7 +119,7 @@ class SearchArgs(BaseModel):
119
119
  )
120
120
  sort_by_arg[i] = (sort_param, sort_order[:3])
121
121
  # remove duplicates
122
- pruned_sort_by_arg: SortByList = list(set(sort_by_arg)) # type: ignore
122
+ pruned_sort_by_arg: SortByList = list(dict.fromkeys(sort_by_arg)) # type: ignore
123
123
  for i, sort_by_tuple in enumerate(pruned_sort_by_arg):
124
124
  for j, sort_by_tuple_tmp in enumerate(pruned_sort_by_arg):
125
125
  # since duplicated tuples or dictionnaries have been removed, if two sorting parameters are equal,
eodag/types/whoosh.py CHANGED
@@ -15,13 +15,14 @@
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 List
19
-
20
18
  from whoosh.fields import Schema
19
+ from whoosh.index import _DEF_INDEX_NAME, FileIndex
21
20
  from whoosh.matching import NullMatcher
22
21
  from whoosh.qparser import OrGroup, QueryParser, plugins
23
22
  from whoosh.query.positional import Phrase
24
23
  from whoosh.query.qcore import QueryError
24
+ from whoosh.util.text import utf8encode
25
+ from whoosh.writing import SegmentWriter
25
26
 
26
27
 
27
28
  class RobustPhrase(Phrase):
@@ -49,7 +50,7 @@ class EODAGQueryParser(QueryParser):
49
50
 
50
51
  def __init__(
51
52
  self,
52
- filters: List[str],
53
+ filters: list[str],
53
54
  schema: Schema,
54
55
  ):
55
56
  """
@@ -77,3 +78,126 @@ class EODAGQueryParser(QueryParser):
77
78
  phraseclass=RobustPhrase,
78
79
  group=OrGroup,
79
80
  )
81
+
82
+
83
+ class CleanSegmentWriter(SegmentWriter):
84
+ """Override to clean up writer for failed document add when exceptions were absorbed
85
+ cf: https://github.com/whoosh-community/whoosh/pull/543
86
+ """
87
+
88
+ def add_document(self, **fields):
89
+ """Add document"""
90
+ self._check_state()
91
+ perdocwriter = self.perdocwriter
92
+ schema = self.schema
93
+ docnum = self.docnum
94
+ add_post = self.pool.add
95
+
96
+ docboost = self._doc_boost(fields)
97
+ fieldnames = sorted(
98
+ [name for name in fields.keys() if not name.startswith("_")]
99
+ )
100
+ self._check_fields(schema, fieldnames)
101
+
102
+ perdocwriter.start_doc(docnum)
103
+
104
+ try:
105
+ for fieldname in fieldnames:
106
+ value = fields.get(fieldname)
107
+ if value is None:
108
+ continue
109
+ field = schema[fieldname]
110
+
111
+ length = 0
112
+ if field.indexed:
113
+ # TODO: Method for adding progressive field values, ie
114
+ # setting start_pos/start_char?
115
+ fieldboost = self._field_boost(fields, fieldname, docboost)
116
+ # Ask the field to return a list of (text, weight, vbytes)
117
+ # tuples
118
+ items = field.index(value)
119
+ # Only store the length if the field is marked scorable
120
+ scorable = field.scorable
121
+ # Add the terms to the pool
122
+ for tbytes, freq, weight, vbytes in items:
123
+ weight *= fieldboost
124
+ if scorable:
125
+ length += freq
126
+ add_post((fieldname, tbytes, docnum, weight, vbytes))
127
+
128
+ if field.separate_spelling():
129
+ spellfield = field.spelling_fieldname(fieldname)
130
+ for word in field.spellable_words(value):
131
+ word = utf8encode(word)[0]
132
+ add_post((spellfield, word, 0, 1, vbytes))
133
+
134
+ vformat = field.vector
135
+ if vformat:
136
+ analyzer = field.analyzer
137
+ # Call the format's word_values method to get posting values
138
+ vitems = vformat.word_values(value, analyzer, mode="index")
139
+ # Remove unused frequency field from the tuple
140
+ vitems = sorted(
141
+ (text, weight, vbytes) for text, _, weight, vbytes in vitems
142
+ )
143
+ perdocwriter.add_vector_items(fieldname, field, vitems)
144
+
145
+ # Allow a custom value for stored field/column
146
+ customval = fields.get("_stored_%s" % fieldname, value)
147
+
148
+ # Add the stored value and length for this field to the per-
149
+ # document writer
150
+ sv = customval if field.stored else None
151
+ perdocwriter.add_field(fieldname, field, sv, length)
152
+
153
+ column = field.column_type
154
+ if column and customval is not None:
155
+ cv = field.to_column_value(customval)
156
+ perdocwriter.add_column_value(fieldname, column, cv)
157
+ except Exception as ex:
158
+ # cancel doc
159
+ perdocwriter._doccount -= 1
160
+ perdocwriter._indoc = False
161
+ raise ex
162
+
163
+ perdocwriter.finish_doc()
164
+ self._added = True
165
+ self.docnum += 1
166
+
167
+
168
+ class CleanFileIndex(FileIndex):
169
+ """Override to call CleanSegmentWriter"""
170
+
171
+ def writer(self, procs=1, **kwargs):
172
+ """file index writer"""
173
+ if procs > 1:
174
+ from whoosh.multiproc import MpWriter
175
+
176
+ return MpWriter(self, procs=procs, **kwargs)
177
+ else:
178
+ return CleanSegmentWriter(self, **kwargs)
179
+
180
+
181
+ def create_in(dirname, schema, indexname=None):
182
+ """
183
+ Override to call the CleanFileIndex.
184
+
185
+ Convenience function to create an index in a directory. Takes care of
186
+ creating a FileStorage object for you.
187
+
188
+ :param dirname: the path string of the directory in which to create the
189
+ index.
190
+ :param schema: a :class:`whoosh.fields.Schema` object describing the
191
+ index's fields.
192
+ :param indexname: the name of the index to create; you only need to specify
193
+ this if you are creating multiple indexes within the same storage
194
+ object.
195
+ :returns: :class:`Index`
196
+ """
197
+
198
+ from whoosh.filedb.filestore import FileStorage
199
+
200
+ if not indexname:
201
+ indexname = _DEF_INDEX_NAME
202
+ storage = FileStorage(dirname)
203
+ return CleanFileIndex.create(storage, schema, indexname)