Skip to content

Commit 37141f6

Browse files
Allow anonymous access to open data datasets
1 parent ef6c252 commit 37141f6

9 files changed

Lines changed: 872 additions & 777 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repos:
99
hooks:
1010
- id: sync-with-uv
1111
- repo: https://github.com/charliermarsh/ruff-pre-commit
12-
rev: v0.14.14
12+
rev: v0.15.7
1313
hooks:
1414
- id: ruff-check
1515
args: [--fix, --exit-non-zero-on-fix]

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.50.1] - 2026-03-31
11+
12+
### Added
13+
14+
- `tilebox-datasets`: Allow anonymous access to open data datasets.
15+
1016
## [0.50.0] - 2026-03-06
1117

1218
### Added
@@ -342,6 +348,7 @@ the first client that does not cache data (since it's already on the local file
342348
- Released packages: `tilebox-datasets`, `tilebox-workflows`, `tilebox-storage`, `tilebox-grpc`
343349

344350
[Unreleased]: https://github.com/tilebox/tilebox-python/compare/v0.50.0...HEAD
351+
[0.50.1]: https://github.com/tilebox/tilebox-python/compare/v0.50.0...v0.50.1
345352
[0.50.0]: https://github.com/tilebox/tilebox-python/compare/v0.49.0...v0.50.0
346353
[0.49.0]: https://github.com/tilebox/tilebox-python/compare/v0.48.0...v0.49.0
347354
[0.48.0]: https://github.com/tilebox/tilebox-python/compare/v0.47.0...v0.48.0

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ dev = [
2626
"ruff>=0.14.10",
2727
"types-protobuf>=6.30",
2828
"junitparser>=3.2.0",
29-
"ty>=0.0.14",
29+
# https://github.com/astral-sh/ty/issues/2759
30+
"ty==0.0.14",
3031
"prek>=0.2.27",
3132
]
3233

@@ -116,5 +117,5 @@ exclude = [
116117
# auto-generated code
117118
"**/*_pb2.py",
118119
"**/*_pb2.pyi",
119-
"**/*pb2_grpc.py"
120+
"**/*pb2_grpc.py",
120121
]

tilebox-datasets/tilebox/datasets/aio/client.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import os
12
from uuid import UUID
23

4+
from loguru import logger
5+
36
from _tilebox.grpc.aio.channel import open_channel
47
from _tilebox.grpc.aio.error import with_pythonic_errors
58
from _tilebox.grpc.error import NotFoundError
69
from tilebox.datasets.aio.dataset import DatasetClient
10+
from tilebox.datasets.client import _TILEBOX_API_KEY_ENV_VAR, _TILEBOX_API_URL
711
from tilebox.datasets.client import Client as BaseClient
8-
from tilebox.datasets.client import token_from_env
912
from tilebox.datasets.data.datasets import DatasetKind, FieldDict
1013
from tilebox.datasets.datasets.v1.collections_pb2_grpc import CollectionServiceStub
1114
from tilebox.datasets.datasets.v1.data_access_pb2_grpc import DataAccessServiceStub
@@ -16,15 +19,31 @@
1619

1720

1821
class Client:
19-
def __init__(self, *, url: str = "https://api.tilebox.com", token: str | None = None) -> None:
22+
def __init__(
23+
self, *, url: str = _TILEBOX_API_URL, token: str | None = None, warn_if_unauthenticated: bool = True
24+
) -> None:
2025
"""
2126
Create a Tilebox datasets client.
2227
2328
Args:
2429
url: Tilebox API Url. Defaults to "https://api.tilebox.com".
2530
token: The API Key to authenticate with. If not set the `TILEBOX_API_KEY` environment variable will be used.
31+
If no token is provided or found, anonymous open data access will be used.
32+
warn_if_unauthenticated: Whether to warn if no API key is provided and the client is used with the default
33+
Tilebox API URL. Defaults to True.
2634
"""
27-
channel = open_channel(url, token_from_env(url, token))
35+
if token is None:
36+
token = os.environ.get(_TILEBOX_API_KEY_ENV_VAR, None)
37+
38+
if token is None and url == _TILEBOX_API_URL and warn_if_unauthenticated:
39+
logger.opt(colors=True).info(
40+
"<yellow>"
41+
"No Tilebox API key detected. Using anonymous Open Data access without authentication. "
42+
"For higher throughput and rate limits, sign up for a free Tilebox at https://console.tilebox.com."
43+
"</yellow>"
44+
)
45+
46+
channel = open_channel(url, token)
2847
dataset_service_stub = with_pythonic_errors(DatasetServiceStub(channel))
2948
collection_service_stub = with_pythonic_errors(CollectionServiceStub(channel))
3049
data_access_service_stub = with_pythonic_errors(DataAccessServiceStub(channel))

tilebox-datasets/tilebox/datasets/client.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from loguru import logger
77
from promise import Promise
88

9-
from _tilebox.grpc.channel import parse_channel_info
109
from tilebox.datasets.data.datasets import Dataset, DatasetGroup, DatasetKind, FieldDict, ListDatasetsResponse
1110
from tilebox.datasets.group import Group
1211
from tilebox.datasets.message_pool import register_once
1312
from tilebox.datasets.service import TileboxDatasetService
1413
from tilebox.datasets.uuid import as_uuid
1514

15+
_TILEBOX_API_URL = "https://api.tilebox.com"
16+
_TILEBOX_API_KEY_ENV_VAR = "TILEBOX_API_KEY"
17+
1618

1719
class TimeseriesDatasetLike(Protocol):
1820
def __init__(self, service: TileboxDatasetService, dataset: Dataset) -> None:
@@ -81,19 +83,6 @@ def _dataset_by_id(self, dataset_id: str | UUID, dataset_type: type[T]) -> Promi
8183
)
8284

8385

84-
def token_from_env(url: str, token: str | None) -> str | None:
85-
if token is None: # if no token is provided, try to get it from the environment
86-
token = os.environ.get("TILEBOX_API_KEY", None)
87-
88-
if token is None and parse_channel_info(url).address == "api.tilebox.com":
89-
raise ValueError(
90-
"No API key provided and no TILEBOX_API_KEY environment variable set. Please specify an API key using "
91-
"the token argument. For example: `Client(token='YOUR_TILEBOX_API_KEY')`"
92-
)
93-
94-
return token
95-
96-
9786
def _log_server_message(response: ListDatasetsResponse) -> ListDatasetsResponse:
9887
if response.server_message:
9988
logger.opt(colors=True).info(response.server_message + "\n")

tilebox-datasets/tilebox/datasets/sync/client.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import os
12
from uuid import UUID
23

4+
from loguru import logger
5+
36
from _tilebox.grpc.channel import open_channel
47
from _tilebox.grpc.error import NotFoundError, with_pythonic_errors
8+
from tilebox.datasets.client import _TILEBOX_API_KEY_ENV_VAR, _TILEBOX_API_URL
59
from tilebox.datasets.client import Client as BaseClient
6-
from tilebox.datasets.client import token_from_env
710
from tilebox.datasets.data.datasets import DatasetKind, FieldDict
811
from tilebox.datasets.datasets.v1.collections_pb2_grpc import CollectionServiceStub
912
from tilebox.datasets.datasets.v1.data_access_pb2_grpc import DataAccessServiceStub
@@ -15,15 +18,31 @@
1518

1619

1720
class Client:
18-
def __init__(self, *, url: str = "https://api.tilebox.com", token: str | None = None) -> None:
21+
def __init__(
22+
self, *, url: str = _TILEBOX_API_URL, token: str | None = None, warn_if_unauthenticated: bool = True
23+
) -> None:
1924
"""
2025
Create a Tilebox datasets client.
2126
2227
Args:
2328
url: Tilebox API Url. Defaults to "https://api.tilebox.com".
2429
token: The API Key to authenticate with. If not set the `TILEBOX_API_KEY` environment variable will be used.
30+
If no token is provided or found, anonymous open data access will be used.
31+
warn_if_unauthenticated: Whether to warn if no API key is provided and the client is used with the default
32+
Tilebox API URL. Defaults to True.
2533
"""
26-
channel = open_channel(url, token_from_env(url, token))
34+
if token is None:
35+
token = os.environ.get(_TILEBOX_API_KEY_ENV_VAR, None)
36+
37+
if token is None and url == _TILEBOX_API_URL and warn_if_unauthenticated:
38+
logger.opt(colors=True).info(
39+
"<yellow>"
40+
"No Tilebox API key detected. Using anonymous Open Data access without authentication. "
41+
"For higher throughput and rate limits, sign up for a free Tilebox at https://console.tilebox.com."
42+
"</yellow>"
43+
)
44+
45+
channel = open_channel(url, token)
2746
dataset_service_stub = with_pythonic_errors(DatasetServiceStub(channel))
2847
collection_service_stub = with_pythonic_errors(CollectionServiceStub(channel))
2948
data_access_service_stub = with_pythonic_errors(DataAccessServiceStub(channel))

tilebox-workflows/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies = [
3232
"boto3-stubs[essential]>=1.33",
3333
"ipywidgets>=8.1.7",
3434
"python-dateutil>=2.9.0.post0",
35+
"obstore>=0.8.2",
3536
]
3637

3738
[dependency-groups]

tilebox-workflows/tilebox/workflows/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def runner(
104104
runner_context_type = context or RunnerContext
105105
runner_context = runner_context_type(
106106
tracer._tracer, # noqa: SLF001
107-
datasets_client=DatasetsClient(**self._auth),
107+
datasets_client=DatasetsClient(**self._auth), # ty: ignore[invalid-argument-type]
108108
storage_locations=storage_locations,
109109
)
110110

0 commit comments

Comments
 (0)