eodash_catalog 0.3.11__py3-none-any.whl → 0.3.12__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.3.11"
4
+ __version__ = "0.3.12"
@@ -9,6 +9,7 @@ from collections.abc import Callable
9
9
  from datetime import datetime, timedelta
10
10
  from itertools import groupby
11
11
  from operator import itemgetter
12
+ from urllib.parse import urlparse
12
13
 
13
14
  import pyarrow.parquet as pq
14
15
  import requests
@@ -20,6 +21,7 @@ from structlog import get_logger
20
21
 
21
22
  from eodash_catalog.sh_endpoint import get_SH_token
22
23
  from eodash_catalog.stac_handling import (
24
+ add_authentication,
23
25
  add_base_overlay_info,
24
26
  add_collection_information,
25
27
  add_example_info,
@@ -954,7 +956,8 @@ def handle_SH_endpoint(
954
956
  ) -> Collection:
955
957
  token = get_SH_token(endpoint_config)
956
958
  headers = {"Authorization": f"Bearer {token}"}
957
- endpoint_config["EndPoint"] = "https://services.sentinel-hub.com/api/v1/catalog/1.0.0/"
959
+ endpoint_url_parts = urlparse(endpoint_config["EndPoint"])
960
+ endpoint_config["EndPoint"] = f"https://{endpoint_url_parts.netloc}/api/v1/catalog/1.0.0/"
958
961
  # Overwrite collection id with type, such as ZARR or BYOC
959
962
  if endpoint_config.get("Type"):
960
963
  endpoint_config["CollectionId"] = (
@@ -1121,9 +1124,10 @@ def add_visualization_info(
1121
1124
 
1122
1125
  if dimensions != {}:
1123
1126
  extra_fields["wms:dimensions"] = dimensions
1127
+ endpoint_url_parts = urlparse(endpoint_config["EndPoint"])
1124
1128
  link = Link(
1125
1129
  rel="wms",
1126
- target=f"https://services.sentinel-hub.com/ogc/wms/{instanceId}",
1130
+ target=f"https://{endpoint_url_parts.netloc}/ogc/wms/{instanceId}",
1127
1131
  media_type=(endpoint_config.get("MimeType", "image/png")),
1128
1132
  title=collection_config["Name"],
1129
1133
  extra_fields=extra_fields,
@@ -1493,3 +1497,88 @@ def handle_raw_source(
1493
1497
 
1494
1498
  add_collection_information(catalog_config, collection, collection_config)
1495
1499
  return collection
1500
+
1501
+
1502
+ def handle_vector_tile_source(
1503
+ catalog_config: dict,
1504
+ endpoint_config: dict,
1505
+ collection_config: dict,
1506
+ coll_path_rel_to_root_catalog: str,
1507
+ catalog: Catalog,
1508
+ options: Options,
1509
+ ) -> Collection:
1510
+ collection = get_or_create_collection(
1511
+ catalog, collection_config["Name"], collection_config, catalog_config, endpoint_config
1512
+ )
1513
+ coll_path_rel_to_root_catalog = f'{coll_path_rel_to_root_catalog}/{collection_config["Name"]}'
1514
+ if len(endpoint_config.get("TimeEntries", [])) > 0:
1515
+ items = []
1516
+ style_link = None
1517
+ for time_entry in endpoint_config["TimeEntries"]:
1518
+ # create Item for each time entry
1519
+ media_type = "application/vnd.mapbox-vector-tile"
1520
+ style_type = "text/vector-styles"
1521
+ bbox = endpoint_config.get("Bbox", [-180, -85, 180, 85])
1522
+ dt = parse_datestring_to_tz_aware_datetime(time_entry["Time"])
1523
+
1524
+ item = Item(
1525
+ id=format_datetime_to_isostring_zulu(dt),
1526
+ bbox=bbox,
1527
+ properties={},
1528
+ geometry=create_geometry_from_bbox(bbox),
1529
+ datetime=dt,
1530
+ extra_fields={},
1531
+ )
1532
+ extra_fields_link = {}
1533
+ add_authentication(item, time_entry["Url"], extra_fields_link)
1534
+ # add mapbox vector tile link
1535
+ identifier = uuid.uuid4()
1536
+ extra_fields_link["key"] = identifier
1537
+ link = Link(
1538
+ rel="vector-tile",
1539
+ target=time_entry["Url"],
1540
+ media_type=media_type,
1541
+ title=collection_config["Name"],
1542
+ extra_fields=extra_fields_link,
1543
+ )
1544
+ add_projection_info(
1545
+ endpoint_config,
1546
+ link,
1547
+ )
1548
+ item.add_link(link)
1549
+ add_projection_info(
1550
+ endpoint_config,
1551
+ item,
1552
+ )
1553
+ if endpoint_config.get("Attribution"):
1554
+ item.stac_extensions.append(
1555
+ "https://stac-extensions.github.io/attribution/v0.1.0/schema.json"
1556
+ )
1557
+ item.extra_fields["attribution"] = endpoint_config["Attribution"]
1558
+ # add style
1559
+ if ep_st := endpoint_config.get("Style"):
1560
+ style_link = Link(
1561
+ rel="style",
1562
+ target=ep_st
1563
+ if ep_st.startswith("http")
1564
+ else f"{catalog_config['assets_endpoint']}/{ep_st}",
1565
+ media_type=style_type,
1566
+ extra_fields={"links:keys": [identifier]},
1567
+ )
1568
+ item.add_link(style_link)
1569
+ items.append(item)
1570
+
1571
+ save_items(
1572
+ collection,
1573
+ items,
1574
+ options.outputpath,
1575
+ catalog_config["id"],
1576
+ coll_path_rel_to_root_catalog,
1577
+ options.gp,
1578
+ )
1579
+
1580
+ else:
1581
+ LOGGER.warn(f"NO datetimes configured for collection: {collection_config['Name']}!")
1582
+
1583
+ add_collection_information(catalog_config, collection, collection_config)
1584
+ return collection
@@ -24,6 +24,7 @@ from eodash_catalog.endpoints import (
24
24
  handle_raw_source,
25
25
  handle_SH_endpoint,
26
26
  handle_SH_WMS_endpoint,
27
+ handle_vector_tile_source,
27
28
  handle_VEDA_endpoint,
28
29
  handle_WMS_endpoint,
29
30
  handle_xcube_endpoint,
@@ -292,6 +293,15 @@ def process_collection_file(
292
293
  catalog,
293
294
  options,
294
295
  )
296
+ elif endpoint_config["Name"] == "VectorTile source":
297
+ collection = handle_vector_tile_source(
298
+ catalog_config,
299
+ endpoint_config,
300
+ collection_config,
301
+ coll_path_rel_to_root_catalog,
302
+ catalog,
303
+ options,
304
+ )
295
305
  elif endpoint_config["Name"] == "JAXA_WMTS_PALSAR":
296
306
  # somewhat one off creation of individual WMTS layers as individual items
297
307
  collection = handle_WMS_endpoint(
@@ -360,9 +370,11 @@ def process_collection_file(
360
370
  countries.extend(sub_coll_def["Country"])
361
371
  else:
362
372
  countries.append(sub_coll_def["Country"])
363
- coll_path_rel_to_root_catalog = (
364
- f"{coll_path_rel_to_root_catalog}/{sub_coll_def['Collection']}"
365
- )
373
+ # commented out intentionally, because otherwise paths further down did
374
+ # not match, parquet file was one level deeper
375
+ # coll_path_rel_to_root_catalog = (
376
+ # f"{coll_path_rel_to_root_catalog}/{sub_coll_def['Collection']}"
377
+ # )
366
378
  process_collection_file(
367
379
  catalog_config,
368
380
  "{}/{}".format(options.collectionspath, sub_coll_def["Collection"]),
@@ -1,10 +1,10 @@
1
1
  import os
2
2
  import time
3
+ from urllib.parse import urlparse
3
4
 
4
5
  from oauthlib.oauth2 import BackendApplicationClient
5
6
  from requests_oauthlib import OAuth2Session
6
7
 
7
- SH_TOKEN_URL = "https://services.sentinel-hub.com/oauth/token"
8
8
  _token_cache: dict[str, dict] = {}
9
9
 
10
10
 
@@ -24,6 +24,8 @@ def get_SH_token(endpoint_config: dict) -> str:
24
24
  client = BackendApplicationClient(client_id=client_id)
25
25
  oauth = OAuth2Session(client=client)
26
26
  # Get token for the session
27
+ endpoint_url_parts = urlparse(endpoint_config["EndPoint"])
28
+ SH_TOKEN_URL = f"https://{endpoint_url_parts.netloc}/oauth/token"
27
29
  token = oauth.fetch_token(
28
30
  token_url=SH_TOKEN_URL,
29
31
  client_secret=client_secret,
@@ -1,3 +1,4 @@
1
+ import uuid
1
2
  from datetime import datetime, timezone
2
3
 
3
4
  import requests
@@ -122,11 +123,14 @@ def create_service_link(endpoint_config: dict, catalog_config: dict) -> Link:
122
123
  return sl
123
124
 
124
125
 
125
- def create_web_map_link(layer_config: dict, role: str) -> Link:
126
+ def create_web_map_link(
127
+ collection: Collection, catalog_config: dict, layer_config: dict, role: str
128
+ ) -> Link:
126
129
  extra_fields = {
127
130
  "roles": [role],
128
131
  "id": layer_config["id"],
129
132
  }
133
+ media_type = (layer_config.get("media_type", "image/png"),)
130
134
  if layer_config.get("default"):
131
135
  extra_fields["roles"].append("default")
132
136
  if layer_config.get("visible"):
@@ -146,12 +150,30 @@ def create_web_map_link(layer_config: dict, role: str) -> Link:
146
150
  extra_fields["wmts:layer"] = layer_config["layer"]
147
151
  if layer_config.get("dimensions"):
148
152
  extra_fields["wmts:dimensions"] = layer_config["dimensions"]
153
+ case "vector-tile":
154
+ identifier = uuid.uuid4()
155
+ extra_fields["key"] = identifier
156
+ media_type = "application/vnd.mapbox-vector-tile"
157
+ if ep_st := layer_config.get("Style"):
158
+ style_link = Link(
159
+ rel="style",
160
+ target=ep_st
161
+ if ep_st.startswith("http")
162
+ else f"{catalog_config['assets_endpoint']}/{ep_st}",
163
+ media_type="text/vector-styles",
164
+ extra_fields={"links:keys": [identifier]},
165
+ )
166
+ collection.add_link(style_link)
167
+ add_authentication(collection, layer_config["url"], extra_fields)
168
+
149
169
  if layer_config.get("Attribution"):
150
170
  extra_fields["attribution"] = layer_config["Attribution"]
171
+ if layer_config.get("Colorlegend"):
172
+ extra_fields["eox:colorlegend"] = layer_config["Colorlegend"]
151
173
  wml = Link(
152
174
  rel=layer_config["protocol"],
153
175
  target=layer_config["url"],
154
- media_type=layer_config.get("media_type", "image/png"),
176
+ media_type=media_type,
155
177
  title=layer_config["name"],
156
178
  extra_fields=extra_fields,
157
179
  )
@@ -321,7 +343,7 @@ def add_collection_information(
321
343
  ),
322
344
  )
323
345
  # Bubble up thumbnail to extra fields
324
- collection.extra_fields["thumbnail"] = (image_url)
346
+ collection.extra_fields["thumbnail"] = image_url
325
347
  # Add extra fields to collection if available
326
348
  add_extra_fields(collection, collection_config, is_root_collection)
327
349
 
@@ -478,21 +500,29 @@ def add_base_overlay_info(
478
500
  # add custom baselayers specially for this indicator
479
501
  if "BaseLayers" in collection_config:
480
502
  for layer in collection_config["BaseLayers"]:
481
- collection.add_link(create_web_map_link(layer, role="baselayer"))
503
+ collection.add_link(
504
+ create_web_map_link(collection, catalog_config, layer, role="baselayer")
505
+ )
482
506
  # alternatively use default base layers defined
483
507
  elif catalog_config.get("default_base_layers"):
484
508
  base_layers = read_config_file(catalog_config["default_base_layers"])
485
509
  for layer in base_layers:
486
- collection.add_link(create_web_map_link(layer, role="baselayer"))
510
+ collection.add_link(
511
+ create_web_map_link(collection, catalog_config, layer, role="baselayer")
512
+ )
487
513
  # add custom overlays just for this indicator
488
514
  if "OverlayLayers" in collection_config:
489
515
  for layer in collection_config["OverlayLayers"]:
490
- collection.add_link(create_web_map_link(layer, role="overlay"))
516
+ collection.add_link(
517
+ create_web_map_link(collection, catalog_config, layer, role="overlay")
518
+ )
491
519
  # check if default overlay layers defined
492
520
  elif catalog_config.get("default_overlay_layers"):
493
521
  overlay_layers = read_config_file(catalog_config["default_overlay_layers"])
494
522
  for layer in overlay_layers:
495
- collection.add_link(create_web_map_link(layer, role="overlay"))
523
+ collection.add_link(
524
+ create_web_map_link(collection, catalog_config, layer, role="overlay")
525
+ )
496
526
 
497
527
 
498
528
  def add_extra_fields(
@@ -582,3 +612,20 @@ def add_projection_info(
582
612
  stac_object.extra_fields["eodash:proj4_def"] = proj
583
613
  else:
584
614
  raise Exception(f"Incorrect type of proj definition {proj}")
615
+
616
+
617
+ def add_authentication(stac_object: Item | Collection | Catalog, url: str, extra_fields_link: dict):
618
+ if "api.mapbox" in url:
619
+ # add authentication info
620
+ auth_extension = "https://stac-extensions.github.io/authentication/v1.1.0/schema.json"
621
+ if auth_extension not in stac_object.stac_extensions:
622
+ stac_object.stac_extensions.append(auth_extension)
623
+ stac_object.extra_fields["auth:schemes"] = {
624
+ "mapboxauth": {
625
+ "type": "apiKey",
626
+ "name": "access_token",
627
+ "in": "query",
628
+ }
629
+ }
630
+ extra_fields_link["auth:refs"] = ["mapboxauth"]
631
+ pass
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import re
3
3
  from pathlib import Path
4
+ from urllib.parse import urlparse
4
5
 
5
6
  import requests
6
7
  from pystac import (
@@ -46,7 +47,9 @@ def generate_thumbnail(
46
47
  # if it is start and end datetime have to exist
47
48
  if item_datetime:
48
49
  time = format_datetime_to_isostring_zulu(item_datetime)
49
- url = "https://services.sentinel-hub.com/ogc/wms/{}?{}&layers={}&time={}&{}".format(
50
+ endpoint_url_parts = urlparse(endpoint_config["EndPoint"])
51
+ url = "https://{}/ogc/wms/{}?{}&layers={}&time={}&{}".format(
52
+ endpoint_url_parts,
50
53
  instanceId,
51
54
  wms_config,
52
55
  endpoint_config["LayerId"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eodash_catalog
3
- Version: 0.3.11
3
+ Version: 0.3.12
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=G5vHY-bMIsYEXrTXESw19KiOll9bG5vorc426Tn8pas,138
2
+ eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
+ eodash_catalog/duration.py,sha256=TBG7v1lCpbYowADK5uJ2M8kPxsvQneFAFi1NIE26dy4,10754
4
+ eodash_catalog/endpoints.py,sha256=AAKnS0BIReYhcaL8JdB1li1VtkcA4bbHs9wVayFVaQc,65150
5
+ eodash_catalog/generate_indicators.py,sha256=djFmhrP_Nsnl1uC5Nd7CI4KbgRkDipUXAad0B2vC3lI,23002
6
+ eodash_catalog/sh_endpoint.py,sha256=l95NRh__AnpEZBhlzTaGVmBnyX00Sr7RRjwy114nroY,1323
7
+ eodash_catalog/stac_handling.py,sha256=lXMzAHT5L35cbVODQg141hDMRiswx6u6dWoEGy6s_T8,27797
8
+ eodash_catalog/thumbnails.py,sha256=9tPnEdwDaScGCMHpDYXayCnAQYoG_E2oIiBFVGvqOz0,2372
9
+ eodash_catalog/utils.py,sha256=Dv28AYksex7lcRi4f4N3UP5svpv_DIHcFOTRaxd5BKM,24030
10
+ eodash_catalog-0.3.12.dist-info/METADATA,sha256=6_V4cKS-wygwnpcox7Gb7thOhnecaJI9vIBB8Ub3L8o,3020
11
+ eodash_catalog-0.3.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ eodash_catalog-0.3.12.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
13
+ eodash_catalog-0.3.12.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
14
+ eodash_catalog-0.3.12.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- eodash_catalog/__about__.py,sha256=LajdP9481ZMHL4lAF0oVwWRt6euiZPZVjj7SaksVZlM,138
2
- eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
- eodash_catalog/duration.py,sha256=TBG7v1lCpbYowADK5uJ2M8kPxsvQneFAFi1NIE26dy4,10754
4
- eodash_catalog/endpoints.py,sha256=N6THxKvWQ6KbXsjdg_U-oFBkfCHGjRmrSTy4ECrDU2c,61845
5
- eodash_catalog/generate_indicators.py,sha256=YuB_Nsmya9dXzsOdS26LyObfyjKLvfv_B2L6n43z4R4,22418
6
- eodash_catalog/sh_endpoint.py,sha256=XjZsZJ5jfJZLQenSTqUhiUZ5YAu9M9nv2KL1Qv3Be-I,1219
7
- eodash_catalog/stac_handling.py,sha256=4J9Fj135FziMAdzPs2OZgqoI0V7P2wSf_OuEcS66WUQ,25995
8
- eodash_catalog/thumbnails.py,sha256=oNbWdRC8KTLUC4PbSMlSaiOeLXfkIpa0j-sOZdn1RGU,2262
9
- eodash_catalog/utils.py,sha256=Dv28AYksex7lcRi4f4N3UP5svpv_DIHcFOTRaxd5BKM,24030
10
- eodash_catalog-0.3.11.dist-info/METADATA,sha256=2_PRwUW6T7Cw5I0wS97ydj8gMwIE6FSXH4-tAcZNJPk,3020
11
- eodash_catalog-0.3.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- eodash_catalog-0.3.11.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
13
- eodash_catalog-0.3.11.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
14
- eodash_catalog-0.3.11.dist-info/RECORD,,