eodag 3.1.0b1__py3-none-any.whl → 3.2.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.
- eodag/api/core.py +69 -63
- eodag/api/product/_assets.py +49 -13
- eodag/api/product/_product.py +41 -30
- eodag/api/product/drivers/__init__.py +81 -4
- eodag/api/product/drivers/base.py +65 -4
- eodag/api/product/drivers/generic.py +65 -0
- eodag/api/product/drivers/sentinel1.py +97 -0
- eodag/api/product/drivers/sentinel2.py +95 -0
- eodag/api/product/metadata_mapping.py +85 -79
- eodag/api/search_result.py +13 -23
- eodag/cli.py +4 -4
- eodag/config.py +77 -80
- eodag/plugins/apis/base.py +1 -1
- eodag/plugins/apis/ecmwf.py +12 -15
- eodag/plugins/apis/usgs.py +12 -11
- eodag/plugins/authentication/aws_auth.py +16 -13
- eodag/plugins/authentication/base.py +5 -3
- eodag/plugins/authentication/header.py +3 -3
- eodag/plugins/authentication/keycloak.py +4 -4
- eodag/plugins/authentication/oauth.py +7 -3
- eodag/plugins/authentication/openid_connect.py +20 -14
- eodag/plugins/authentication/sas_auth.py +4 -4
- eodag/plugins/authentication/token.py +7 -7
- eodag/plugins/authentication/token_exchange.py +1 -1
- eodag/plugins/base.py +4 -4
- eodag/plugins/crunch/base.py +4 -4
- eodag/plugins/crunch/filter_date.py +4 -4
- eodag/plugins/crunch/filter_latest_intersect.py +6 -6
- eodag/plugins/crunch/filter_latest_tpl_name.py +7 -7
- eodag/plugins/crunch/filter_overlap.py +4 -4
- eodag/plugins/crunch/filter_property.py +4 -4
- eodag/plugins/download/aws.py +137 -77
- eodag/plugins/download/base.py +8 -17
- eodag/plugins/download/creodias_s3.py +2 -2
- eodag/plugins/download/http.py +30 -32
- eodag/plugins/download/s3rest.py +5 -4
- eodag/plugins/manager.py +10 -20
- eodag/plugins/search/__init__.py +6 -5
- eodag/plugins/search/base.py +38 -42
- eodag/plugins/search/build_search_result.py +286 -336
- eodag/plugins/search/cop_marine.py +22 -12
- eodag/plugins/search/creodias_s3.py +8 -78
- eodag/plugins/search/csw.py +11 -11
- eodag/plugins/search/data_request_search.py +19 -18
- eodag/plugins/search/qssearch.py +84 -151
- eodag/plugins/search/stac_list_assets.py +85 -0
- eodag/plugins/search/static_stac_search.py +4 -4
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +848 -398
- eodag/resources/providers.yml +1038 -1115
- eodag/resources/stac_api.yml +2 -2
- eodag/resources/user_conf_template.yml +10 -9
- eodag/rest/cache.py +2 -2
- eodag/rest/config.py +3 -3
- eodag/rest/core.py +24 -24
- eodag/rest/errors.py +5 -5
- eodag/rest/server.py +3 -11
- eodag/rest/stac.py +41 -38
- eodag/rest/types/collections_search.py +3 -3
- eodag/rest/types/eodag_search.py +23 -23
- eodag/rest/types/queryables.py +40 -28
- eodag/rest/types/stac_search.py +15 -25
- eodag/rest/utils/__init__.py +11 -21
- eodag/rest/utils/cql_evaluate.py +6 -6
- eodag/rest/utils/rfc3339.py +2 -2
- eodag/types/__init__.py +97 -29
- eodag/types/bbox.py +2 -2
- eodag/types/download_args.py +2 -2
- eodag/types/queryables.py +5 -2
- eodag/types/search_args.py +4 -4
- eodag/types/whoosh.py +1 -3
- eodag/utils/__init__.py +82 -41
- eodag/utils/exceptions.py +2 -2
- eodag/utils/import_system.py +2 -2
- eodag/utils/requests.py +2 -2
- eodag/utils/rest.py +2 -2
- eodag/utils/s3.py +231 -0
- eodag/utils/stac_reader.py +10 -10
- {eodag-3.1.0b1.dist-info → eodag-3.2.0.dist-info}/METADATA +12 -10
- eodag-3.2.0.dist-info/RECORD +113 -0
- {eodag-3.1.0b1.dist-info → eodag-3.2.0.dist-info}/WHEEL +1 -1
- {eodag-3.1.0b1.dist-info → eodag-3.2.0.dist-info}/entry_points.txt +1 -0
- eodag-3.1.0b1.dist-info/RECORD +0 -108
- {eodag-3.1.0b1.dist-info → eodag-3.2.0.dist-info/licenses}/LICENSE +0 -0
- {eodag-3.1.0b1.dist-info → eodag-3.2.0.dist-info}/top_level.txt +0 -0
eodag/resources/stac_api.yml
CHANGED
|
@@ -799,7 +799,7 @@ components:
|
|
|
799
799
|
description: |
|
|
800
800
|
Sentinel-2 is a wide-swath, high-resolution, multi-spectral
|
|
801
801
|
imaging mission...
|
|
802
|
-
license:
|
|
802
|
+
license: other
|
|
803
803
|
keywords:
|
|
804
804
|
- copernicus
|
|
805
805
|
- esa
|
|
@@ -1416,7 +1416,7 @@ components:
|
|
|
1416
1416
|
description: |-
|
|
1417
1417
|
License(s) of the data as a SPDX
|
|
1418
1418
|
[License identifier](https://spdx.org/licenses/). Alternatively, use
|
|
1419
|
-
`
|
|
1419
|
+
`other` if the license is not on the SPDX license list or
|
|
1420
1420
|
`various` if multiple licenses apply. In these two cases links to the
|
|
1421
1421
|
license texts SHOULD be added, see the `license` link relation type.
|
|
1422
1422
|
|
|
@@ -157,15 +157,18 @@ geodes:
|
|
|
157
157
|
download:
|
|
158
158
|
extract:
|
|
159
159
|
output_dir:
|
|
160
|
-
|
|
160
|
+
geodes_s3:
|
|
161
161
|
priority: # Lower value means lower priority (Default: 0)
|
|
162
162
|
search: # Search parameters configuration
|
|
163
163
|
auth:
|
|
164
164
|
credentials:
|
|
165
|
-
|
|
165
|
+
aws_access_key_id:
|
|
166
|
+
aws_secret_access_key:
|
|
167
|
+
aws_session_token:
|
|
166
168
|
download:
|
|
169
|
+
extract:
|
|
167
170
|
output_dir:
|
|
168
|
-
|
|
171
|
+
hydroweb_next:
|
|
169
172
|
priority: # Lower value means lower priority (Default: 0)
|
|
170
173
|
search: # Search parameters configuration
|
|
171
174
|
auth:
|
|
@@ -173,16 +176,14 @@ meteoblue:
|
|
|
173
176
|
apikey:
|
|
174
177
|
download:
|
|
175
178
|
output_dir:
|
|
176
|
-
|
|
179
|
+
meteoblue:
|
|
177
180
|
priority: # Lower value means lower priority (Default: 0)
|
|
178
181
|
search: # Search parameters configuration
|
|
179
|
-
download:
|
|
180
|
-
extract:
|
|
181
|
-
output_dir:
|
|
182
182
|
auth:
|
|
183
183
|
credentials:
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
apikey:
|
|
185
|
+
download:
|
|
186
|
+
output_dir:
|
|
186
187
|
peps:
|
|
187
188
|
priority: # Lower value means lower priority (Default: 1)
|
|
188
189
|
search: # Search parameters configuration
|
eodag/rest/cache.py
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
import logging
|
|
19
|
-
from typing import Any, Callable, Coroutine,
|
|
19
|
+
from typing import Any, Callable, Coroutine, TypeVar, cast
|
|
20
20
|
|
|
21
21
|
import orjson
|
|
22
22
|
from cachetools import LRUCache
|
|
@@ -48,7 +48,7 @@ async def cached(
|
|
|
48
48
|
host_cache_key = f"{cache_key}:{host}"
|
|
49
49
|
|
|
50
50
|
try:
|
|
51
|
-
c:
|
|
51
|
+
c: dict[str, Any] = request.app.state.cache
|
|
52
52
|
|
|
53
53
|
if cached := c.get(host_cache_key):
|
|
54
54
|
logger.debug("Cache result hit")
|
eodag/rest/config.py
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
from functools import lru_cache
|
|
21
|
-
from typing import Annotated,
|
|
21
|
+
from typing import Annotated, Union
|
|
22
22
|
|
|
23
23
|
from pydantic import Field
|
|
24
24
|
from pydantic.functional_validators import BeforeValidator
|
|
@@ -28,7 +28,7 @@ from typing_extensions import Doc
|
|
|
28
28
|
from eodag.rest.constants import DEFAULT_MAXSIZE, DEFAULT_TTL
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def str2liststr(raw: Union[str,
|
|
31
|
+
def str2liststr(raw: Union[str, list[str]]) -> list[str]:
|
|
32
32
|
"""Convert str to list[str]"""
|
|
33
33
|
if isinstance(raw, list):
|
|
34
34
|
return raw
|
|
@@ -49,7 +49,7 @@ class Settings(BaseSettings):
|
|
|
49
49
|
stac_api_landing_id: str = "eodag-stac-api"
|
|
50
50
|
|
|
51
51
|
origin_url_blacklist: Annotated[
|
|
52
|
-
Union[str,
|
|
52
|
+
Union[str, list[str]],
|
|
53
53
|
BeforeValidator(str2liststr),
|
|
54
54
|
Doc(
|
|
55
55
|
"Hide from clients items assets' alternative URLs starting with URLs from the list"
|
eodag/rest/core.py
CHANGED
|
@@ -77,7 +77,7 @@ from eodag.utils.exceptions import (
|
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
if TYPE_CHECKING:
|
|
80
|
-
from typing import Any,
|
|
80
|
+
from typing import Any, Optional, Union
|
|
81
81
|
|
|
82
82
|
from fastapi import Request
|
|
83
83
|
from requests.auth import AuthBase
|
|
@@ -116,12 +116,12 @@ def get_home_page_content(base_url: str, ipp: Optional[int] = None) -> str:
|
|
|
116
116
|
reason="Function internally used by get_home_page_content, also deprecated",
|
|
117
117
|
version="2.6.1",
|
|
118
118
|
)
|
|
119
|
-
def format_product_types(product_types:
|
|
119
|
+
def format_product_types(product_types: list[dict[str, Any]]) -> str:
|
|
120
120
|
"""Format product_types
|
|
121
121
|
|
|
122
122
|
:param product_types: A list of EODAG product types as returned by the core api
|
|
123
123
|
"""
|
|
124
|
-
result:
|
|
124
|
+
result: list[str] = []
|
|
125
125
|
for pt in product_types:
|
|
126
126
|
result.append(f'* *__{pt["ID"]}__*: {pt["abstract"]}')
|
|
127
127
|
return "\n".join(sorted(result))
|
|
@@ -130,7 +130,7 @@ def format_product_types(product_types: List[Dict[str, Any]]) -> str:
|
|
|
130
130
|
def search_stac_items(
|
|
131
131
|
request: Request,
|
|
132
132
|
search_request: SearchPostRequest,
|
|
133
|
-
) ->
|
|
133
|
+
) -> dict[str, Any]:
|
|
134
134
|
"""
|
|
135
135
|
Search and retrieve STAC items based on the given search request.
|
|
136
136
|
|
|
@@ -309,8 +309,8 @@ def download_stac_item(
|
|
|
309
309
|
|
|
310
310
|
def _order_and_update(
|
|
311
311
|
product: EOProduct,
|
|
312
|
-
auth: Union[AuthBase,
|
|
313
|
-
query_args:
|
|
312
|
+
auth: Union[AuthBase, dict[str, str], None],
|
|
313
|
+
query_args: dict[str, Any],
|
|
314
314
|
) -> None:
|
|
315
315
|
"""Order product if needed and update given kwargs with order-status-dict"""
|
|
316
316
|
if product.properties.get("storageStatus") != ONLINE_STATUS and hasattr(
|
|
@@ -353,7 +353,7 @@ def _order_and_update(
|
|
|
353
353
|
|
|
354
354
|
|
|
355
355
|
@lru_cache(maxsize=1)
|
|
356
|
-
def get_detailled_collections_list() ->
|
|
356
|
+
def get_detailled_collections_list() -> list[dict[str, Any]]:
|
|
357
357
|
"""Returns detailled collections / product_types list as a list of
|
|
358
358
|
config dicts
|
|
359
359
|
|
|
@@ -370,7 +370,7 @@ async def all_collections(
|
|
|
370
370
|
instrument: Optional[str] = None,
|
|
371
371
|
constellation: Optional[str] = None,
|
|
372
372
|
datetime: Optional[str] = None,
|
|
373
|
-
) ->
|
|
373
|
+
) -> dict[str, Any]:
|
|
374
374
|
"""Build STAC collections
|
|
375
375
|
|
|
376
376
|
:param url: Requested URL
|
|
@@ -380,7 +380,7 @@ async def all_collections(
|
|
|
380
380
|
:returns: Collections dictionary
|
|
381
381
|
"""
|
|
382
382
|
|
|
383
|
-
async def _fetch() ->
|
|
383
|
+
async def _fetch() -> dict[str, Any]:
|
|
384
384
|
stac_collection = StacCollection(
|
|
385
385
|
url=request.state.url,
|
|
386
386
|
stac_config=stac_config,
|
|
@@ -422,7 +422,7 @@ async def all_collections(
|
|
|
422
422
|
|
|
423
423
|
async def get_collection(
|
|
424
424
|
request: Request, collection_id: str, provider: Optional[str] = None
|
|
425
|
-
) ->
|
|
425
|
+
) -> dict[str, Any]:
|
|
426
426
|
"""Build STAC collection by id
|
|
427
427
|
|
|
428
428
|
:param url: Requested URL
|
|
@@ -432,7 +432,7 @@ async def get_collection(
|
|
|
432
432
|
:returns: Collection dictionary
|
|
433
433
|
"""
|
|
434
434
|
|
|
435
|
-
async def _fetch() ->
|
|
435
|
+
async def _fetch() -> dict[str, Any]:
|
|
436
436
|
stac_collection = StacCollection(
|
|
437
437
|
url=request.state.url,
|
|
438
438
|
stac_config=stac_config,
|
|
@@ -455,7 +455,7 @@ async def get_stac_catalogs(
|
|
|
455
455
|
request: Request,
|
|
456
456
|
url: str,
|
|
457
457
|
provider: Optional[str] = None,
|
|
458
|
-
) ->
|
|
458
|
+
) -> dict[str, Any]:
|
|
459
459
|
"""Build STAC catalog
|
|
460
460
|
|
|
461
461
|
:param url: Requested URL
|
|
@@ -464,7 +464,7 @@ async def get_stac_catalogs(
|
|
|
464
464
|
:returns: Catalog dictionary
|
|
465
465
|
"""
|
|
466
466
|
|
|
467
|
-
async def _fetch() ->
|
|
467
|
+
async def _fetch() -> dict[str, Any]:
|
|
468
468
|
return StacCatalog(
|
|
469
469
|
url=url,
|
|
470
470
|
stac_config=stac_config,
|
|
@@ -523,7 +523,7 @@ def time_interval_overlap(eodag_args: EODAGSearch, catalog: StacCatalog) -> bool
|
|
|
523
523
|
|
|
524
524
|
|
|
525
525
|
@lru_cache(maxsize=1)
|
|
526
|
-
def get_stac_conformance() ->
|
|
526
|
+
def get_stac_conformance() -> dict[str, str]:
|
|
527
527
|
"""Build STAC conformance
|
|
528
528
|
|
|
529
529
|
:returns: conformance dictionary
|
|
@@ -540,7 +540,7 @@ def get_stac_api_version() -> str:
|
|
|
540
540
|
|
|
541
541
|
|
|
542
542
|
@lru_cache(maxsize=1)
|
|
543
|
-
def get_stac_extension_oseo(url: str) ->
|
|
543
|
+
def get_stac_extension_oseo(url: str) -> dict[str, str]:
|
|
544
544
|
"""Build STAC OGC / OpenSearch Extension for EO
|
|
545
545
|
|
|
546
546
|
:param url: Requested URL
|
|
@@ -571,14 +571,14 @@ async def get_queryables(
|
|
|
571
571
|
request: Request,
|
|
572
572
|
params: QueryablesGetParams,
|
|
573
573
|
provider: Optional[str] = None,
|
|
574
|
-
) ->
|
|
574
|
+
) -> dict[str, Any]:
|
|
575
575
|
"""Fetch the queryable properties for a collection.
|
|
576
576
|
|
|
577
577
|
:param collection_id: The ID of the collection.
|
|
578
578
|
:returns: A set containing the STAC standardized queryable properties for a collection.
|
|
579
579
|
"""
|
|
580
580
|
|
|
581
|
-
async def _fetch() ->
|
|
581
|
+
async def _fetch() -> dict[str, Any]:
|
|
582
582
|
python_queryables = eodag_api.list_queryables(
|
|
583
583
|
provider=provider,
|
|
584
584
|
fetch_providers=False,
|
|
@@ -589,8 +589,8 @@ async def get_queryables(
|
|
|
589
589
|
by_alias=True
|
|
590
590
|
)
|
|
591
591
|
|
|
592
|
-
properties:
|
|
593
|
-
required:
|
|
592
|
+
properties: dict[str, Any] = python_queryables_json["properties"]
|
|
593
|
+
required: list[str] = python_queryables_json.get("required") or []
|
|
594
594
|
|
|
595
595
|
# productType is either simply removed or replaced by collection later.
|
|
596
596
|
if "productType" in properties:
|
|
@@ -598,7 +598,7 @@ async def get_queryables(
|
|
|
598
598
|
if "productType" in required:
|
|
599
599
|
required.remove("productType")
|
|
600
600
|
|
|
601
|
-
stac_properties:
|
|
601
|
+
stac_properties: dict[str, Any] = {}
|
|
602
602
|
|
|
603
603
|
# get stac default properties to set prefixes
|
|
604
604
|
stac_item_properties = list(stac_config["item"]["properties"].values())
|
|
@@ -687,7 +687,7 @@ def crunch_products(
|
|
|
687
687
|
f'Unknown crunch name. Use one of: {", ".join(crunchers.keys())}'
|
|
688
688
|
)
|
|
689
689
|
|
|
690
|
-
cruncher_config:
|
|
690
|
+
cruncher_config: dict[str, Any] = {}
|
|
691
691
|
for config_param in cruncher.config_params:
|
|
692
692
|
config_param_value = kwargs.get(config_param)
|
|
693
693
|
if not config_param_value:
|
|
@@ -720,13 +720,13 @@ def eodag_api_init() -> None:
|
|
|
720
720
|
ext_col = StacCollection.ext_stac_collections.get(key)
|
|
721
721
|
if not ext_col:
|
|
722
722
|
continue
|
|
723
|
-
platform: Union[str,
|
|
723
|
+
platform: Union[str, list[str]] = ext_col.get("summaries", {}).get(
|
|
724
724
|
"platform"
|
|
725
725
|
)
|
|
726
|
-
constellation: Union[str,
|
|
726
|
+
constellation: Union[str, list[str]] = ext_col.get("summaries", {}).get(
|
|
727
727
|
"constellation"
|
|
728
728
|
)
|
|
729
|
-
processing_level: Union[str,
|
|
729
|
+
processing_level: Union[str, list[str]] = ext_col.get("summaries", {}).get(
|
|
730
730
|
"processing:level"
|
|
731
731
|
)
|
|
732
732
|
# Check if platform or constellation are lists and join them into a string if they are
|
eodag/rest/errors.py
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
import logging
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Union
|
|
20
20
|
|
|
21
21
|
from fastapi import FastAPI, Request
|
|
22
22
|
from fastapi.responses import ORJSONResponse
|
|
@@ -56,16 +56,16 @@ logger = logging.getLogger("eodag.rest.server")
|
|
|
56
56
|
class ResponseSearchError(Exception):
|
|
57
57
|
"""Represent a EODAG search error response"""
|
|
58
58
|
|
|
59
|
-
def __init__(self, errors:
|
|
59
|
+
def __init__(self, errors: list[tuple[str, Exception]]) -> None:
|
|
60
60
|
self._errors = errors
|
|
61
61
|
|
|
62
62
|
@property
|
|
63
|
-
def errors(self) ->
|
|
63
|
+
def errors(self) -> list[dict[str, Union[str, int]]]:
|
|
64
64
|
"""return errors as a list of dict"""
|
|
65
|
-
error_list:
|
|
65
|
+
error_list: list[dict[str, Union[str, int]]] = []
|
|
66
66
|
for name, exception in self._errors:
|
|
67
67
|
|
|
68
|
-
error_dict:
|
|
68
|
+
error_dict: dict[str, Union[str, int]] = {
|
|
69
69
|
"provider": name,
|
|
70
70
|
"error": exception.__class__.__name__,
|
|
71
71
|
}
|
eodag/rest/server.py
CHANGED
|
@@ -23,15 +23,7 @@ import re
|
|
|
23
23
|
from contextlib import asynccontextmanager
|
|
24
24
|
from importlib.metadata import version
|
|
25
25
|
from json import JSONDecodeError
|
|
26
|
-
from typing import
|
|
27
|
-
TYPE_CHECKING,
|
|
28
|
-
Any,
|
|
29
|
-
AsyncGenerator,
|
|
30
|
-
Awaitable,
|
|
31
|
-
Callable,
|
|
32
|
-
Dict,
|
|
33
|
-
Optional,
|
|
34
|
-
)
|
|
26
|
+
from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Optional
|
|
35
27
|
|
|
36
28
|
from fastapi import APIRouter as FastAPIRouter
|
|
37
29
|
from fastapi import FastAPI, HTTPException, Request
|
|
@@ -131,7 +123,7 @@ stac_api_config = load_stac_api_config()
|
|
|
131
123
|
include_in_schema=False,
|
|
132
124
|
status_code=200,
|
|
133
125
|
)
|
|
134
|
-
async def liveness_probe(request: Request) ->
|
|
126
|
+
async def liveness_probe(request: Request) -> dict[str, bool]:
|
|
135
127
|
"Endpoint meant to be used as liveness probe by deployment platforms"
|
|
136
128
|
return {"success": True}
|
|
137
129
|
|
|
@@ -139,7 +131,7 @@ async def liveness_probe(request: Request) -> Dict[str, bool]:
|
|
|
139
131
|
@router.api_route(
|
|
140
132
|
methods=["GET", "HEAD"], path="/api", tags=["Capabilities"], include_in_schema=False
|
|
141
133
|
)
|
|
142
|
-
async def eodag_openapi(request: Request) ->
|
|
134
|
+
async def eodag_openapi(request: Request) -> dict[str, Any]:
|
|
143
135
|
"""Customized openapi"""
|
|
144
136
|
logger.debug("URL: /api")
|
|
145
137
|
if app.openapi_schema:
|
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, 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",
|
|
@@ -95,6 +97,7 @@ IGNORED_ITEM_PROPERTIES = [
|
|
|
95
97
|
"qs",
|
|
96
98
|
"defaultGeometry",
|
|
97
99
|
"_date",
|
|
100
|
+
"productType",
|
|
98
101
|
]
|
|
99
102
|
|
|
100
103
|
|
|
@@ -118,7 +121,7 @@ class StacCommon:
|
|
|
118
121
|
def __init__(
|
|
119
122
|
self,
|
|
120
123
|
url: str,
|
|
121
|
-
stac_config:
|
|
124
|
+
stac_config: dict[str, Any],
|
|
122
125
|
provider: Optional[str],
|
|
123
126
|
eodag_api: EODataAccessGateway,
|
|
124
127
|
root: str = "/",
|
|
@@ -129,9 +132,9 @@ class StacCommon:
|
|
|
129
132
|
self.eodag_api = eodag_api
|
|
130
133
|
self.root = root.rstrip("/") if len(root) > 1 else root
|
|
131
134
|
|
|
132
|
-
self.data:
|
|
135
|
+
self.data: dict[str, Any] = {}
|
|
133
136
|
|
|
134
|
-
def update_data(self, data:
|
|
137
|
+
def update_data(self, data: dict[str, Any]) -> None:
|
|
135
138
|
"""Updates data using given input STAC dict data
|
|
136
139
|
|
|
137
140
|
:param data: Catalog data (parsed STAC dict)
|
|
@@ -165,8 +168,8 @@ class StacCommon:
|
|
|
165
168
|
|
|
166
169
|
@staticmethod
|
|
167
170
|
def get_stac_extension(
|
|
168
|
-
url: str, stac_config:
|
|
169
|
-
) ->
|
|
171
|
+
url: str, stac_config: dict[str, Any], extension: str, **kwargs: Any
|
|
172
|
+
) -> dict[str, str]:
|
|
170
173
|
"""Parse STAC extension from config and return as dict
|
|
171
174
|
|
|
172
175
|
:param url: Requested URL
|
|
@@ -185,7 +188,7 @@ class StacCommon:
|
|
|
185
188
|
}
|
|
186
189
|
return format_dict_items(extension_model, **format_args)
|
|
187
190
|
|
|
188
|
-
def get_provider_dict(self, provider: str) ->
|
|
191
|
+
def get_provider_dict(self, provider: str) -> dict[str, Any]:
|
|
189
192
|
"""Generate STAC provider dict"""
|
|
190
193
|
provider_config = next(
|
|
191
194
|
p
|
|
@@ -214,7 +217,7 @@ class StacItem(StacCommon):
|
|
|
214
217
|
def __init__(
|
|
215
218
|
self,
|
|
216
219
|
url: str,
|
|
217
|
-
stac_config:
|
|
220
|
+
stac_config: dict[str, Any],
|
|
218
221
|
provider: Optional[str],
|
|
219
222
|
eodag_api: EODataAccessGateway,
|
|
220
223
|
root: str = "/",
|
|
@@ -228,8 +231,8 @@ class StacItem(StacCommon):
|
|
|
228
231
|
)
|
|
229
232
|
|
|
230
233
|
def __get_item_list(
|
|
231
|
-
self, search_results: SearchResult, catalog:
|
|
232
|
-
) ->
|
|
234
|
+
self, search_results: SearchResult, catalog: dict[str, Any]
|
|
235
|
+
) -> list[dict[str, Any]]:
|
|
233
236
|
"""Build STAC items list from EODAG search results
|
|
234
237
|
|
|
235
238
|
:param search_results: EODAG search results
|
|
@@ -244,7 +247,7 @@ class StacItem(StacCommon):
|
|
|
244
247
|
)
|
|
245
248
|
|
|
246
249
|
# check if some items need to be converted
|
|
247
|
-
need_conversion:
|
|
250
|
+
need_conversion: dict[str, Any] = {}
|
|
248
251
|
for k, v in item_model["properties"].items():
|
|
249
252
|
if isinstance(v, str):
|
|
250
253
|
conversion, item_model["properties"][k] = get_metadata_path(
|
|
@@ -264,11 +267,11 @@ class StacItem(StacCommon):
|
|
|
264
267
|
]
|
|
265
268
|
ignored_props = COLLECTION_PROPERTIES + item_props + IGNORED_ITEM_PROPERTIES
|
|
266
269
|
|
|
267
|
-
item_list:
|
|
270
|
+
item_list: list[dict[str, Any]] = []
|
|
268
271
|
for product in search_results:
|
|
269
272
|
product_dict = deepcopy(product.__dict__)
|
|
270
273
|
|
|
271
|
-
product_item:
|
|
274
|
+
product_item: dict[str, Any] = jsonpath_parse_dict_items(
|
|
272
275
|
item_model,
|
|
273
276
|
{
|
|
274
277
|
"product": product_dict,
|
|
@@ -370,10 +373,10 @@ class StacItem(StacCommon):
|
|
|
370
373
|
product: EOProduct,
|
|
371
374
|
downloadlink_href: str,
|
|
372
375
|
without_arg_url: str,
|
|
373
|
-
query_dict: Optional[
|
|
376
|
+
query_dict: Optional[dict[str, Any]] = None,
|
|
374
377
|
_dc_qs: Optional[str] = None,
|
|
375
|
-
) ->
|
|
376
|
-
assets:
|
|
378
|
+
) -> dict[str, Any]:
|
|
379
|
+
assets: dict[str, Any] = {}
|
|
377
380
|
settings = Settings.from_environment()
|
|
378
381
|
|
|
379
382
|
if _dc_qs:
|
|
@@ -452,9 +455,9 @@ class StacItem(StacCommon):
|
|
|
452
455
|
self,
|
|
453
456
|
search_results: SearchResult,
|
|
454
457
|
total: int,
|
|
455
|
-
catalog:
|
|
456
|
-
next_link: Optional[
|
|
457
|
-
) ->
|
|
458
|
+
catalog: dict[str, Any],
|
|
459
|
+
next_link: Optional[dict[str, Any]],
|
|
460
|
+
) -> dict[str, Any]:
|
|
458
461
|
"""Build STAC items from EODAG search results
|
|
459
462
|
|
|
460
463
|
:param search_results: EODAG search results
|
|
@@ -503,8 +506,8 @@ class StacItem(StacCommon):
|
|
|
503
506
|
return self.data
|
|
504
507
|
|
|
505
508
|
def __filter_item_model_properties(
|
|
506
|
-
self, item_model:
|
|
507
|
-
) ->
|
|
509
|
+
self, item_model: dict[str, Any], product_type: str
|
|
510
|
+
) -> dict[str, Any]:
|
|
508
511
|
"""Filter item model depending on product type metadata and its extensions.
|
|
509
512
|
Removes not needed parameters, and adds supplementary ones as
|
|
510
513
|
part of oseo extension.
|
|
@@ -568,13 +571,13 @@ class StacItem(StacCommon):
|
|
|
568
571
|
|
|
569
572
|
return result_item_model
|
|
570
573
|
|
|
571
|
-
def __filter_item_properties_values(self, item:
|
|
574
|
+
def __filter_item_properties_values(self, item: dict[str, Any]) -> dict[str, Any]:
|
|
572
575
|
"""Removes empty properties, unused extensions, and add missing extensions
|
|
573
576
|
|
|
574
577
|
:param item: STAC item data
|
|
575
578
|
:returns: Filtered item model
|
|
576
579
|
"""
|
|
577
|
-
all_extensions_dict:
|
|
580
|
+
all_extensions_dict: dict[str, str] = deepcopy(
|
|
578
581
|
self.stac_config["stac_extensions"]
|
|
579
582
|
)
|
|
580
583
|
# parse f-strings with root
|
|
@@ -599,7 +602,7 @@ class StacItem(StacCommon):
|
|
|
599
602
|
|
|
600
603
|
return item
|
|
601
604
|
|
|
602
|
-
def get_stac_item_from_product(self, product: EOProduct) ->
|
|
605
|
+
def get_stac_item_from_product(self, product: EOProduct) -> dict[str, Any]:
|
|
603
606
|
"""Build STAC item from EODAG product
|
|
604
607
|
|
|
605
608
|
:param product: EODAG product
|
|
@@ -659,7 +662,7 @@ class StacCollection(StacCommon):
|
|
|
659
662
|
"""
|
|
660
663
|
|
|
661
664
|
# External STAC collections
|
|
662
|
-
ext_stac_collections:
|
|
665
|
+
ext_stac_collections: dict[str, dict[str, Any]] = dict()
|
|
663
666
|
|
|
664
667
|
@classmethod
|
|
665
668
|
def fetch_external_stac_collections(cls, eodag_api: EODataAccessGateway) -> None:
|
|
@@ -688,7 +691,7 @@ class StacCollection(StacCommon):
|
|
|
688
691
|
def __init__(
|
|
689
692
|
self,
|
|
690
693
|
url: str,
|
|
691
|
-
stac_config:
|
|
694
|
+
stac_config: dict[str, Any],
|
|
692
695
|
provider: Optional[str],
|
|
693
696
|
eodag_api: EODataAccessGateway,
|
|
694
697
|
root: str = "/",
|
|
@@ -701,7 +704,7 @@ class StacCollection(StacCommon):
|
|
|
701
704
|
root=root,
|
|
702
705
|
)
|
|
703
706
|
|
|
704
|
-
def __list_product_type_providers(self, product_type:
|
|
707
|
+
def __list_product_type_providers(self, product_type: dict[str, Any]) -> list[str]:
|
|
705
708
|
"""Retrieve a list of providers for a given product type.
|
|
706
709
|
|
|
707
710
|
:param product_type: Dictionary containing information about the product type.
|
|
@@ -718,8 +721,8 @@ class StacCollection(StacCommon):
|
|
|
718
721
|
]
|
|
719
722
|
|
|
720
723
|
def __generate_stac_collection(
|
|
721
|
-
self, collection_model: Any, product_type:
|
|
722
|
-
) ->
|
|
724
|
+
self, collection_model: Any, product_type: dict[str, Any]
|
|
725
|
+
) -> dict[str, Any]:
|
|
723
726
|
"""Generate a STAC collection dictionary for a given product type.
|
|
724
727
|
|
|
725
728
|
:param collection_model: The base model for the STAC collection.
|
|
@@ -728,7 +731,7 @@ class StacCollection(StacCommon):
|
|
|
728
731
|
"""
|
|
729
732
|
providers = self.__list_product_type_providers(product_type)
|
|
730
733
|
|
|
731
|
-
providers_dict:
|
|
734
|
+
providers_dict: dict[str, dict[str, Any]] = {}
|
|
732
735
|
for provider in providers:
|
|
733
736
|
p_dict = self.get_provider_dict(provider)
|
|
734
737
|
providers_dict.setdefault(p_dict["name"], p_dict)
|
|
@@ -815,7 +818,7 @@ class StacCollection(StacCommon):
|
|
|
815
818
|
instrument: Optional[str] = None,
|
|
816
819
|
constellation: Optional[str] = None,
|
|
817
820
|
datetime: Optional[str] = None,
|
|
818
|
-
) ->
|
|
821
|
+
) -> list[dict[str, Any]]:
|
|
819
822
|
"""Build STAC collections list
|
|
820
823
|
|
|
821
824
|
:param filters: (optional) Additional filters for collections search
|
|
@@ -850,7 +853,7 @@ class StacCollection(StacCommon):
|
|
|
850
853
|
product_types = all_pt
|
|
851
854
|
|
|
852
855
|
# list product types with all metadata using guessed ids
|
|
853
|
-
collection_list:
|
|
856
|
+
collection_list: list[dict[str, Any]] = []
|
|
854
857
|
for product_type in product_types:
|
|
855
858
|
stac_collection = self.__generate_stac_collection(
|
|
856
859
|
collection_model, product_type
|
|
@@ -874,7 +877,7 @@ class StacCatalog(StacCommon):
|
|
|
874
877
|
def __init__(
|
|
875
878
|
self,
|
|
876
879
|
url: str,
|
|
877
|
-
stac_config:
|
|
880
|
+
stac_config: dict[str, Any],
|
|
878
881
|
provider: Optional[str],
|
|
879
882
|
eodag_api: EODataAccessGateway,
|
|
880
883
|
root: str = "/",
|
|
@@ -890,8 +893,8 @@ class StacCatalog(StacCommon):
|
|
|
890
893
|
self.data = {}
|
|
891
894
|
|
|
892
895
|
self.shp_location_config = eodag_api.locations_config
|
|
893
|
-
self.search_args:
|
|
894
|
-
self.children:
|
|
896
|
+
self.search_args: dict[str, Any] = {}
|
|
897
|
+
self.children: list[dict[str, Any]] = []
|
|
895
898
|
|
|
896
899
|
self.catalog_config = deepcopy(stac_config["catalog"])
|
|
897
900
|
|
|
@@ -907,7 +910,7 @@ class StacCatalog(StacCommon):
|
|
|
907
910
|
# build catalog
|
|
908
911
|
self.__build_stac_catalog(collection)
|
|
909
912
|
|
|
910
|
-
def __update_data_from_catalog_config(self, catalog_config:
|
|
913
|
+
def __update_data_from_catalog_config(self, catalog_config: dict[str, Any]) -> bool:
|
|
911
914
|
"""Updates configuration and data using given input catalog config
|
|
912
915
|
|
|
913
916
|
:param catalog_config: Catalog config, from yml stac_config[catalogs]
|
|
@@ -959,7 +962,7 @@ class StacCatalog(StacCommon):
|
|
|
959
962
|
|
|
960
963
|
def set_stac_product_type_by_id(
|
|
961
964
|
self, product_type: str, **_: Any
|
|
962
|
-
) ->
|
|
965
|
+
) -> dict[str, Any]:
|
|
963
966
|
"""Updates catalog with given product_type
|
|
964
967
|
|
|
965
968
|
:param product_type: Product type
|
|
@@ -991,7 +994,7 @@ class StacCatalog(StacCommon):
|
|
|
991
994
|
format_args["catalog"] = defaultdict(str, **self.data)
|
|
992
995
|
format_args["collection"] = collections[0]
|
|
993
996
|
try:
|
|
994
|
-
parsed_dict:
|
|
997
|
+
parsed_dict: dict[str, Any] = format_dict_items(cat_model, **format_args)
|
|
995
998
|
except Exception:
|
|
996
999
|
logger.error("Could not format product_type catalog")
|
|
997
1000
|
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,
|
|
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) ->
|
|
43
|
-
dumped:
|
|
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()}
|