tilebox-workflows 0.63.0__tar.gz → 0.63.2__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.
Files changed (87) hide show
  1. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/PKG-INFO +1 -1
  2. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/pyproject.toml +2 -0
  3. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/cache.py +77 -5
  4. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/.gitignore +0 -0
  5. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/README.md +0 -0
  6. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/__init__.py +0 -0
  7. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codec.py +0 -0
  8. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/__init__.py +0 -0
  9. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/affine.py +0 -0
  10. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/async_geotiff.py +0 -0
  11. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/odc.py +0 -0
  12. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/pyproj.py +0 -0
  13. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/rasterio.py +0 -0
  14. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/shapely.py +0 -0
  15. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_codecs/tilebox.py +0 -0
  16. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/_serialization.py +0 -0
  17. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/automations/__init__.py +0 -0
  18. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/automations/client.py +0 -0
  19. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/automations/cron.py +0 -0
  20. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/automations/service.py +0 -0
  21. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/automations/storage_event.py +0 -0
  22. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/client.py +0 -0
  23. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/clusters/__init__.py +0 -0
  24. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/clusters/client.py +0 -0
  25. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/clusters/service.py +0 -0
  26. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/data.py +0 -0
  27. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/formatting/__init__.py +0 -0
  28. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/formatting/job.py +0 -0
  29. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/jobs/__init__.py +0 -0
  30. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/jobs/client.py +0 -0
  31. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/jobs/service.py +0 -0
  32. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/jobs/telemetry_service.py +0 -0
  33. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/observability/__init__.py +0 -0
  34. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/observability/_log_pipe.py +0 -0
  35. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/observability/_logging.py +0 -0
  36. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/observability/logging.py +0 -0
  37. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/observability/tracing.py +0 -0
  38. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/__init__.py +0 -0
  39. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/__main__.py +0 -0
  40. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/executor.py +0 -0
  41. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/runner.py +0 -0
  42. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/task_runner.py +0 -0
  43. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/task_service.py +0 -0
  44. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/worker_server.py +0 -0
  45. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/runner/worker_service.py +0 -0
  46. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/task.py +0 -0
  47. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/__init__.py +0 -0
  48. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/client.py +0 -0
  49. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/service.py +0 -0
  50. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/automation_connect.py +0 -0
  51. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/automation_pb2.py +0 -0
  52. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/automation_pb2.pyi +0 -0
  53. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/automation_pb2_grpc.py +0 -0
  54. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/core_pb2.py +0 -0
  55. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/core_pb2.pyi +0 -0
  56. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/core_pb2_grpc.py +0 -0
  57. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/diagram_connect.py +0 -0
  58. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/diagram_pb2.py +0 -0
  59. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/diagram_pb2.pyi +0 -0
  60. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/diagram_pb2_grpc.py +0 -0
  61. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/job_connect.py +0 -0
  62. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/job_pb2.py +0 -0
  63. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/job_pb2.pyi +0 -0
  64. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/job_pb2_grpc.py +0 -0
  65. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/storage_location_connect.py +0 -0
  66. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/storage_location_pb2.py +0 -0
  67. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/storage_location_pb2.pyi +0 -0
  68. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/storage_location_pb2_grpc.py +0 -0
  69. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_connect.py +0 -0
  70. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_pb2.py +0 -0
  71. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_pb2.pyi +0 -0
  72. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_pb2_grpc.py +0 -0
  73. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_release_pb2.py +0 -0
  74. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_release_pb2.pyi +0 -0
  75. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/task_release_pb2_grpc.py +0 -0
  76. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/telemetry_connect.py +0 -0
  77. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/telemetry_pb2.py +0 -0
  78. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/telemetry_pb2.pyi +0 -0
  79. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/telemetry_pb2_grpc.py +0 -0
  80. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/worker_connect.py +0 -0
  81. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/worker_pb2.py +0 -0
  82. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/worker_pb2.pyi +0 -0
  83. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/worker_pb2_grpc.py +0 -0
  84. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/workflows_connect.py +0 -0
  85. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/workflows_pb2.py +0 -0
  86. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/workflows_pb2.pyi +0 -0
  87. {tilebox_workflows-0.63.0 → tilebox_workflows-0.63.2}/tilebox/workflows/workflows/v1/workflows_pb2_grpc.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tilebox-workflows
3
- Version: 0.63.0
3
+ Version: 0.63.2
4
4
  Summary: Workflow client and task runner for Tilebox
5
5
  Project-URL: Homepage, https://tilebox.com
6
6
  Project-URL: Documentation, https://docs.tilebox.com/workflows/introduction
@@ -50,6 +50,8 @@ geospatial = [
50
50
  [dependency-groups]
51
51
  dev = [
52
52
  "boto3-stubs[s3]>=1.40.2",
53
+ "google-cloud-storage>=3.2.0",
54
+ "grpcio-status>=1.78.0",
53
55
  "hypothesis>=6.112.1",
54
56
  "ipywidgets>=8.1.7",
55
57
  "odc-geo>=0.5",
@@ -1,10 +1,12 @@
1
1
  import contextlib
2
2
  from abc import ABC, abstractmethod
3
- from collections.abc import Iterator
3
+ from collections.abc import Iterable, Iterator
4
+ from copy import copy
5
+ from io import BytesIO
4
6
  from pathlib import Path
5
7
  from pathlib import PurePosixPath as ObjectPath
6
8
  from threading import RLock
7
- from typing import TYPE_CHECKING, Any
9
+ from typing import TYPE_CHECKING, Any, Generic, Protocol, Self, TypeVar
8
10
 
9
11
  if TYPE_CHECKING:
10
12
  from obstore.store import ObjectStore
@@ -257,14 +259,37 @@ class LocalFileSystemCache(JobCache):
257
259
  return LocalFileSystemCache(self.root / key)
258
260
 
259
261
 
260
- class GoogleStorageCache(ObstoreCache):
261
- def __init__(self, bucket: str, prefix: str | ObjectPath = "jobs") -> None:
262
+ class _GoogleBlob(Protocol):
263
+ @property
264
+ def name(self) -> str: ...
265
+ def exists(self) -> bool: ...
266
+ def upload_from_file(self, stream: BytesIO, /) -> None: ...
267
+ def download_as_bytes(self) -> bytes: ...
268
+ def delete(self) -> None: ...
269
+
270
+
271
+ class _GoogleBucket(Protocol):
272
+ def blob(self, name: str, /) -> _GoogleBlob: ...
273
+ def list_blobs(self, *, prefix: str, delimiter: str) -> Iterable[_GoogleBlob]: ...
274
+
275
+
276
+ _BucketT = TypeVar("_BucketT", bound=str | _GoogleBucket)
277
+
278
+
279
+ class GoogleStorageCache(ObstoreCache, Generic[_BucketT]):
280
+ def __init__(self, bucket: _BucketT, prefix: str | ObjectPath = "jobs") -> None:
262
281
  """A cache implementation that stores data in Google Cloud Storage.
263
282
 
264
283
  Args:
265
- bucket: The Google Cloud Storage bucket name. Credentials come from Google Auth.
284
+ bucket: A bucket name or Google SDK Bucket. Names use obstore and Google Auth;
285
+ Bucket objects keep their existing client and its configuration.
266
286
  prefix: A path prefix to append to all objects stored in the cache. Defaults to "jobs".
267
287
  """
288
+ self.bucket = bucket
289
+ if not isinstance(bucket, str):
290
+ self.prefix = ObjectPath(prefix)
291
+ return
292
+
268
293
  import google.auth # noqa: PLC0415
269
294
  from obstore.auth.google import GoogleCredentialProvider # noqa: PLC0415
270
295
  from obstore.store import GCSStore # noqa: PLC0415
@@ -273,6 +298,53 @@ class GoogleStorageCache(ObstoreCache):
273
298
  store = GCSStore(bucket, credential_provider=GoogleCredentialProvider(credentials=credentials))
274
299
  super().__init__(store, prefix)
275
300
 
301
+ def __contains__(self, key: str) -> bool:
302
+ if isinstance(self.bucket, str):
303
+ return super().__contains__(key)
304
+ return self.bucket.blob(str(self.prefix / key)).exists()
305
+
306
+ def __setitem__(self, key: str, value: bytes) -> None:
307
+ if isinstance(self.bucket, str):
308
+ super().__setitem__(key, value)
309
+ else:
310
+ self.bucket.blob(str(self.prefix / key)).upload_from_file(BytesIO(value))
311
+
312
+ def __getitem__(self, key: str) -> bytes:
313
+ if isinstance(self.bucket, str):
314
+ return super().__getitem__(key)
315
+
316
+ from google.api_core.exceptions import NotFound # noqa: PLC0415
317
+
318
+ try:
319
+ return self.bucket.blob(str(self.prefix / key)).download_as_bytes()
320
+ except NotFound:
321
+ raise KeyError(f"{key} is not cached!") from None
322
+
323
+ def __delitem__(self, key: str) -> None:
324
+ if isinstance(self.bucket, str):
325
+ super().__delitem__(key)
326
+ return
327
+
328
+ from google.api_core.exceptions import NotFound # noqa: PLC0415
329
+
330
+ try:
331
+ self.bucket.blob(str(self.prefix / key)).delete()
332
+ except NotFound:
333
+ raise KeyError(f"{key} is not cached!") from None
334
+
335
+ def __iter__(self) -> Iterator[str]:
336
+ if isinstance(self.bucket, str):
337
+ yield from super().__iter__()
338
+ return
339
+ prefix = "" if self.prefix == ObjectPath(".") else str(self.prefix) + "/"
340
+ for blob in self.bucket.list_blobs(prefix=prefix, delimiter="/"):
341
+ yield str(ObjectPath(blob.name).relative_to(self.prefix))
342
+
343
+ def group(self, key: str) -> Self:
344
+ group = copy(self)
345
+ group.prefix = self.prefix / key
346
+ return group
347
+
276
348
 
277
349
  class AmazonS3Cache(ObstoreCache):
278
350
  def __init__(self, bucket: str, prefix: str | ObjectPath = "jobs", *, region: str | None = None) -> None: