eodash_catalog 0.0.16__py3-none-any.whl → 0.0.18__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.

Potentially problematic release.


This version of eodash_catalog might be problematic. Click here for more details.

@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2024-present Daniel Santillan <daniel.santillan@eox.at>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.0.16"
4
+ __version__ = "0.0.18"
@@ -4,7 +4,7 @@ import os
4
4
  import sys
5
5
  import uuid
6
6
  from collections.abc import Callable
7
- from datetime import datetime, timedelta
7
+ from datetime import datetime, timedelta, timezone
8
8
  from itertools import groupby
9
9
  from operator import itemgetter
10
10
 
@@ -27,6 +27,7 @@ from eodash_catalog.utils import (
27
27
  create_geojson_from_bbox,
28
28
  create_geojson_point,
29
29
  generate_veda_cog_link,
30
+ replace_with_env_variables,
30
31
  retrieveExtentFromWMSWMTS,
31
32
  )
32
33
 
@@ -293,7 +294,7 @@ def handle_collection_only(
293
294
  catalog, collection_config["Name"], collection_config, catalog_config, endpoint_config
294
295
  )
295
296
  times = get_collection_times_from_config(endpoint_config)
296
- if len(times) > 0 and not endpoint_config.get("Disable_Items"):
297
+ if len(times) > 0:
297
298
  for t in times:
298
299
  item = Item(
299
300
  id=t,
@@ -473,7 +474,7 @@ def handle_SH_endpoint(
473
474
  catalog: Catalog,
474
475
  options: Options,
475
476
  ) -> Collection:
476
- token = get_SH_token()
477
+ token = get_SH_token(endpoint_config)
477
478
  headers = {"Authorization": f"Bearer {token}"}
478
479
  endpoint_config["EndPoint"] = "https://services.sentinel-hub.com/api/v1/catalog/1.0.0/"
479
480
  # Overwrite collection id with type, such as ZARR or BYOC
@@ -509,8 +510,21 @@ def handle_WMS_endpoint(
509
510
  version=endpoint_config.get("Version", "1.1.1"),
510
511
  wmts=wmts,
511
512
  )
513
+ # optionally filter time results
514
+ if query := endpoint_config.get("Query"):
515
+ datetime_query = [times[0], times[-1]]
516
+ if start := query.get("Start"):
517
+ datetime_query[0] = parser.isoparse(start).replace(tzinfo=timezone.utc)
518
+ if end := query.get("End"):
519
+ datetime_query[1] = parser.isoparse(end).replace(tzinfo=timezone.utc)
520
+ # filter times based on query Start/End
521
+ times = [
522
+ datetime_str
523
+ for datetime_str in times
524
+ if datetime_query[0] <= parser.isoparse(datetime_str) < datetime_query[1]
525
+ ]
512
526
  # Create an item per time to allow visualization in stac clients
513
- if len(times) > 0 and not endpoint_config.get("Disable_Items"):
527
+ if len(times) > 0:
514
528
  for t in times:
515
529
  item = Item(
516
530
  id=t,
@@ -567,6 +581,10 @@ def add_visualization_info(
567
581
  instanceId = os.getenv("SH_INSTANCE_ID")
568
582
  if "InstanceId" in endpoint_config:
569
583
  instanceId = endpoint_config["InstanceId"]
584
+ if env_id := endpoint_config.get("CustomSHEnvId"):
585
+ # special handling for custom environment
586
+ # (will take SH_INSTANCE_ID_{env_id}) as ENV VAR
587
+ instanceId = os.getenv(f"SH_INSTANCE_ID_{env_id}")
570
588
  extra_fields: dict[str, list[str] | dict[str, str]] = {
571
589
  "wms:layers": [endpoint_config["LayerId"]],
572
590
  "role": ["data"],
@@ -604,10 +622,13 @@ def add_visualization_info(
604
622
  media_type = "image/jpeg"
605
623
  if "MediaType" in endpoint_config:
606
624
  media_type = endpoint_config["MediaType"]
625
+ endpoint_url = endpoint_config["EndPoint"]
626
+ # custom replacing of all ENV VARS present as template in URL as {VAR}
627
+ endpoint_url = replace_with_env_variables(endpoint_url)
607
628
  stac_object.add_link(
608
629
  Link(
609
630
  rel="wms",
610
- target=endpoint_config["EndPoint"],
631
+ target=endpoint_url,
611
632
  media_type=media_type,
612
633
  title=collection_config["Name"],
613
634
  extra_fields=extra_fields,
@@ -88,6 +88,8 @@ def process_catalog_file(file_path: str, options: Options):
88
88
  )
89
89
  else:
90
90
  print(f"Warning: neither collection nor indicator found for {collection}")
91
+ if "MapProjection" in catalog_config:
92
+ catalog.extra_fields["eodash:mapProjection"] = catalog_config["MapProjection"]
91
93
 
92
94
  strategy = TemplateLayoutStrategy(item_template="${collection}/${year}")
93
95
  # expecting that the catalog will be hosted online, self url should correspond to that
@@ -196,64 +198,64 @@ def process_collection_file(
196
198
  with open(file_path) as f:
197
199
  collection_config: dict = yaml.load(f, Loader=SafeLoader)
198
200
  if "Resources" in collection_config:
199
- for resource in collection_config["Resources"]:
201
+ for endpoint_config in collection_config["Resources"]:
200
202
  collection = None
201
- if resource["Name"] == "Sentinel Hub":
203
+ if endpoint_config["Name"] == "Sentinel Hub":
202
204
  collection = handle_SH_endpoint(
203
- catalog_config, resource, collection_config, catalog, options
205
+ catalog_config, endpoint_config, collection_config, catalog, options
204
206
  )
205
- elif resource["Name"] == "Sentinel Hub WMS":
207
+ elif endpoint_config["Name"] == "Sentinel Hub WMS":
206
208
  collection = handle_SH_WMS_endpoint(
207
- catalog_config, resource, collection_config, catalog
209
+ catalog_config, endpoint_config, collection_config, catalog
208
210
  )
209
- elif resource["Name"] == "GeoDB":
211
+ elif endpoint_config["Name"] == "GeoDB":
210
212
  collection = handle_GeoDB_endpoint(
211
- catalog_config, resource, collection_config, catalog
213
+ catalog_config, endpoint_config, collection_config, catalog
212
214
  )
213
- elif resource["Name"] == "VEDA":
215
+ elif endpoint_config["Name"] == "VEDA":
214
216
  collection = handle_VEDA_endpoint(
215
- catalog_config, resource, collection_config, catalog, options
217
+ catalog_config, endpoint_config, collection_config, catalog, options
216
218
  )
217
- elif resource["Name"] == "marinedatastore":
219
+ elif endpoint_config["Name"] == "marinedatastore":
218
220
  collection = handle_WMS_endpoint(
219
- catalog_config, resource, collection_config, catalog, wmts=True
221
+ catalog_config, endpoint_config, collection_config, catalog, wmts=True
220
222
  )
221
- elif resource["Name"] == "xcube":
223
+ elif endpoint_config["Name"] == "xcube":
222
224
  collection = handle_xcube_endpoint(
223
- catalog_config, resource, collection_config, catalog
225
+ catalog_config, endpoint_config, collection_config, catalog
224
226
  )
225
- elif resource["Name"] == "WMS":
227
+ elif endpoint_config["Name"] == "WMS":
226
228
  collection = handle_WMS_endpoint(
227
- catalog_config, resource, collection_config, catalog
229
+ catalog_config, endpoint_config, collection_config, catalog
228
230
  )
229
- elif resource["Name"] == "JAXA_WMTS_PALSAR":
231
+ elif endpoint_config["Name"] == "JAXA_WMTS_PALSAR":
230
232
  # somewhat one off creation of individual WMTS layers as individual items
231
233
  collection = handle_WMS_endpoint(
232
- catalog_config, resource, collection_config, catalog, wmts=True
234
+ catalog_config, endpoint_config, collection_config, catalog, wmts=True
233
235
  )
234
- elif resource["Name"] == "Collection-only":
236
+ elif endpoint_config["Name"] == "Collection-only":
235
237
  collection = handle_collection_only(
236
- catalog_config, resource, collection_config, catalog
238
+ catalog_config, endpoint_config, collection_config, catalog
237
239
  )
238
- elif resource["Name"] == "Custom-Endpoint":
240
+ elif endpoint_config["Name"] == "Custom-Endpoint":
239
241
  collection = handle_custom_endpoint(
240
242
  catalog_config,
241
- resource,
243
+ endpoint_config,
242
244
  collection_config,
243
245
  catalog,
244
246
  )
245
- elif resource["Name"] in ["COG source", "GeoJSON source"]:
247
+ elif endpoint_config["Name"] in ["COG source", "GeoJSON source"]:
246
248
  collection = handle_raw_source(
247
- catalog_config, resource, collection_config, catalog
249
+ catalog_config, endpoint_config, collection_config, catalog
248
250
  )
249
251
  else:
250
252
  raise ValueError("Type of Resource is not supported")
251
253
  if collection:
252
254
  add_single_item_if_collection_empty(collection)
253
- add_projection_info(resource, collection)
254
- add_to_catalog(collection, catalog, resource, collection_config)
255
+ add_projection_info(endpoint_config, collection)
256
+ add_to_catalog(collection, catalog, endpoint_config, collection_config)
255
257
  else:
256
- raise Exception(f"No collection was generated for resource {resource}")
258
+ raise Exception(f"No collection was generated for resource {endpoint_config}")
257
259
  elif "Subcollections" in collection_config:
258
260
  # if no endpoint is specified we check for definition of subcollections
259
261
  parent_collection = get_or_create_collection(
@@ -4,12 +4,18 @@ from oauthlib.oauth2 import BackendApplicationClient
4
4
  from requests_oauthlib import OAuth2Session
5
5
 
6
6
  SH_TOKEN_URL = "https://services.sentinel-hub.com/oauth/token"
7
+ _token_cache: dict[str, str] = {}
7
8
 
8
9
 
9
- def get_SH_token() -> str:
10
+ def get_SH_token(endpoint_config: dict) -> str:
10
11
  # Your client credentials
11
- client_id = os.getenv("SH_CLIENT_ID")
12
- client_secret = os.getenv("SH_CLIENT_SECRET")
12
+ client_id = os.getenv("SH_CLIENT_ID", "")
13
+ client_secret = os.getenv("SH_CLIENT_SECRET", "")
14
+ if env_id := endpoint_config.get("CustomSHEnvId"):
15
+ client_id = os.getenv(f"SH_CLIENT_ID_{env_id}", "")
16
+ client_secret = os.getenv(f"SH_CLIENT_SECRET_{env_id}", "")
17
+ if client_id in _token_cache:
18
+ return _token_cache[client_id]
13
19
  # Create a session
14
20
  client = BackendApplicationClient(client_id=client_id)
15
21
  oauth = OAuth2Session(client=client)
@@ -18,5 +24,7 @@ def get_SH_token() -> str:
18
24
  token_url=SH_TOKEN_URL,
19
25
  client_secret=client_secret,
20
26
  )
27
+ access_token = token["access_token"]
28
+ _token_cache[client_id] = access_token
21
29
 
22
- return token["access_token"]
30
+ return access_token
@@ -347,7 +347,7 @@ def add_base_overlay_info(
347
347
  collection.add_link(create_web_map_link(layer, role="overlay"))
348
348
 
349
349
 
350
- def add_extra_fields(stac_object: Collection | Catalog | Link, collection_config: dict) -> None:
350
+ def add_extra_fields(stac_object: Collection | Link, collection_config: dict) -> None:
351
351
  if "yAxis" in collection_config:
352
352
  stac_object.extra_fields["yAxis"] = collection_config["yAxis"]
353
353
  if "Themes" in collection_config:
@@ -379,7 +379,7 @@ def add_extra_fields(stac_object: Collection | Catalog | Link, collection_config
379
379
  if "Other" in collection_config["DataSource"]:
380
380
  stac_object.extra_fields["otherSources"] = collection_config["DataSource"]["Other"]
381
381
  if "MapProjection" in collection_config:
382
- stac_object.extra_fields["mapProjection"] = collection_config["MapProjection"]
382
+ stac_object.extra_fields["eodash:mapProjection"] = collection_config["MapProjection"]
383
383
 
384
384
 
385
385
  def get_collection_times_from_config(endpoint_config: dict) -> list[str]:
@@ -416,6 +416,6 @@ def add_projection_info(
416
416
  # so we are taking over the DataProjection as is and deal with it in the eodash client
417
417
  # in a non-standard compliant way
418
418
  # https://github.com/proj4js/proj4js/issues/400
419
- stac_object.extra_fields["proj4_def"] = proj
419
+ stac_object.extra_fields["eodash:proj4_def"] = proj
420
420
  else:
421
421
  raise Exception(f"Incorrect type of proj definition {proj}")
eodash_catalog/utils.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import re
2
3
  import threading
3
4
  import uuid
@@ -252,3 +253,18 @@ def add_single_item_if_collection_empty(collection: Collection) -> None:
252
253
  end_datetime=datetime.now(),
253
254
  )
254
255
  collection.add_item(item)
256
+
257
+
258
+ def replace_with_env_variables(s: str) -> str:
259
+ # Define the regex pattern to find text within curly brackets
260
+ pattern = r"\{(\w+)\}"
261
+
262
+ # Define the replacement function
263
+ def replacer(match):
264
+ # Extract the variable name from the match
265
+ var_name = match.group(1)
266
+ # Get the environment variable value, if it doesn't exist, keep the original placeholder
267
+ return os.getenv(var_name, match.group(0))
268
+
269
+ # Use re.sub with the replacement function
270
+ return re.sub(pattern, replacer, s)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: eodash_catalog
3
- Version: 0.0.16
3
+ Version: 0.0.18
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
@@ -0,0 +1,14 @@
1
+ eodash_catalog/__about__.py,sha256=qhKAhTix1N8_dYJ9ebFANzydGLRaBuHbCEZSda-fBeE,138
2
+ eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
+ eodash_catalog/duration.py,sha256=B6XOZfvNU7SuqpxuVtT1kNKODoOQJXDI6mocvA_U1ik,10816
4
+ eodash_catalog/endpoints.py,sha256=hL9rxeGcBpRr6wj6lcKxX7NtkLjP1auzwnt7zJjYVUo,33714
5
+ eodash_catalog/generate_indicators.py,sha256=Fxq3sAXzZaPpE_RhiyFlnIvUBmf17tVFpoN2R_xLFGM,19109
6
+ eodash_catalog/sh_endpoint.py,sha256=F99LpYT-MGhPiwdSSysm3xBTjaQBXRUkieh-q-vhTvE,1012
7
+ eodash_catalog/stac_handling.py,sha256=sN-B2jTQZyQFhs7nvszI5n3qvsHqKoAXbxjyIaHpQmM,18201
8
+ eodash_catalog/thumbnails.py,sha256=31Wk38oNQDxfhSUbMLBpHuZFhsR8v_7luYr65XQtDf0,2213
9
+ eodash_catalog/utils.py,sha256=44V-Pm9tl70nWahMPE4vl-9FzZbRkMVRQPdINdG_8F8,8975
10
+ eodash_catalog-0.0.18.dist-info/METADATA,sha256=N-kEMopvt8_0J_3S2a9tRFCNZKKuXWm5abbidXMO7SY,3203
11
+ eodash_catalog-0.0.18.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
12
+ eodash_catalog-0.0.18.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
13
+ eodash_catalog-0.0.18.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
14
+ eodash_catalog-0.0.18.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- eodash_catalog/__about__.py,sha256=DufokORcq7HQve6GPFansFU8LMELcmOjGhPms7LOjFM,138
2
- eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
- eodash_catalog/duration.py,sha256=B6XOZfvNU7SuqpxuVtT1kNKODoOQJXDI6mocvA_U1ik,10816
4
- eodash_catalog/endpoints.py,sha256=0cCwNbQ1YqH8zKxdPY2LvXZWXqmqrAuW6ae_mUK4nTE,32734
5
- eodash_catalog/generate_indicators.py,sha256=DlbgMuNVPGdg8roYO7raXIeTmsMRpsyN71DYnRATATI,18790
6
- eodash_catalog/sh_endpoint.py,sha256=vELooJwk269v1DNnOzb32vil96vL_SRCio8UBlx10N0,618
7
- eodash_catalog/stac_handling.py,sha256=BKFFhM2JhrBnEd6EbEESAIUcFncDaAb5N4aHx0uZBv4,18197
8
- eodash_catalog/thumbnails.py,sha256=31Wk38oNQDxfhSUbMLBpHuZFhsR8v_7luYr65XQtDf0,2213
9
- eodash_catalog/utils.py,sha256=4qcCADoIs6woJoqd553j_qT5mLb7_wl6NAUN_BoJ3jE,8438
10
- eodash_catalog-0.0.16.dist-info/METADATA,sha256=PqIbwvI4nxwpPpXICYWWYhwti33D9NKu77nu0gjXXQU,3203
11
- eodash_catalog-0.0.16.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
12
- eodash_catalog-0.0.16.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
13
- eodash_catalog-0.0.16.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
14
- eodash_catalog-0.0.16.dist-info/RECORD,,