eodash_catalog 0.0.24__tar.gz → 0.0.26__tar.gz
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.
Potentially problematic release.
This version of eodash_catalog might be problematic. Click here for more details.
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.bumpversion.cfg +1 -1
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.github/workflows/ci.yml +0 -1
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/PKG-INFO +1 -1
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/__about__.py +1 -1
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/endpoints.py +7 -2
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/generate_indicators.py +77 -66
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/stac_handling.py +7 -5
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/utils.py +43 -4
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.github/workflows/python-publish.yml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.gitignore +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.vscode/extensions.json +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/.vscode/settings.json +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/LICENSE.txt +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/README.md +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/pyproject.toml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/requirements.txt +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/ruff.toml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/__init__.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/duration.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/sh_endpoint.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/src/eodash_catalog/thumbnails.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/__init__.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/test-data/regional_forecast.json +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/test_generate.py +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-catalogs/testing.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_CROPOMAT1.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_see_solar_energy.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_tif_demo_1.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_tif_demo_2.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_wms_no_time.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-indicators/test_indicator.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-layers/baselayers.yaml +0 -0
- {eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-layers/overlays.yaml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: eodash_catalog
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.26
|
|
4
4
|
Summary: This package is intended to help create a compatible STAC catalog for the eodash dashboard client. It supports configuration of multiple endpoint types for information extraction.
|
|
5
5
|
Project-URL: Documentation, https://github.com/eodash/eodash_catalog#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/eodash/eodash_catalog/issues
|
|
@@ -12,6 +12,7 @@ import requests
|
|
|
12
12
|
from dateutil import parser
|
|
13
13
|
from pystac import Asset, Catalog, Collection, Item, Link, SpatialExtent, Summaries
|
|
14
14
|
from pystac_client import Client
|
|
15
|
+
from structlog import get_logger
|
|
15
16
|
|
|
16
17
|
from eodash_catalog.sh_endpoint import get_SH_token
|
|
17
18
|
from eodash_catalog.stac_handling import (
|
|
@@ -31,6 +32,8 @@ from eodash_catalog.utils import (
|
|
|
31
32
|
retrieveExtentFromWMSWMTS,
|
|
32
33
|
)
|
|
33
34
|
|
|
35
|
+
LOGGER = get_logger(__name__)
|
|
36
|
+
|
|
34
37
|
|
|
35
38
|
def process_STAC_Datacube_Endpoint(
|
|
36
39
|
catalog_config: dict, endpoint_config: dict, collection_config: dict, catalog: Catalog
|
|
@@ -774,7 +777,7 @@ def add_visualization_info(
|
|
|
774
777
|
)
|
|
775
778
|
)
|
|
776
779
|
else:
|
|
777
|
-
|
|
780
|
+
LOGGER.info(f"Visualization endpoint not supported {endpoint_config['Name']}")
|
|
778
781
|
|
|
779
782
|
|
|
780
783
|
def handle_custom_endpoint(
|
|
@@ -797,7 +800,7 @@ def handle_custom_endpoint(
|
|
|
797
800
|
importlib.import_module(module_name), func_name
|
|
798
801
|
)
|
|
799
802
|
except ModuleNotFoundError as e:
|
|
800
|
-
|
|
803
|
+
LOGGER.warn(
|
|
801
804
|
f"""function {func_name} from module {module_name} can not be imported.
|
|
802
805
|
Check if you are specifying relative path inside the
|
|
803
806
|
catalog repository or catalog generator repository."""
|
|
@@ -865,6 +868,8 @@ def handle_raw_source(
|
|
|
865
868
|
link = collection.add_item(item)
|
|
866
869
|
link.extra_fields["datetime"] = time_entry["Time"]
|
|
867
870
|
link.extra_fields["assets"] = [a["File"] for a in time_entry["Assets"]]
|
|
871
|
+
# eodash v4 compatibility, adding last referenced style to collection
|
|
872
|
+
collection.add_link(style_link)
|
|
868
873
|
add_collection_information(catalog_config, collection, collection_config)
|
|
869
874
|
collection.update_extent_from_items()
|
|
870
875
|
return collection
|
|
@@ -14,6 +14,7 @@ from dotenv import load_dotenv
|
|
|
14
14
|
from pystac import Catalog, CatalogType, Collection, Link, Summaries
|
|
15
15
|
from pystac.layout import TemplateLayoutStrategy
|
|
16
16
|
from pystac.validation import validate_all
|
|
17
|
+
from structlog import get_logger
|
|
17
18
|
from yaml.loader import SafeLoader
|
|
18
19
|
|
|
19
20
|
from eodash_catalog.endpoints import (
|
|
@@ -40,14 +41,16 @@ from eodash_catalog.utils import (
|
|
|
40
41
|
add_single_item_if_collection_empty,
|
|
41
42
|
iter_len_at_least,
|
|
42
43
|
recursive_save,
|
|
44
|
+
retry,
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
# make sure we are loading the env local definition
|
|
46
48
|
load_dotenv()
|
|
49
|
+
LOGGER = get_logger(__name__)
|
|
47
50
|
|
|
48
51
|
|
|
49
52
|
def process_catalog_file(file_path: str, options: Options):
|
|
50
|
-
|
|
53
|
+
LOGGER.info(f"Processing catalog: {file_path}")
|
|
51
54
|
with open(file_path) as f:
|
|
52
55
|
catalog_config: dict = yaml.load(f, Loader=SafeLoader)
|
|
53
56
|
|
|
@@ -62,7 +65,7 @@ def process_catalog_file(file_path: str, options: Options):
|
|
|
62
65
|
# create full catalog
|
|
63
66
|
process_collections = catalog_config["collections"]
|
|
64
67
|
if len(process_collections) == 0:
|
|
65
|
-
|
|
68
|
+
LOGGER.info("No applicable collections found for catalog, skipping creation")
|
|
66
69
|
return
|
|
67
70
|
catalog = Catalog(
|
|
68
71
|
id=catalog_config["id"],
|
|
@@ -87,7 +90,7 @@ def process_catalog_file(file_path: str, options: Options):
|
|
|
87
90
|
options,
|
|
88
91
|
)
|
|
89
92
|
else:
|
|
90
|
-
|
|
93
|
+
LOGGER.info(f"Warning: neither collection nor indicator found for {collection}")
|
|
91
94
|
if "MapProjection" in catalog_config:
|
|
92
95
|
catalog.extra_fields["eodash:mapProjection"] = catalog_config["MapProjection"]
|
|
93
96
|
|
|
@@ -95,7 +98,7 @@ def process_catalog_file(file_path: str, options: Options):
|
|
|
95
98
|
# expecting that the catalog will be hosted online, self url should correspond to that
|
|
96
99
|
# default to a local folder + catalog id in case not set
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
LOGGER.info("Started creation of collection files")
|
|
99
102
|
start = time.time()
|
|
100
103
|
if options.ni:
|
|
101
104
|
catalog_self_href = f'{options.outputpath}/{catalog_config["id"]}'
|
|
@@ -109,15 +112,15 @@ def process_catalog_file(file_path: str, options: Options):
|
|
|
109
112
|
catalog.normalize_hrefs(catalog_self_href, strategy=strategy)
|
|
110
113
|
catalog.save(dest_href="{}/{}".format(options.outputpath, catalog_config["id"]))
|
|
111
114
|
end = time.time()
|
|
112
|
-
|
|
115
|
+
LOGGER.info(f"Catalog {catalog_config['id']}: Time consumed in saving: {end - start}")
|
|
113
116
|
|
|
114
117
|
if options.vd:
|
|
115
118
|
# try to validate catalog if flag was set
|
|
116
|
-
|
|
119
|
+
LOGGER.info(f"Running validation of catalog {file_path}")
|
|
117
120
|
try:
|
|
118
121
|
validate_all(catalog.to_dict(), href=catalog_config["endpoint"])
|
|
119
122
|
except Exception as e:
|
|
120
|
-
|
|
123
|
+
LOGGER.info(f"Issue validation collection: {e}")
|
|
121
124
|
|
|
122
125
|
|
|
123
126
|
def extract_indicator_info(parent_collection: Collection):
|
|
@@ -161,7 +164,7 @@ def process_indicator_file(
|
|
|
161
164
|
catalog_config: dict, file_path: str, catalog: Catalog, options: Options
|
|
162
165
|
):
|
|
163
166
|
with open(file_path) as f:
|
|
164
|
-
|
|
167
|
+
LOGGER.info(f"Processing indicator: {file_path}")
|
|
165
168
|
indicator_config: dict = yaml.load(f, Loader=SafeLoader)
|
|
166
169
|
parent_indicator = get_or_create_collection(
|
|
167
170
|
catalog, indicator_config["Name"], indicator_config, catalog_config, {}
|
|
@@ -191,71 +194,79 @@ def process_indicator_file(
|
|
|
191
194
|
add_to_catalog(parent_indicator, catalog, {}, indicator_config)
|
|
192
195
|
|
|
193
196
|
|
|
197
|
+
@retry((Exception), tries=3, delay=5, backoff=2, logger=LOGGER)
|
|
194
198
|
def process_collection_file(
|
|
195
199
|
catalog_config: dict, file_path: str, catalog: Catalog | Collection, options: Options
|
|
196
200
|
):
|
|
197
|
-
|
|
201
|
+
LOGGER.info(f"Processing collection: {file_path}")
|
|
198
202
|
with open(file_path) as f:
|
|
199
203
|
collection_config: dict = yaml.load(f, Loader=SafeLoader)
|
|
200
204
|
if "Resources" in collection_config:
|
|
201
205
|
for endpoint_config in collection_config["Resources"]:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
206
|
+
try:
|
|
207
|
+
collection = None
|
|
208
|
+
if endpoint_config["Name"] == "Sentinel Hub":
|
|
209
|
+
collection = handle_SH_endpoint(
|
|
210
|
+
catalog_config, endpoint_config, collection_config, catalog, options
|
|
211
|
+
)
|
|
212
|
+
elif endpoint_config["Name"] == "Sentinel Hub WMS":
|
|
213
|
+
collection = handle_SH_WMS_endpoint(
|
|
214
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
215
|
+
)
|
|
216
|
+
elif endpoint_config["Name"] == "GeoDB":
|
|
217
|
+
collection = handle_GeoDB_endpoint(
|
|
218
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
219
|
+
)
|
|
220
|
+
elif endpoint_config["Name"] == "VEDA":
|
|
221
|
+
collection = handle_VEDA_endpoint(
|
|
222
|
+
catalog_config, endpoint_config, collection_config, catalog, options
|
|
223
|
+
)
|
|
224
|
+
elif endpoint_config["Name"] == "marinedatastore":
|
|
225
|
+
collection = handle_WMS_endpoint(
|
|
226
|
+
catalog_config, endpoint_config, collection_config, catalog, wmts=True
|
|
227
|
+
)
|
|
228
|
+
elif endpoint_config["Name"] == "xcube":
|
|
229
|
+
collection = handle_xcube_endpoint(
|
|
230
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
231
|
+
)
|
|
232
|
+
elif endpoint_config["Name"] == "WMS":
|
|
233
|
+
collection = handle_WMS_endpoint(
|
|
234
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
235
|
+
)
|
|
236
|
+
elif endpoint_config["Name"] == "JAXA_WMTS_PALSAR":
|
|
237
|
+
# somewhat one off creation of individual WMTS layers as individual items
|
|
238
|
+
collection = handle_WMS_endpoint(
|
|
239
|
+
catalog_config, endpoint_config, collection_config, catalog, wmts=True
|
|
240
|
+
)
|
|
241
|
+
elif endpoint_config["Name"] == "Collection-only":
|
|
242
|
+
collection = handle_collection_only(
|
|
243
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
244
|
+
)
|
|
245
|
+
elif endpoint_config["Name"] == "Custom-Endpoint":
|
|
246
|
+
collection = handle_custom_endpoint(
|
|
247
|
+
catalog_config,
|
|
248
|
+
endpoint_config,
|
|
249
|
+
collection_config,
|
|
250
|
+
catalog,
|
|
251
|
+
)
|
|
252
|
+
elif endpoint_config["Name"] in ["COG source", "GeoJSON source"]:
|
|
253
|
+
collection = handle_raw_source(
|
|
254
|
+
catalog_config, endpoint_config, collection_config, catalog
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
raise ValueError("Type of Resource is not supported")
|
|
258
|
+
if collection:
|
|
259
|
+
add_single_item_if_collection_empty(collection)
|
|
260
|
+
add_projection_info(endpoint_config, collection)
|
|
261
|
+
add_to_catalog(collection, catalog, endpoint_config, collection_config)
|
|
262
|
+
else:
|
|
263
|
+
raise Exception(
|
|
264
|
+
f"No collection was generated for resource {endpoint_config}"
|
|
265
|
+
)
|
|
266
|
+
except Exception as e:
|
|
267
|
+
LOGGER.warn(f"""Exception: {e.args[0]} with config: {endpoint_config}""")
|
|
268
|
+
raise e
|
|
269
|
+
|
|
259
270
|
elif "Subcollections" in collection_config:
|
|
260
271
|
# if no endpoint is specified we check for definition of subcollections
|
|
261
272
|
parent_collection = get_or_create_collection(
|
|
@@ -15,10 +15,13 @@ from pystac import (
|
|
|
15
15
|
SpatialExtent,
|
|
16
16
|
TemporalExtent,
|
|
17
17
|
)
|
|
18
|
+
from structlog import get_logger
|
|
18
19
|
from yaml.loader import SafeLoader
|
|
19
20
|
|
|
20
21
|
from eodash_catalog.utils import generateDateIsostringsFromInterval
|
|
21
22
|
|
|
23
|
+
LOGGER = get_logger(__name__)
|
|
24
|
+
|
|
22
25
|
|
|
23
26
|
def get_or_create_collection(
|
|
24
27
|
catalog: Catalog,
|
|
@@ -65,7 +68,7 @@ def get_or_create_collection(
|
|
|
65
68
|
if response.status_code == 200:
|
|
66
69
|
description = response.text
|
|
67
70
|
elif "Subtitle" in collection_config:
|
|
68
|
-
|
|
71
|
+
LOGGER.warn("Markdown file could not be fetched")
|
|
69
72
|
description = collection_config["Subtitle"]
|
|
70
73
|
else:
|
|
71
74
|
# relative path to assets was given
|
|
@@ -73,7 +76,7 @@ def get_or_create_collection(
|
|
|
73
76
|
if response.status_code == 200:
|
|
74
77
|
description = response.text
|
|
75
78
|
elif "Subtitle" in collection_config:
|
|
76
|
-
|
|
79
|
+
LOGGER.warn("Markdown file could not be fetched")
|
|
77
80
|
description = collection_config["Subtitle"]
|
|
78
81
|
elif "Subtitle" in collection_config:
|
|
79
82
|
# Try to use at least subtitle to fill some information
|
|
@@ -242,10 +245,9 @@ def add_collection_information(
|
|
|
242
245
|
)
|
|
243
246
|
else:
|
|
244
247
|
# fallback to proprietary
|
|
245
|
-
|
|
248
|
+
LOGGER.warn("License could not be parsed, falling back to proprietary")
|
|
246
249
|
collection.license = "proprietary"
|
|
247
250
|
else:
|
|
248
|
-
# print("WARNING: No license was provided, falling back to proprietary")
|
|
249
251
|
pass
|
|
250
252
|
|
|
251
253
|
if "Provider" in collection_config:
|
|
@@ -258,7 +260,7 @@ def add_collection_information(
|
|
|
258
260
|
for provider in collection_config["Provider"]
|
|
259
261
|
]
|
|
260
262
|
except Exception:
|
|
261
|
-
|
|
263
|
+
LOGGER.warn(f"Issue creating provider information for collection: {collection.id}")
|
|
262
264
|
|
|
263
265
|
if "Citation" in collection_config:
|
|
264
266
|
if "DOI" in collection_config["Citation"]:
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
3
|
import threading
|
|
4
|
+
import time
|
|
4
5
|
import uuid
|
|
5
6
|
from collections.abc import Iterator
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
from datetime import datetime, timedelta
|
|
8
9
|
from decimal import Decimal
|
|
9
|
-
from functools import reduce
|
|
10
|
+
from functools import reduce, wraps
|
|
10
11
|
from typing import Any
|
|
11
12
|
|
|
12
13
|
from dateutil import parser
|
|
@@ -14,6 +15,7 @@ from owslib.wms import WebMapService
|
|
|
14
15
|
from owslib.wmts import WebMapTileService
|
|
15
16
|
from pystac import Catalog, Collection, Item, RelType
|
|
16
17
|
from six import string_types
|
|
18
|
+
from structlog import get_logger
|
|
17
19
|
|
|
18
20
|
from eodash_catalog.duration import Duration
|
|
19
21
|
|
|
@@ -30,6 +32,8 @@ ISO8601_PERIOD_REGEX = re.compile(
|
|
|
30
32
|
)
|
|
31
33
|
# regular expression to parse ISO duartion strings.
|
|
32
34
|
|
|
35
|
+
LOGGER = get_logger(__name__)
|
|
36
|
+
|
|
33
37
|
|
|
34
38
|
def create_geojson_point(lon: int | float, lat: int | float) -> dict[str, Any]:
|
|
35
39
|
point = {"type": "Point", "coordinates": [lon, lat]}
|
|
@@ -84,10 +88,10 @@ def retrieveExtentFromWMSWMTS(
|
|
|
84
88
|
# get unique times
|
|
85
89
|
times = reduce(lambda re, x: [*re, x] if x not in re else re, times, [])
|
|
86
90
|
except Exception as e:
|
|
87
|
-
|
|
91
|
+
LOGGER.warn("Issue extracting information from service capabilities")
|
|
88
92
|
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
|
|
89
93
|
message = template.format(type(e).__name__, e.args)
|
|
90
|
-
|
|
94
|
+
LOGGER.warn(message)
|
|
91
95
|
|
|
92
96
|
bbox = [-180.0, -90.0, 180.0, 90.0]
|
|
93
97
|
if service and service[layer].boundingBoxWGS84:
|
|
@@ -116,7 +120,6 @@ def parse_duration(datestring):
|
|
|
116
120
|
if key not in ("separator", "sign"):
|
|
117
121
|
if val is None:
|
|
118
122
|
groups[key] = "0n"
|
|
119
|
-
# print groups[key]
|
|
120
123
|
if key in ("years", "months"):
|
|
121
124
|
groups[key] = Decimal(groups[key][:-1].replace(",", "."))
|
|
122
125
|
else:
|
|
@@ -268,3 +271,39 @@ def replace_with_env_variables(s: str) -> str:
|
|
|
268
271
|
|
|
269
272
|
# Use re.sub with the replacement function
|
|
270
273
|
return re.sub(pattern, replacer, s)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def retry(exceptions, tries=3, delay=2, backoff=1, logger=None):
|
|
277
|
+
"""
|
|
278
|
+
Retry decorator for retrying exceptions.
|
|
279
|
+
|
|
280
|
+
:param exceptions: Exception or tuple of exceptions to catch.
|
|
281
|
+
:param tries: Number of attempts. Default is 3.
|
|
282
|
+
:param delay: Initial delay between attempts in seconds. Default is 2.
|
|
283
|
+
:param backoff: Multiplier applied to delay between attempts. Default is 1 (no backoff).
|
|
284
|
+
:param logger: Logger to use. If None, print. Default is None.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
def decorator(func):
|
|
288
|
+
@wraps(func)
|
|
289
|
+
def wrapper(*args, **kwargs):
|
|
290
|
+
_tries, _delay = tries, delay
|
|
291
|
+
while _tries > 0:
|
|
292
|
+
try:
|
|
293
|
+
return func(*args, **kwargs)
|
|
294
|
+
except exceptions as e:
|
|
295
|
+
_tries -= 1
|
|
296
|
+
if _tries == 0:
|
|
297
|
+
raise
|
|
298
|
+
else:
|
|
299
|
+
msg = f"{e}, Try: {tries-_tries+1}/{tries}, retry in {_delay} seconds..."
|
|
300
|
+
if logger:
|
|
301
|
+
logger.warning(msg)
|
|
302
|
+
else:
|
|
303
|
+
print(msg)
|
|
304
|
+
time.sleep(_delay)
|
|
305
|
+
_delay *= backoff
|
|
306
|
+
|
|
307
|
+
return wrapper
|
|
308
|
+
|
|
309
|
+
return decorator
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_CROPOMAT1.yaml
RENAMED
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_see_solar_energy.yaml
RENAMED
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_tif_demo_1.yaml
RENAMED
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_tif_demo_2.yaml
RENAMED
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-collections/test_wms_no_time.yaml
RENAMED
|
File without changes
|
{eodash_catalog-0.0.24 → eodash_catalog-0.0.26}/tests/testing-indicators/test_indicator.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|