icechunk 0.2.2__tar.gz → 0.2.3__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 (168) hide show
  1. {icechunk-0.2.2 → icechunk-0.2.3}/PKG-INFO +2 -2
  2. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/Cargo.toml +1 -1
  3. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/config.rs +13 -0
  4. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/repository.rs +10 -0
  5. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/storage/logging.rs +7 -0
  6. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/storage/mod.rs +1 -1
  7. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/storage/object_store.rs +55 -2
  8. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/storage/s3.rs +11 -0
  9. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/Cargo.toml +2 -2
  10. {icechunk-0.2.2 → icechunk-0.2.3/icechunk-python}/python/icechunk/__init__.py +18 -0
  11. {icechunk-0.2.2 → icechunk-0.2.3/icechunk-python}/python/icechunk/_icechunk_python.pyi +4 -0
  12. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/repository.py +10 -0
  13. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/config.rs +4 -0
  14. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/repository.rs +24 -0
  15. icechunk-0.2.3/icechunk-python/tests/test_debuginfo.py +6 -0
  16. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_pickle.py +12 -0
  17. {icechunk-0.2.2 → icechunk-0.2.3}/pyproject.toml +1 -1
  18. {icechunk-0.2.2/icechunk-python → icechunk-0.2.3}/python/icechunk/__init__.py +18 -0
  19. {icechunk-0.2.2/icechunk-python → icechunk-0.2.3}/python/icechunk/_icechunk_python.pyi +4 -0
  20. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/repository.py +10 -0
  21. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/examples/low_level_dataset.rs +0 -0
  22. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/examples/multithreaded_get_chunk_refs.rs +0 -0
  23. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/examples/multithreaded_store.rs +0 -0
  24. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/flatbuffers/all.fbs +0 -0
  25. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/flatbuffers/manifest.fbs +0 -0
  26. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/flatbuffers/object_ids.fbs +0 -0
  27. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/flatbuffers/snapshot.fbs +0 -0
  28. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/flatbuffers/transaction_log.fbs +0 -0
  29. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/dataset.txt +0 -0
  30. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/format/manifest.txt +0 -0
  31. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/manifest.txt +0 -0
  32. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/session.txt +0 -0
  33. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/storage/mod.txt +0 -0
  34. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/storage/s3.txt +0 -0
  35. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/proptest-regressions/storage/virtual_ref.txt +0 -0
  36. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/asset_manager.rs +0 -0
  37. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/change_set.rs +0 -0
  38. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/conflicts/basic_solver.rs +0 -0
  39. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/conflicts/detector.rs +0 -0
  40. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/conflicts/mod.rs +0 -0
  41. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/error.rs +0 -0
  42. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/attributes.rs +0 -0
  43. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/flatbuffers/all_generated.rs +0 -0
  44. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/manifest.rs +0 -0
  45. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/mod.rs +0 -0
  46. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/serializers/mod.rs +0 -0
  47. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/snapshot.rs +0 -0
  48. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/format/transaction_log.rs +0 -0
  49. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/lib.rs +0 -0
  50. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/ops/gc.rs +0 -0
  51. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/ops/mod.rs +0 -0
  52. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/refs.rs +0 -0
  53. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/session.rs +0 -0
  54. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/store.rs +0 -0
  55. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/strategies.rs +0 -0
  56. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/src/virtual_chunks.rs +0 -0
  57. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/tests/test_concurrency.rs +0 -0
  58. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/tests/test_distributed_writes.rs +0 -0
  59. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/tests/test_gc.rs +0 -0
  60. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/tests/test_storage.rs +0 -0
  61. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk/tests/test_virtual_refs.rs +0 -0
  62. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/.gitignore +0 -0
  63. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/Cargo.lock +0 -0
  64. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/__init__.py +0 -0
  65. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/coiled_runner.py +0 -0
  66. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/conftest.py +0 -0
  67. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/create_era5.py +0 -0
  68. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/datasets.py +0 -0
  69. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/envs/icechunk-alpha-12.txt +0 -0
  70. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/envs/icechunk-alpha-release.txt +0 -0
  71. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/helpers.py +0 -0
  72. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/lib.py +0 -0
  73. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/most_recent.sh +0 -0
  74. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/runner.py +0 -0
  75. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/tasks.py +0 -0
  76. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/test_benchmark_reads.py +0 -0
  77. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/benchmarks/test_benchmark_writes.py +0 -0
  78. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/examples/dask_write.py +0 -0
  79. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/conflict.ipynb +0 -0
  80. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/demo-azure-blob.ipynb +0 -0
  81. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/demo-dummy-data.ipynb +0 -0
  82. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/demo-gcs.ipynb +0 -0
  83. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/demo-s3.ipynb +0 -0
  84. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/environment.yml +0 -0
  85. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/memorystore.ipynb +0 -0
  86. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/performance/era5_xarray-Icechunk.ipynb +0 -0
  87. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/performance/era5_xarray-zarr2.ipynb +0 -0
  88. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/performance/era5_xarray-zarr3.ipynb +0 -0
  89. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/notebooks/version-control.ipynb +0 -0
  90. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/credentials.py +0 -0
  91. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/dask.py +0 -0
  92. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/distributed.py +0 -0
  93. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/py.typed +0 -0
  94. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/session.py +0 -0
  95. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/storage.py +0 -0
  96. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/store.py +0 -0
  97. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/vendor/__init__.py +0 -0
  98. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/vendor/xarray.py +0 -0
  99. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/python/icechunk/xarray.py +0 -0
  100. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/conflicts.rs +0 -0
  101. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/errors.rs +0 -0
  102. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/lib.rs +0 -0
  103. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/session.rs +0 -0
  104. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/store.rs +0 -0
  105. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/src/streams.rs +0 -0
  106. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/__init__.py +0 -0
  107. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/conftest.py +0 -0
  108. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/chunks/09HEW2P03CSMHFAZY7DG +0 -0
  109. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/chunks/52H0E4NSPN8SVRK9EVGG +0 -0
  110. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/chunks/DWQ75SDC624XF9H326RG +0 -0
  111. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/chunks/RW938N1KP2R4BHMW62QG +0 -0
  112. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/config.yaml +0 -0
  113. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/manifests/CMYVHDWMSTG9R25780YG +0 -0
  114. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/manifests/G3W2W8V6ZG09J6C21WE0 +0 -0
  115. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/manifests/Q04J7QW5RQ8D17TPA10G +0 -0
  116. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/manifests/SHTEAP8C784YMZSJKBM0 +0 -0
  117. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/branch.main/ref.json +0 -0
  118. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/branch.my-branch/ref.json +0 -0
  119. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/tag.deleted/ref.json +0 -0
  120. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/tag.deleted/ref.json.deleted +0 -0
  121. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/tag.it also works!/ref.json +0 -0
  122. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/refs/tag.it works!/ref.json +0 -0
  123. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/4QF8JA0YPDN51MHSSYVG +0 -0
  124. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/7XAF0Q905SH4938DN9CG +0 -0
  125. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/GC4YVH5SKBPEZCENYQE0 +0 -0
  126. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/NXH3M0HJ7EEJ0699DPP0 +0 -0
  127. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/P874YS3J196959RDHX7G +0 -0
  128. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/snapshots/XDZ162T1TYBEJMK99NPG +0 -0
  129. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/transactions/4QF8JA0YPDN51MHSSYVG +0 -0
  130. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/transactions/7XAF0Q905SH4938DN9CG +0 -0
  131. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/transactions/GC4YVH5SKBPEZCENYQE0 +0 -0
  132. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/transactions/NXH3M0HJ7EEJ0699DPP0 +0 -0
  133. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/data/test-repo/transactions/XDZ162T1TYBEJMK99NPG +0 -0
  134. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/run_xarray_backends_tests.py +0 -0
  135. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_can_read_old.py +0 -0
  136. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_commit_properties.py +0 -0
  137. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_concurrency.py +0 -0
  138. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_config.py +0 -0
  139. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_conflicts.py +0 -0
  140. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_credentials.py +0 -0
  141. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_dask.py +0 -0
  142. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_distributed_writers.py +0 -0
  143. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_error.py +0 -0
  144. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_gc.py +0 -0
  145. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_regressions.py +0 -0
  146. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_stateful_repo_ops.py +0 -0
  147. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_store.py +0 -0
  148. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_timetravel.py +0 -0
  149. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_virtual_ref.py +0 -0
  150. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_xarray.py +0 -0
  151. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/__init__.py +0 -0
  152. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_array.py +0 -0
  153. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_group.py +0 -0
  154. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_properties.py +0 -0
  155. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_stateful.py +0 -0
  156. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_store/__init__.py +0 -0
  157. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_store/test_core.py +0 -0
  158. {icechunk-0.2.2 → icechunk-0.2.3}/icechunk-python/tests/test_zarr/test_store/test_icechunk_store.py +0 -0
  159. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/credentials.py +0 -0
  160. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/dask.py +0 -0
  161. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/distributed.py +0 -0
  162. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/py.typed +0 -0
  163. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/session.py +0 -0
  164. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/storage.py +0 -0
  165. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/store.py +0 -0
  166. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/vendor/__init__.py +0 -0
  167. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/vendor/xarray.py +0 -0
  168. {icechunk-0.2.2 → icechunk-0.2.3}/python/icechunk/xarray.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: icechunk
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3.11
9
9
  Classifier: Programming Language :: Python :: 3.12
10
- Requires-Dist: zarr>=3
10
+ Requires-Dist: zarr>=3,!=3.0.3
11
11
  Requires-Dist: boto3 ; extra == 'test'
12
12
  Requires-Dist: coverage ; extra == 'test'
13
13
  Requires-Dist: mypy ; extra == 'test'
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "icechunk"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Transactional storage engine for Zarr designed for use on cloud object storage"
5
5
  readme = "README.md"
6
6
  repository = "https://github.com/earth-mover/icechunk"
@@ -24,6 +24,19 @@ pub struct S3Options {
24
24
  pub allow_http: bool,
25
25
  }
26
26
 
27
+ impl fmt::Display for S3Options {
28
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29
+ write!(
30
+ f,
31
+ "S3Options(region={}, endpoint_url={}, anonymous={}, allow_http={})",
32
+ self.region.as_deref().unwrap_or("None"),
33
+ self.endpoint_url.as_deref().unwrap_or("None"),
34
+ self.anonymous,
35
+ self.allow_http
36
+ )
37
+ }
38
+ }
39
+
27
40
  #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
28
41
  #[serde(rename_all = "snake_case")]
29
42
  pub enum ObjectStoreConfig {
@@ -331,6 +331,16 @@ impl Repository {
331
331
  )
332
332
  }
333
333
 
334
+ #[instrument(skip(bytes))]
335
+ pub fn from_bytes(bytes: Vec<u8>) -> RepositoryResult<Self> {
336
+ rmp_serde::from_slice(&bytes).err_into()
337
+ }
338
+
339
+ #[instrument(skip(self))]
340
+ pub fn as_bytes(&self) -> RepositoryResult<Vec<u8>> {
341
+ rmp_serde::to_vec(self).err_into()
342
+ }
343
+
334
344
  #[instrument(skip_all)]
335
345
  pub async fn fetch_config(
336
346
  storage: &(dyn Storage + Send + Sync),
@@ -1,4 +1,5 @@
1
1
  use std::{
2
+ fmt,
2
3
  ops::Range,
3
4
  sync::{Arc, Mutex},
4
5
  };
@@ -37,6 +38,12 @@ impl LoggingStorage {
37
38
  }
38
39
  }
39
40
 
41
+ impl fmt::Display for LoggingStorage {
42
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43
+ write!(f, "LoggingStorage(backend={})", self.backend)
44
+ }
45
+ }
46
+
40
47
  impl private::Sealed for LoggingStorage {}
41
48
 
42
49
  #[async_trait]
@@ -298,7 +298,7 @@ pub enum WriteRefResult {
298
298
  /// Implementations are free to assume files are never overwritten.
299
299
  #[async_trait]
300
300
  #[typetag::serde(tag = "type")]
301
- pub trait Storage: fmt::Debug + private::Sealed + Sync + Send {
301
+ pub trait Storage: fmt::Debug + fmt::Display + private::Sealed + Sync + Send {
302
302
  fn default_settings(&self) -> Settings {
303
303
  Default::default()
304
304
  }
@@ -27,7 +27,7 @@ use object_store::{
27
27
  use serde::{Deserialize, Serialize};
28
28
  use std::{
29
29
  collections::HashMap,
30
- fmt::Debug,
30
+ fmt::{self, Debug, Display},
31
31
  fs::create_dir_all,
32
32
  future::ready,
33
33
  num::{NonZeroU16, NonZeroU64},
@@ -286,6 +286,12 @@ impl ObjectStorage {
286
286
  }
287
287
  }
288
288
 
289
+ impl fmt::Display for ObjectStorage {
290
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291
+ write!(f, "ObjectStorage(backend={})", self.backend)
292
+ }
293
+ }
294
+
289
295
  impl private::Sealed for ObjectStorage {}
290
296
 
291
297
  #[async_trait]
@@ -622,7 +628,7 @@ impl Storage for ObjectStorage {
622
628
 
623
629
  #[async_trait]
624
630
  #[typetag::serde(tag = "object_store_provider_type")]
625
- pub trait ObjectStoreBackend: Debug + Sync + Send {
631
+ pub trait ObjectStoreBackend: Debug + Display + Sync + Send {
626
632
  async fn mk_object_store(&self) -> Result<Arc<dyn ObjectStore>, StorageError>;
627
633
 
628
634
  /// The prefix for the object store.
@@ -640,6 +646,12 @@ pub trait ObjectStoreBackend: Debug + Sync + Send {
640
646
  #[derive(Debug, Serialize, Deserialize)]
641
647
  pub struct InMemoryObjectStoreBackend;
642
648
 
649
+ impl fmt::Display for InMemoryObjectStoreBackend {
650
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
651
+ write!(f, "InMemoryObjectStoreBackend")
652
+ }
653
+ }
654
+
643
655
  #[async_trait]
644
656
  #[typetag::serde(name = "in_memory_object_store_provider")]
645
657
  impl ObjectStoreBackend for InMemoryObjectStoreBackend {
@@ -672,6 +684,12 @@ pub struct LocalFileSystemObjectStoreBackend {
672
684
  path: PathBuf,
673
685
  }
674
686
 
687
+ impl fmt::Display for LocalFileSystemObjectStoreBackend {
688
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
689
+ write!(f, "LocalFileSystemObjectStoreBackend(path={})", self.path.display())
690
+ }
691
+ }
692
+
675
693
  #[async_trait]
676
694
  #[typetag::serde(name = "local_file_system_object_store_provider")]
677
695
  impl ObjectStoreBackend for LocalFileSystemObjectStoreBackend {
@@ -720,6 +738,18 @@ pub struct S3ObjectStoreBackend {
720
738
  config: Option<S3Options>,
721
739
  }
722
740
 
741
+ impl fmt::Display for S3ObjectStoreBackend {
742
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
743
+ write!(
744
+ f,
745
+ "S3ObjectStoreBackend(bucket={}, prefix={}, config={})",
746
+ self.bucket,
747
+ self.prefix.as_deref().unwrap_or(""),
748
+ self.config.as_ref().map(|c| c.to_string()).unwrap_or("None".to_string())
749
+ )
750
+ }
751
+ }
752
+
723
753
  #[async_trait]
724
754
  #[typetag::serde(name = "s3_object_store_provider")]
725
755
  impl ObjectStoreBackend for S3ObjectStoreBackend {
@@ -794,6 +824,18 @@ pub struct AzureObjectStoreBackend {
794
824
  config: Option<HashMap<AzureConfigKey, String>>,
795
825
  }
796
826
 
827
+ impl fmt::Display for AzureObjectStoreBackend {
828
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829
+ write!(
830
+ f,
831
+ "AzureObjectStoreBackend(account={}, container={}, prefix={})",
832
+ self.account,
833
+ self.container,
834
+ self.prefix.as_deref().unwrap_or("")
835
+ )
836
+ }
837
+ }
838
+
797
839
  #[async_trait]
798
840
  #[typetag::serde(name = "azure_object_store_provider")]
799
841
  impl ObjectStoreBackend for AzureObjectStoreBackend {
@@ -846,6 +888,17 @@ pub struct GcsObjectStoreBackend {
846
888
  config: Option<HashMap<GoogleConfigKey, String>>,
847
889
  }
848
890
 
891
+ impl fmt::Display for GcsObjectStoreBackend {
892
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
893
+ write!(
894
+ f,
895
+ "GcsObjectStoreBackend(bucket={}, prefix={})",
896
+ self.bucket,
897
+ self.prefix.as_deref().unwrap_or("")
898
+ )
899
+ }
900
+ }
901
+
849
902
  #[async_trait]
850
903
  #[typetag::serde(name = "gcs_object_store_provider")]
851
904
  impl ObjectStoreBackend for GcsObjectStoreBackend {
@@ -1,4 +1,5 @@
1
1
  use std::{
2
+ fmt,
2
3
  future::ready,
3
4
  ops::Range,
4
5
  path::{Path, PathBuf},
@@ -59,6 +60,16 @@ pub struct S3Storage {
59
60
  client: OnceCell<Arc<Client>>,
60
61
  }
61
62
 
63
+ impl fmt::Display for S3Storage {
64
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65
+ write!(
66
+ f,
67
+ "S3Storage(bucket={}, prefix={}, config={})",
68
+ self.bucket, self.prefix, self.config,
69
+ )
70
+ }
71
+ }
72
+
62
73
  #[instrument(skip(credentials))]
63
74
  pub async fn mk_client(config: &S3Options, credentials: S3Credentials) -> Client {
64
75
  let region = config
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "icechunk-python"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Transactional storage engine for Zarr designed for use on cloud object storage"
5
5
  readme = "../README.md"
6
6
  repository = "https://github.com/earth-mover/icechunk"
@@ -21,7 +21,7 @@ crate-type = ["cdylib"]
21
21
  bytes = "1.9.0"
22
22
  chrono = { version = "0.4.39" }
23
23
  futures = "0.3.31"
24
- icechunk = { path = "../icechunk", version = "0.2.2", features = ["logs"] }
24
+ icechunk = { path = "../icechunk", version = "0.2.3", features = ["logs"] }
25
25
  itertools = "0.14.0"
26
26
  pyo3 = { version = "0.23", features = [
27
27
  "chrono",
@@ -52,6 +52,7 @@ from icechunk.credentials import (
52
52
  containers_credentials,
53
53
  gcs_credentials,
54
54
  gcs_from_env_credentials,
55
+ gcs_refreshable_credentials,
55
56
  gcs_static_credentials,
56
57
  s3_anonymous_credentials,
57
58
  s3_credentials,
@@ -128,11 +129,13 @@ __all__ = [
128
129
  "containers_credentials",
129
130
  "gcs_credentials",
130
131
  "gcs_from_env_credentials",
132
+ "gcs_refreshable_credentials",
131
133
  "gcs_static_credentials",
132
134
  "gcs_storage",
133
135
  "in_memory_storage",
134
136
  "initialize_logs",
135
137
  "local_filesystem_storage",
138
+ "print_debug_info",
136
139
  "s3_anonymous_credentials",
137
140
  "s3_credentials",
138
141
  "s3_from_env_credentials",
@@ -144,4 +147,19 @@ __all__ = [
144
147
  "tigris_storage",
145
148
  ]
146
149
 
150
+
151
+ def print_debug_info() -> None:
152
+ import platform
153
+ from importlib import import_module
154
+
155
+ print(f"platform: {platform.platform()}")
156
+ print(f"python: {platform.python_version()}")
157
+ print(f"icechunk: {__version__}")
158
+ for package in ["zarr", "numcodecs", "xarray", "virtualizarr"]:
159
+ try:
160
+ print(f"{package}: {import_module(package).__version__}")
161
+ except ModuleNotFoundError:
162
+ continue
163
+
164
+
147
165
  initialize_logs()
@@ -947,6 +947,9 @@ class PyRepository:
947
947
  ) -> PyRepository: ...
948
948
  @staticmethod
949
949
  def exists(storage: Storage) -> bool: ...
950
+ @classmethod
951
+ def from_bytes(cls, data: bytes) -> PyRepository: ...
952
+ def as_bytes(self) -> bytes: ...
950
953
  @staticmethod
951
954
  def fetch_config(storage: Storage) -> RepositoryConfig | None: ...
952
955
  def save_config(self) -> None: ...
@@ -1418,6 +1421,7 @@ class Storage:
1418
1421
  *,
1419
1422
  config: dict[str, str] | None = None,
1420
1423
  ) -> Storage: ...
1424
+ def __repr__(self) -> str: ...
1421
1425
  def default_settings(self) -> StorageSettings: ...
1422
1426
 
1423
1427
  class VersionSelection(Enum):
@@ -140,6 +140,16 @@ class Repository:
140
140
  """
141
141
  return PyRepository.exists(storage)
142
142
 
143
+ def __getstate__(self) -> object:
144
+ return {
145
+ "_repository": self._repository.as_bytes(),
146
+ }
147
+
148
+ def __setstate__(self, state: object) -> None:
149
+ if not isinstance(state, dict):
150
+ raise ValueError("Invalid repository state")
151
+ self._repository = PyRepository.from_bytes(state["_repository"])
152
+
143
153
  @staticmethod
144
154
  def fetch_config(storage: Storage) -> RepositoryConfig | None:
145
155
  """
@@ -1312,6 +1312,10 @@ impl PyStorage {
1312
1312
  })
1313
1313
  }
1314
1314
 
1315
+ pub fn __repr__(&self) -> String {
1316
+ format!("{}", self.0)
1317
+ }
1318
+
1315
1319
  pub fn default_settings(&self) -> PyStorageSettings {
1316
1320
  self.0.default_settings().into()
1317
1321
  }
@@ -1,4 +1,5 @@
1
1
  use std::{
2
+ borrow::Cow,
2
3
  collections::{BTreeMap, BTreeSet, HashMap, HashSet},
3
4
  sync::Arc,
4
5
  };
@@ -463,6 +464,29 @@ impl PyRepository {
463
464
  })
464
465
  }
465
466
 
467
+ #[classmethod]
468
+ fn from_bytes(
469
+ _cls: Bound<'_, PyType>,
470
+ py: Python<'_>,
471
+ bytes: Vec<u8>,
472
+ ) -> PyResult<Self> {
473
+ // This is a compute intensive task, we need to release the Gil
474
+ py.allow_threads(move || {
475
+ let repository = Repository::from_bytes(bytes)
476
+ .map_err(PyIcechunkStoreError::RepositoryError)?;
477
+ Ok(Self(Arc::new(repository)))
478
+ })
479
+ }
480
+
481
+ fn as_bytes(&self, py: Python<'_>) -> PyResult<Cow<[u8]>> {
482
+ // This is a compute intensive task, we need to release the Gil
483
+ py.allow_threads(move || {
484
+ let bytes =
485
+ self.0.as_bytes().map_err(PyIcechunkStoreError::RepositoryError)?;
486
+ Ok(Cow::Owned(bytes))
487
+ })
488
+ }
489
+
466
490
  #[staticmethod]
467
491
  fn fetch_config(
468
492
  py: Python<'_>,
@@ -0,0 +1,6 @@
1
+ from icechunk import print_debug_info
2
+
3
+
4
+ def test_debug_info() -> None:
5
+ # simple test that this does not cause an error.
6
+ print_debug_info()
@@ -25,6 +25,18 @@ def tmp_repo(tmpdir: Path) -> Repository:
25
25
  return repo
26
26
 
27
27
 
28
+ def test_pickle_repository(tmpdir: Path, tmp_repo: Repository) -> None:
29
+ pickled = pickle.dumps(tmp_repo)
30
+ roundtripped = pickle.loads(pickled)
31
+ assert tmp_repo.list_branches() == roundtripped.list_branches()
32
+
33
+ storage = tmp_repo.storage
34
+ assert (
35
+ repr(storage)
36
+ == f"ObjectStorage(backend=LocalFileSystemObjectStoreBackend(path={tmpdir}))"
37
+ )
38
+
39
+
28
40
  def test_pickle_read_only(tmp_repo: Repository) -> None:
29
41
  tmp_session = tmp_repo.writable_session(branch="main")
30
42
  tmp_store = tmp_session.store
@@ -19,7 +19,7 @@ license = "Apache-2.0"
19
19
  dynamic = ["version"]
20
20
  authors = [{ name = "Earthmover", email = "info@earthmover.io" }]
21
21
 
22
- dependencies = ["zarr>=3"]
22
+ dependencies = ["zarr>=3,!=3.0.3"]
23
23
 
24
24
  [project.optional-dependencies]
25
25
  test = [
@@ -52,6 +52,7 @@ from icechunk.credentials import (
52
52
  containers_credentials,
53
53
  gcs_credentials,
54
54
  gcs_from_env_credentials,
55
+ gcs_refreshable_credentials,
55
56
  gcs_static_credentials,
56
57
  s3_anonymous_credentials,
57
58
  s3_credentials,
@@ -128,11 +129,13 @@ __all__ = [
128
129
  "containers_credentials",
129
130
  "gcs_credentials",
130
131
  "gcs_from_env_credentials",
132
+ "gcs_refreshable_credentials",
131
133
  "gcs_static_credentials",
132
134
  "gcs_storage",
133
135
  "in_memory_storage",
134
136
  "initialize_logs",
135
137
  "local_filesystem_storage",
138
+ "print_debug_info",
136
139
  "s3_anonymous_credentials",
137
140
  "s3_credentials",
138
141
  "s3_from_env_credentials",
@@ -144,4 +147,19 @@ __all__ = [
144
147
  "tigris_storage",
145
148
  ]
146
149
 
150
+
151
+ def print_debug_info() -> None:
152
+ import platform
153
+ from importlib import import_module
154
+
155
+ print(f"platform: {platform.platform()}")
156
+ print(f"python: {platform.python_version()}")
157
+ print(f"icechunk: {__version__}")
158
+ for package in ["zarr", "numcodecs", "xarray", "virtualizarr"]:
159
+ try:
160
+ print(f"{package}: {import_module(package).__version__}")
161
+ except ModuleNotFoundError:
162
+ continue
163
+
164
+
147
165
  initialize_logs()
@@ -947,6 +947,9 @@ class PyRepository:
947
947
  ) -> PyRepository: ...
948
948
  @staticmethod
949
949
  def exists(storage: Storage) -> bool: ...
950
+ @classmethod
951
+ def from_bytes(cls, data: bytes) -> PyRepository: ...
952
+ def as_bytes(self) -> bytes: ...
950
953
  @staticmethod
951
954
  def fetch_config(storage: Storage) -> RepositoryConfig | None: ...
952
955
  def save_config(self) -> None: ...
@@ -1418,6 +1421,7 @@ class Storage:
1418
1421
  *,
1419
1422
  config: dict[str, str] | None = None,
1420
1423
  ) -> Storage: ...
1424
+ def __repr__(self) -> str: ...
1421
1425
  def default_settings(self) -> StorageSettings: ...
1422
1426
 
1423
1427
  class VersionSelection(Enum):
@@ -140,6 +140,16 @@ class Repository:
140
140
  """
141
141
  return PyRepository.exists(storage)
142
142
 
143
+ def __getstate__(self) -> object:
144
+ return {
145
+ "_repository": self._repository.as_bytes(),
146
+ }
147
+
148
+ def __setstate__(self, state: object) -> None:
149
+ if not isinstance(state, dict):
150
+ raise ValueError("Invalid repository state")
151
+ self._repository = PyRepository.from_bytes(state["_repository"])
152
+
143
153
  @staticmethod
144
154
  def fetch_config(storage: Storage) -> RepositoryConfig | None:
145
155
  """
File without changes
File without changes
File without changes
File without changes