eodag 2.12.0__py3-none-any.whl → 3.0.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/__init__.py +6 -8
- eodag/api/core.py +654 -538
- eodag/api/product/__init__.py +12 -2
- eodag/api/product/_assets.py +59 -16
- eodag/api/product/_product.py +100 -93
- eodag/api/product/drivers/__init__.py +7 -2
- eodag/api/product/drivers/base.py +0 -3
- eodag/api/product/metadata_mapping.py +192 -96
- eodag/api/search_result.py +69 -10
- eodag/cli.py +55 -25
- eodag/config.py +391 -116
- eodag/plugins/apis/base.py +11 -165
- eodag/plugins/apis/ecmwf.py +36 -25
- eodag/plugins/apis/usgs.py +80 -35
- eodag/plugins/authentication/aws_auth.py +13 -4
- eodag/plugins/authentication/base.py +10 -1
- eodag/plugins/authentication/generic.py +2 -2
- eodag/plugins/authentication/header.py +31 -6
- eodag/plugins/authentication/keycloak.py +17 -84
- eodag/plugins/authentication/oauth.py +3 -3
- eodag/plugins/authentication/openid_connect.py +268 -49
- eodag/plugins/authentication/qsauth.py +4 -1
- eodag/plugins/authentication/sas_auth.py +9 -2
- eodag/plugins/authentication/token.py +98 -47
- eodag/plugins/authentication/token_exchange.py +122 -0
- 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 +149 -185
- eodag/plugins/download/base.py +88 -97
- eodag/plugins/download/creodias_s3.py +1 -1
- eodag/plugins/download/http.py +638 -310
- eodag/plugins/download/s3rest.py +47 -45
- eodag/plugins/manager.py +228 -88
- eodag/plugins/search/__init__.py +36 -0
- eodag/plugins/search/base.py +239 -30
- eodag/plugins/search/build_search_result.py +382 -37
- eodag/plugins/search/cop_marine.py +441 -0
- eodag/plugins/search/creodias_s3.py +25 -20
- eodag/plugins/search/csw.py +5 -7
- eodag/plugins/search/data_request_search.py +61 -30
- eodag/plugins/search/qssearch.py +713 -255
- eodag/plugins/search/static_stac_search.py +106 -40
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/product_types.yml +1921 -34
- eodag/resources/providers.yml +4091 -3655
- eodag/resources/stac.yml +50 -216
- eodag/resources/stac_api.yml +71 -25
- eodag/resources/stac_provider.yml +5 -0
- eodag/resources/user_conf_template.yml +89 -32
- eodag/rest/__init__.py +6 -0
- eodag/rest/cache.py +70 -0
- eodag/rest/config.py +68 -0
- eodag/rest/constants.py +26 -0
- eodag/rest/core.py +735 -0
- eodag/rest/errors.py +178 -0
- eodag/rest/server.py +264 -431
- eodag/rest/stac.py +442 -836
- eodag/rest/types/collections_search.py +44 -0
- eodag/rest/types/eodag_search.py +238 -47
- eodag/rest/types/queryables.py +164 -0
- eodag/rest/types/stac_search.py +273 -0
- eodag/rest/utils/__init__.py +216 -0
- eodag/rest/utils/cql_evaluate.py +119 -0
- eodag/rest/utils/rfc3339.py +64 -0
- eodag/types/__init__.py +106 -10
- eodag/types/bbox.py +15 -14
- eodag/types/download_args.py +40 -0
- eodag/types/search_args.py +57 -7
- eodag/types/whoosh.py +79 -0
- eodag/utils/__init__.py +110 -91
- eodag/utils/constraints.py +37 -45
- eodag/utils/exceptions.py +39 -22
- eodag/utils/import_system.py +0 -4
- eodag/utils/logging.py +37 -80
- eodag/utils/notebook.py +4 -4
- eodag/utils/repr.py +113 -0
- eodag/utils/requests.py +128 -0
- eodag/utils/rest.py +100 -0
- eodag/utils/stac_reader.py +93 -21
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/METADATA +88 -53
- eodag-3.0.0.dist-info/RECORD +109 -0
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/WHEEL +1 -1
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/entry_points.txt +7 -5
- eodag/plugins/apis/cds.py +0 -540
- eodag/rest/types/stac_queryables.py +0 -134
- eodag/rest/utils.py +0 -1133
- eodag-2.12.0.dist-info/RECORD +0 -94
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/LICENSE +0 -0
- {eodag-2.12.0.dist-info → eodag-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -18,22 +18,20 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import logging
|
|
21
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
|
|
21
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast
|
|
22
|
+
from unittest import mock
|
|
22
23
|
|
|
23
24
|
import geojson
|
|
24
25
|
|
|
26
|
+
from eodag.api.product.metadata_mapping import get_metadata_path_value
|
|
25
27
|
from eodag.api.search_result import SearchResult
|
|
26
28
|
from eodag.plugins.crunch.filter_date import FilterDate
|
|
27
29
|
from eodag.plugins.crunch.filter_overlap import FilterOverlap
|
|
28
30
|
from eodag.plugins.crunch.filter_property import FilterProperty
|
|
31
|
+
from eodag.plugins.search import PreparedSearch
|
|
29
32
|
from eodag.plugins.search.qssearch import StacSearch
|
|
30
|
-
from eodag.utils import
|
|
31
|
-
|
|
32
|
-
DEFAULT_PAGE,
|
|
33
|
-
HTTP_REQ_TIMEOUT,
|
|
34
|
-
MockResponse,
|
|
35
|
-
)
|
|
36
|
-
from eodag.utils.stac_reader import fetch_stac_items
|
|
33
|
+
from eodag.utils import HTTP_REQ_TIMEOUT, MockResponse
|
|
34
|
+
from eodag.utils.stac_reader import fetch_stac_collections, fetch_stac_items
|
|
37
35
|
|
|
38
36
|
if TYPE_CHECKING:
|
|
39
37
|
from eodag.api.product import EOProduct
|
|
@@ -62,55 +60,121 @@ class StaticStacSearch(StacSearch):
|
|
|
62
60
|
Then it uses crunchers to only keep products matching query parameters.
|
|
63
61
|
|
|
64
62
|
:param provider: An eodag providers configuration dictionary
|
|
65
|
-
:type provider: dict
|
|
66
63
|
:param config: Path to the user configuration file
|
|
67
|
-
:type config: str
|
|
68
64
|
"""
|
|
69
65
|
|
|
70
66
|
def __init__(self, provider: str, config: PluginConfig) -> None:
|
|
67
|
+
# prevent search parameters from being queried when they are known in the configuration or not
|
|
68
|
+
for param, mapping in config.metadata_mapping.items():
|
|
69
|
+
# only keep one queryable to allow the mock search request
|
|
70
|
+
if param != "productType":
|
|
71
|
+
config.metadata_mapping[param] = get_metadata_path_value(mapping)
|
|
72
|
+
config.discover_metadata["auto_discovery"] = False
|
|
73
|
+
# there is no endpoint for fetching queryables with a static search
|
|
74
|
+
config.discover_queryables["fetch_url"] = None
|
|
75
|
+
config.discover_queryables["product_type_fetch_url"] = None
|
|
76
|
+
|
|
71
77
|
super(StaticStacSearch, self).__init__(provider, config)
|
|
72
78
|
self.config.__dict__.setdefault("max_connections", 100)
|
|
73
79
|
self.config.__dict__.setdefault("timeout", HTTP_REQ_TIMEOUT)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
""
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
self.config.__dict__.setdefault("ssl_verify", True)
|
|
81
|
+
self.config.__dict__.setdefault("pagination", {})
|
|
82
|
+
self.config.__dict__["pagination"].setdefault(
|
|
83
|
+
"total_items_nb_key_path", "$.null"
|
|
84
|
+
)
|
|
85
|
+
self.config.__dict__["pagination"].setdefault("max_items_per_page", -1)
|
|
86
|
+
# disable product types discovery by default (if endpoints equals to STAC API default)
|
|
87
|
+
if (
|
|
88
|
+
getattr(self.config, "discover_product_types", {}).get("fetch_url")
|
|
89
|
+
== "{api_endpoint}/../collections"
|
|
90
|
+
):
|
|
91
|
+
self.config.discover_product_types = {"fetch_url": None}
|
|
92
|
+
|
|
93
|
+
def discover_product_types(self, **kwargs: Any) -> Optional[Dict[str, Any]]:
|
|
94
|
+
"""Fetch product types list from a static STAC Catalog provider using `discover_product_types` conf
|
|
95
|
+
|
|
96
|
+
:returns: configuration dict containing fetched product types information
|
|
80
97
|
"""
|
|
81
|
-
|
|
98
|
+
fetch_url = cast(
|
|
99
|
+
str,
|
|
100
|
+
self.config.discover_product_types["fetch_url"].format(
|
|
101
|
+
**self.config.__dict__
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
collections = fetch_stac_collections(
|
|
105
|
+
fetch_url,
|
|
106
|
+
collection=kwargs.get("q"),
|
|
107
|
+
max_connections=self.config.max_connections,
|
|
108
|
+
timeout=int(self.config.timeout),
|
|
109
|
+
ssl_verify=self.config.ssl_verify,
|
|
110
|
+
)
|
|
111
|
+
if "q" in kwargs:
|
|
112
|
+
collections = [c for c in collections if c["id"] == kwargs["q"]]
|
|
113
|
+
collections_mock_response = {"collections": collections}
|
|
114
|
+
|
|
115
|
+
# discover_product_types on mocked QueryStringSearch._request
|
|
116
|
+
with mock.patch(
|
|
117
|
+
"eodag.plugins.search.qssearch.QueryStringSearch._request",
|
|
118
|
+
autospec=True,
|
|
119
|
+
return_value=MockResponse(collections_mock_response, 200),
|
|
120
|
+
):
|
|
121
|
+
conf_update_dict = super(StaticStacSearch, self).discover_product_types(
|
|
122
|
+
**kwargs
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return conf_update_dict
|
|
82
126
|
|
|
83
127
|
def query(
|
|
84
128
|
self,
|
|
85
|
-
|
|
86
|
-
items_per_page: int = DEFAULT_ITEMS_PER_PAGE,
|
|
87
|
-
page: int = DEFAULT_PAGE,
|
|
88
|
-
count: bool = True,
|
|
129
|
+
prep: PreparedSearch = PreparedSearch(),
|
|
89
130
|
**kwargs: Any,
|
|
90
131
|
) -> Tuple[List[EOProduct], Optional[int]]:
|
|
91
132
|
"""Perform a search on a static STAC Catalog"""
|
|
92
133
|
|
|
134
|
+
# only return 1 page if pagination is disabled
|
|
135
|
+
if (
|
|
136
|
+
prep.page
|
|
137
|
+
and prep.page > 1
|
|
138
|
+
and prep.items_per_page is not None
|
|
139
|
+
and prep.items_per_page <= 0
|
|
140
|
+
):
|
|
141
|
+
return ([], 0) if prep.count else ([], None)
|
|
142
|
+
|
|
143
|
+
product_type = kwargs.get("productType", prep.product_type)
|
|
144
|
+
# provider product type specific conf
|
|
145
|
+
self.product_type_def_params = (
|
|
146
|
+
self.get_product_type_def_params(product_type, **kwargs)
|
|
147
|
+
if product_type is not None
|
|
148
|
+
else {}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
for collection in self.get_collections(prep, **kwargs):
|
|
152
|
+
# skip empty collection if one is required in api_endpoint
|
|
153
|
+
if "{collection}" in self.config.api_endpoint and not collection:
|
|
154
|
+
continue
|
|
155
|
+
search_endpoint = self.config.api_endpoint.rstrip("/").format(
|
|
156
|
+
collection=collection
|
|
157
|
+
)
|
|
158
|
+
|
|
93
159
|
features = fetch_stac_items(
|
|
94
|
-
|
|
160
|
+
search_endpoint,
|
|
95
161
|
recursive=True,
|
|
96
162
|
max_connections=self.config.max_connections,
|
|
97
|
-
timeout=self.config.timeout,
|
|
163
|
+
timeout=int(self.config.timeout),
|
|
164
|
+
ssl_verify=self.config.ssl_verify,
|
|
98
165
|
)
|
|
99
166
|
nb_features = len(features)
|
|
100
167
|
feature_collection = geojson.FeatureCollection(features)
|
|
101
168
|
|
|
102
|
-
#
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
169
|
+
# query on mocked StacSearch._request
|
|
170
|
+
with mock.patch(
|
|
171
|
+
"eodag.plugins.search.qssearch.StacSearch._request",
|
|
172
|
+
autospec=True,
|
|
173
|
+
return_value=MockResponse(feature_collection, 200),
|
|
174
|
+
):
|
|
175
|
+
eo_products, _ = super(StaticStacSearch, self).query(
|
|
176
|
+
PreparedSearch(items_per_page=nb_features, page=1, count=True), **kwargs
|
|
107
177
|
)
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
# query on mocked StacSearch
|
|
111
|
-
eo_products, _ = super(StaticStacSearch, self).query(
|
|
112
|
-
items_per_page=nb_features, page=1, count=True, **kwargs
|
|
113
|
-
)
|
|
114
178
|
# filter using query params
|
|
115
179
|
search_result = SearchResult(eo_products)
|
|
116
180
|
# Filter by date
|
|
@@ -124,9 +188,10 @@ class StaticStacSearch(StacSearch):
|
|
|
124
188
|
)
|
|
125
189
|
|
|
126
190
|
# Filter by geometry
|
|
127
|
-
|
|
191
|
+
geometry = kwargs.pop("geometry", None)
|
|
192
|
+
if geometry:
|
|
128
193
|
search_result = search_result.crunch(
|
|
129
|
-
FilterOverlap({"intersects": True}), geometry=
|
|
194
|
+
FilterOverlap({"intersects": True}), geometry=geometry
|
|
130
195
|
)
|
|
131
196
|
# Filter by cloudCover
|
|
132
197
|
if "cloudCover" in kwargs.keys():
|
|
@@ -151,7 +216,8 @@ class StaticStacSearch(StacSearch):
|
|
|
151
216
|
FilterProperty({property_key: property_value, "operator": "eq"})
|
|
152
217
|
)
|
|
153
218
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
219
|
+
return (
|
|
220
|
+
(search_result.data, len(search_result))
|
|
221
|
+
if prep.count
|
|
222
|
+
else (search_result.data, None)
|
|
223
|
+
)
|