eodag 4.0.0a4__py3-none-any.whl → 4.0.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 (42) hide show
  1. eodag/api/collection.py +65 -1
  2. eodag/api/core.py +65 -19
  3. eodag/api/product/_assets.py +1 -1
  4. eodag/api/product/_product.py +133 -18
  5. eodag/api/product/drivers/__init__.py +3 -1
  6. eodag/api/product/drivers/base.py +3 -1
  7. eodag/api/product/drivers/generic.py +9 -5
  8. eodag/api/product/drivers/sentinel1.py +14 -9
  9. eodag/api/product/drivers/sentinel2.py +14 -7
  10. eodag/api/product/metadata_mapping.py +5 -2
  11. eodag/api/provider.py +1 -0
  12. eodag/api/search_result.py +4 -1
  13. eodag/cli.py +17 -8
  14. eodag/config.py +22 -4
  15. eodag/plugins/apis/ecmwf.py +3 -24
  16. eodag/plugins/apis/usgs.py +3 -24
  17. eodag/plugins/download/aws.py +85 -44
  18. eodag/plugins/download/base.py +117 -41
  19. eodag/plugins/download/http.py +88 -65
  20. eodag/plugins/search/base.py +8 -3
  21. eodag/plugins/search/build_search_result.py +108 -120
  22. eodag/plugins/search/cop_marine.py +3 -1
  23. eodag/plugins/search/qssearch.py +7 -6
  24. eodag/resources/collections.yml +255 -0
  25. eodag/resources/ext_collections.json +1 -1
  26. eodag/resources/ext_product_types.json +1 -1
  27. eodag/resources/providers.yml +62 -25
  28. eodag/resources/user_conf_template.yml +6 -0
  29. eodag/types/__init__.py +22 -16
  30. eodag/types/download_args.py +3 -1
  31. eodag/types/queryables.py +125 -55
  32. eodag/types/stac_extensions.py +408 -0
  33. eodag/types/stac_metadata.py +312 -0
  34. eodag/utils/__init__.py +42 -4
  35. eodag/utils/dates.py +202 -2
  36. eodag/utils/s3.py +4 -4
  37. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/METADATA +7 -13
  38. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/RECORD +42 -40
  39. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/WHEEL +1 -1
  40. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/entry_points.txt +1 -1
  41. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/licenses/LICENSE +0 -0
  42. {eodag-4.0.0a4.dist-info → eodag-4.0.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,408 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025, CS GROUP - France, 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
+ """STAC extensions."""
19
+
20
+ from typing import Annotated, Any, Optional, Union
21
+
22
+ from annotated_types import Ge, Le
23
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
24
+
25
+ from eodag.utils import ONLINE_STATUS
26
+
27
+ Percentage = Annotated[float, Ge(0), Le(100)]
28
+
29
+
30
+ class Centroid(BaseModel):
31
+ """Centroid object for projection extension.
32
+
33
+ https://github.com/stac-extensions/projection#centroid-object
34
+ """
35
+
36
+ lat: Optional[float] = Field(None)
37
+ lon: Optional[float] = Field(None)
38
+
39
+
40
+ class CubeDimension(BaseModel):
41
+ """Cube dimension object for datacube extension.
42
+
43
+ https://github.com/stac-extensions/datacube#dimension-object
44
+ """
45
+
46
+ type: Optional[str] = Field(None)
47
+ axis: Optional[str] = Field(None)
48
+ description: Optional[str] = Field(None)
49
+ extent: Optional[list[float]] = Field(None)
50
+ values: Optional[list[float]] = Field(None)
51
+ step: Optional[float] = Field(None)
52
+ unit: Optional[str] = Field(None)
53
+ reference_system: Optional[Union[str, int, dict[str, Any]]] = Field(None)
54
+
55
+
56
+ class CubeVariable(BaseModel):
57
+ """Cube variable object for datacube extension.
58
+
59
+ https://github.com/stac-extensions/datacube#variable-object
60
+ """
61
+
62
+ dimensions: Optional[list[str]] = Field(None)
63
+ type: Optional[str] = Field(None)
64
+ description: Optional[str] = Field(None)
65
+ extent: Optional[list[Union[float, str, None]]] = Field(None)
66
+ values: Optional[list[Union[float, str]]] = Field(None)
67
+ unit: Optional[str] = Field(None)
68
+ nodata: Optional[Union[float, str]] = Field(None)
69
+ data_type: Optional[str] = Field(None)
70
+
71
+
72
+ class BaseStacExtension(BaseModel):
73
+ """Abstract base class for defining STAC extensions."""
74
+
75
+ model_config = ConfigDict(arbitrary_types_allowed=True)
76
+
77
+ FIELDS: Optional[type[BaseModel]] = None
78
+ schema_href: Optional[str] = None
79
+ field_name_prefix: Optional[str] = None
80
+
81
+ @model_validator(mode="after")
82
+ def setup_field_aliases(self) -> "BaseStacExtension":
83
+ """Add serialization validation_alias to extension properties
84
+ and extension metadata to the field.
85
+ """
86
+ if self.field_name_prefix is None:
87
+ return self
88
+
89
+ fields: dict[str, Any] = getattr(self.FIELDS, "model_fields", {})
90
+ for k, v in fields.items():
91
+ v.alias = v.serialization_alias = v.validation_alias = k.replace(
92
+ f"{self.field_name_prefix}_", f"{self.field_name_prefix}:"
93
+ )
94
+ v.metadata.insert(0, {"extension": self.__class__.__name__})
95
+ return self
96
+
97
+
98
+ class SarFields(BaseModel):
99
+ """
100
+ https://github.com/stac-extensions/sar
101
+ """
102
+
103
+ sar_instrument_mode: Optional[str] = Field(None)
104
+ sar_frequency_band: Optional[str] = Field(None)
105
+ sar_center_frequency: Optional[float] = Field(None)
106
+ sar_polarizations: Optional[list[str]] = Field(None)
107
+ sar_resolution_range: Optional[float] = Field(None)
108
+ sar_resolution_azimuth: Optional[float] = Field(None)
109
+ sar_pixel_spacing_range: Optional[float] = Field(None)
110
+ sar_pixel_spacing_azimuth: Optional[float] = Field(None)
111
+ sar_looks_range: Optional[int] = Field(None)
112
+ sar_looks_azimuth: Optional[int] = Field(None)
113
+ sar_looks_equivalent_number: Optional[float] = Field(None)
114
+ sar_observation_direction: Optional[str] = Field(None)
115
+ sar_relative_burst: Optional[int] = Field(None)
116
+ sar_beam_ids: Optional[list[str]] = Field(None)
117
+
118
+
119
+ class SarExtension(BaseStacExtension):
120
+ """STAC SAR extension."""
121
+
122
+ FIELDS: type[BaseModel] = SarFields
123
+
124
+ schema_href: str = "https://stac-extensions.github.io/sar/v1.3.0/schema.json"
125
+ field_name_prefix: Optional[str] = "sar"
126
+
127
+
128
+ class SatelliteFields(BaseModel):
129
+ """
130
+ https://github.com/stac-extensions/sat
131
+ """
132
+
133
+ sat_platform_international_designator: Optional[str] = Field(None)
134
+ sat_orbit_cycle: Optional[int] = Field(None)
135
+ sat_orbit_state: Optional[str] = Field(None)
136
+ sat_absolute_orbit: Optional[int] = Field(None)
137
+ sat_relative_orbit: Optional[int] = Field(None)
138
+ sat_anx_datetime: Optional[str] = Field(None)
139
+
140
+
141
+ class SatelliteExtension(BaseStacExtension):
142
+ """STAC Satellite extension."""
143
+
144
+ FIELDS: type[BaseModel] = SatelliteFields
145
+
146
+ schema_href: str = "https://stac-extensions.github.io/sat/v1.1.0/schema.json"
147
+ field_name_prefix: Optional[str] = "sat"
148
+
149
+
150
+ class TimestampFields(BaseModel):
151
+ """
152
+ https://github.com/stac-extensions/timestamps
153
+ """
154
+
155
+ published: Optional[str] = Field(None)
156
+ unpublished: Optional[str] = Field(None)
157
+ expires: Optional[str] = Field(None)
158
+
159
+
160
+ class TimestampExtension(BaseStacExtension):
161
+ """STAC timestamp extension"""
162
+
163
+ FIELDS: type[BaseModel] = TimestampFields
164
+
165
+ schema_href: str = "https://stac-extensions.github.io/timestamps/v1.1.0/schema.json"
166
+
167
+
168
+ class ProcessingFields(BaseModel):
169
+ """
170
+ https://github.com/stac-extensions/processing
171
+ """
172
+
173
+ processing_expression: Optional[dict[str, Any]] = Field(None)
174
+ processing_lineage: Optional[str] = Field(None)
175
+ processing_level: Optional[str] = Field(None)
176
+ processing_facility: Optional[str] = Field(None)
177
+ processing_software: Optional[dict[str, str]] = Field(None)
178
+
179
+
180
+ class ProcessingExtension(BaseStacExtension):
181
+ """STAC processing extension."""
182
+
183
+ FIELDS: type[BaseModel] = ProcessingFields
184
+
185
+ schema_href: str = "https://stac-extensions.github.io/processing/v1.2.0/schema.json"
186
+ field_name_prefix: Optional[str] = "processing"
187
+
188
+
189
+ class ViewGeometryFields(BaseModel):
190
+ """
191
+ https://github.com/stac-extensions/view
192
+ """
193
+
194
+ view_off_nadir: Optional[float] = Field(None)
195
+ view_incidence_angle: Optional[float] = Field(None)
196
+ view_azimuth: Optional[float] = Field(None)
197
+ view_sun_azimuth: Optional[float] = Field(None)
198
+ view_sun_elevation: Optional[float] = Field(None)
199
+
200
+
201
+ class ViewGeometryExtension(BaseStacExtension):
202
+ """STAC ViewGeometry extension."""
203
+
204
+ FIELDS: type[BaseModel] = ViewGeometryFields
205
+
206
+ schema_href: str = "https://stac-extensions.github.io/view/v1.1.0/schema.json"
207
+ field_name_prefix: Optional[str] = "view"
208
+
209
+
210
+ class ElectroOpticalFields(BaseModel):
211
+ """
212
+ https://github.com/stac-extensions/eo
213
+ """
214
+
215
+ eo_cloud_cover: Optional[Percentage] = Field(None)
216
+ eo_snow_cover: Optional[Percentage] = Field(None)
217
+ eo_bands: Optional[list[dict[str, Union[str, int]]]] = Field(None)
218
+
219
+
220
+ class ElectroOpticalExtension(BaseStacExtension):
221
+ """STAC ElectroOptical extension."""
222
+
223
+ FIELDS: type[BaseModel] = ElectroOpticalFields
224
+
225
+ schema_href: str = "https://stac-extensions.github.io/eo/v2.0.0/schema.json"
226
+ field_name_prefix: Optional[str] = "eo"
227
+
228
+
229
+ class ScientificCitationFields(BaseModel):
230
+ """
231
+ https://github.com/stac-extensions/scientific
232
+ """
233
+
234
+ sci_doi: Optional[str] = Field(None)
235
+ sci_citation: Optional[str] = Field(None)
236
+ sci_publications: Optional[list[dict[str, str]]] = Field(None)
237
+
238
+
239
+ class ScientificCitationExtension(BaseStacExtension):
240
+ """STAC scientific extension."""
241
+
242
+ FIELDS: type[BaseModel] = ScientificCitationFields
243
+
244
+ schema_href: str = "https://stac-extensions.github.io/scientific/v1.0.0/schema.json"
245
+ field_name_prefix: Optional[str] = "sci"
246
+
247
+
248
+ class ProductFields(BaseModel):
249
+ """
250
+ https://github.com/stac-extensions/product
251
+ """
252
+
253
+ product_type: Optional[str] = Field(None)
254
+ product_timeliness: Optional[str] = Field(None)
255
+ product_timeliness_category: Optional[str] = Field(None)
256
+ product_acquisition_type: Optional[str] = Field(None)
257
+
258
+
259
+ class ProductExtension(BaseStacExtension):
260
+ """STAC product extension."""
261
+
262
+ FIELDS: type[BaseModel] = ProductFields
263
+
264
+ schema_href: str = "https://stac-extensions.github.io/product/v1.0.0/schema.json"
265
+ field_name_prefix: Optional[str] = "product"
266
+
267
+
268
+ class StorageFields(BaseModel):
269
+ """
270
+ https://github.com/stac-extensions/storage
271
+ """
272
+
273
+ storage_platform: Optional[str] = Field(default=None)
274
+ storage_region: Optional[str] = Field(default=None)
275
+ storage_requester_pays: Optional[bool] = Field(default=None)
276
+ storage_tier: Optional[str] = Field(default=None, validation_alias="storage:tier")
277
+
278
+ @field_validator("storage_tier")
279
+ @classmethod
280
+ def tier_to_stac(cls, v: Optional[str]) -> str:
281
+ """Convert tier from EODAG naming to STAC"""
282
+ return "online" if v == ONLINE_STATUS else "offline"
283
+
284
+
285
+ class StorageExtension(BaseStacExtension):
286
+ """STAC product extension."""
287
+
288
+ FIELDS: type[BaseModel] = StorageFields
289
+
290
+ schema_href: str = "https://stac-extensions.github.io/storage/v2.0.0/schema.json"
291
+ field_name_prefix: Optional[str] = "storage"
292
+
293
+
294
+ class OrderFields(BaseModel):
295
+ """
296
+ https://github.com/stac-extensions/order
297
+ """
298
+
299
+ order_status: Optional[str] = Field(default=None)
300
+ order_id: Optional[str] = Field(default=None, validation_alias="eodag:order_id")
301
+ order_date: Optional[bool] = Field(default=None)
302
+
303
+
304
+ class OrderExtension(BaseStacExtension):
305
+ """STAC product extension."""
306
+
307
+ FIELDS: type[BaseModel] = OrderFields
308
+
309
+ schema_href: str = "https://stac-extensions.github.io/order/v1.1.0/schema.json"
310
+ field_name_prefix: Optional[str] = "order"
311
+
312
+
313
+ class GridFields(BaseModel):
314
+ """
315
+ https://github.com/stac-extensions/grid
316
+ """
317
+
318
+ grid_code: Optional[str] = Field(
319
+ default=None, pattern=r"^[A-Z0-9]+-[-_.A-Za-z0-9]+$"
320
+ )
321
+
322
+
323
+ class GridExtension(BaseStacExtension):
324
+ """STAC grid extension."""
325
+
326
+ FIELDS: type[BaseModel] = GridFields
327
+
328
+ schema_href: str = "https://stac-extensions.github.io/grid/v1.1.0/schema.json"
329
+ field_name_prefix: Optional[str] = "grid"
330
+
331
+
332
+ class MgrsFields(BaseModel):
333
+ """
334
+ https://github.com/stac-extensions/mgrs
335
+ """
336
+
337
+ mgrs_grid_square: Optional[str] = Field(default=None)
338
+ mgrs_latitude_band: Optional[str] = Field(default=None)
339
+ mgrs_utm_zone: Optional[int] = Field(default=None)
340
+
341
+
342
+ class MgrsExtension(BaseStacExtension):
343
+ """STAC mgrs extension."""
344
+
345
+ FIELDS: type[BaseModel] = MgrsFields
346
+
347
+ schema_href: str = "https://stac-extensions.github.io/mgrs/v1.0.0/schema.json"
348
+ field_name_prefix: Optional[str] = "mgrs"
349
+
350
+
351
+ class ProjectionFields(BaseModel):
352
+ """
353
+ https://github.com/stac-extensions/projection
354
+ """
355
+
356
+ proj_code: Optional[str] = Field(default=None)
357
+ proj_wkt2: Optional[str] = Field(default=None)
358
+ proj_projjson: Optional[dict[str, Any]] = Field(default=None)
359
+ proj_geometry: Optional[dict[str, Any]] = Field(default=None)
360
+ proj_bbox: Optional[list[float]] = Field(default=None)
361
+ proj_centroid: Optional[Centroid] = Field(default=None)
362
+ proj_shape: Optional[list[int]] = Field(default=None)
363
+ proj_transform: Optional[list[float]] = Field(default=None)
364
+
365
+
366
+ class ProjectionExtension(BaseStacExtension):
367
+ """STAC projection extension."""
368
+
369
+ FIELDS: type[BaseModel] = ProjectionFields
370
+
371
+ schema_href: str = "https://stac-extensions.github.io/projection/v2.0.0/schema.json"
372
+ field_name_prefix: Optional[str] = "proj"
373
+
374
+
375
+ class DatacubeFields(BaseModel):
376
+ """
377
+ https://github.com/stac-extensions/datacube
378
+ """
379
+
380
+ cube_dimensions: Optional[dict[str, CubeDimension]] = Field(default=None)
381
+ cube_variables: Optional[dict[str, CubeVariable]] = Field(default=None)
382
+
383
+
384
+ class DatacubeExtension(BaseStacExtension):
385
+ """STAC datacube extension."""
386
+
387
+ FIELDS: type[BaseModel] = DatacubeFields
388
+
389
+ schema_href: str = "https://stac-extensions.github.io/datacube/v2.3.0/schema.json"
390
+ field_name_prefix: Optional[str] = "cube"
391
+
392
+
393
+ STAC_EXTENSIONS = [
394
+ SarExtension(),
395
+ SatelliteExtension(),
396
+ TimestampExtension(),
397
+ ProcessingExtension(),
398
+ ViewGeometryExtension(),
399
+ ElectroOpticalExtension(),
400
+ ScientificCitationExtension(),
401
+ ProductExtension(),
402
+ StorageExtension(),
403
+ OrderExtension(),
404
+ GridExtension(),
405
+ MgrsExtension(),
406
+ ProjectionExtension(),
407
+ DatacubeExtension(),
408
+ ]