rustytree-xarray 0.4.0__tar.gz → 0.5.0__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 (48) hide show
  1. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/.github/workflows/ci.yml +2 -2
  2. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/.github/workflows/release.yml +1 -1
  3. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/CHANGELOG.md +36 -1
  4. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/Cargo.lock +126 -87
  5. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/Cargo.toml +2 -2
  6. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/PKG-INFO +1 -1
  7. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/pyproject.toml +1 -1
  8. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/python/rustytree/__init__.py +1 -1
  9. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/python/rustytree/_array.py +14 -5
  10. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/python/rustytree/backend.py +9 -6
  11. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/array.rs +15 -3
  12. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/lib.rs +6 -2
  13. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/node.rs +4 -1
  14. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/walk.rs +92 -26
  15. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/conftest.py +22 -0
  16. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_backend_entrypoint.py +45 -5
  17. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_eager_fetch.py +4 -15
  18. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_phase1_scaffold.py +1 -1
  19. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_string_arrays.py +165 -6
  20. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/.github/dependabot.yml +0 -0
  21. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/.gitignore +0 -0
  22. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/LICENSE +0 -0
  23. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/README.md +0 -0
  24. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/assets/logo-banner-dark.png +0 -0
  25. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/assets/logo-banner-dark.svg +0 -0
  26. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/assets/logo-banner-light.png +0 -0
  27. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/assets/logo-banner-light.svg +0 -0
  28. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/assets/logo.png +0 -0
  29. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/docs/architecture.md +0 -0
  30. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/docs/contributing.md +0 -0
  31. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/docs/release-process.md +0 -0
  32. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/docs/usage.md +0 -0
  33. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/notebooks/klot_demo.ipynb +0 -0
  34. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/dtype_dispatch.rs +0 -0
  35. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/error.rs +0 -0
  36. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/glob.rs +0 -0
  37. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/icechunk_store.rs +0 -0
  38. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/py_credentials.rs +0 -0
  39. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/runtime.rs +0 -0
  40. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/store.rs +0 -0
  41. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/src/url.rs +0 -0
  42. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_chunks.py +0 -0
  43. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_codecs.py +0 -0
  44. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_icechunk.py +0 -0
  45. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_lazy.py +0 -0
  46. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_pickle.py +0 -0
  47. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_to_rust_source.py +0 -0
  48. {rustytree_xarray-0.4.0 → rustytree_xarray-0.5.0}/tests/test_walk.py +0 -0
@@ -39,7 +39,7 @@ jobs:
39
39
  - uses: dtolnay/rust-toolchain@stable
40
40
  with:
41
41
  components: clippy, rustfmt
42
- - uses: actions/setup-python@v6
42
+ - uses: actions/setup-python@v7
43
43
  with:
44
44
  python-version: "3.12"
45
45
  - uses: Swatinem/rust-cache@v2
@@ -73,7 +73,7 @@ jobs:
73
73
  with:
74
74
  # Keyed by Python version so each matrix cell gets its own cache.
75
75
  key: py-${{ matrix.python-version }}
76
- - uses: actions/setup-python@v6
76
+ - uses: actions/setup-python@v7
77
77
  with:
78
78
  python-version: ${{ matrix.python-version }}
79
79
  - uses: astral-sh/setup-uv@v7
@@ -48,7 +48,7 @@ jobs:
48
48
  runs-on: ${{ matrix.platform.os }}
49
49
  steps:
50
50
  - uses: actions/checkout@v7
51
- - uses: actions/setup-python@v6
51
+ - uses: actions/setup-python@v7
52
52
  with:
53
53
  python-version: ${{ matrix.python-version }}
54
54
  - uses: dtolnay/rust-toolchain@stable
@@ -11,6 +11,35 @@ release, that section is renamed to `[x.y.z] - YYYY-MM-DD` and a fresh
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.5.0] - 2026-07-26
15
+
16
+ ### Added
17
+
18
+ - Eager-fetch small `object`-dtype (vlen `string`) scalars and self-named
19
+ 1-D coords during the walk's Phase C ([#77]). `xr.open_datatree(engine=
20
+ "rustytree")` was paying one serial lazy read per `object`-dtype variable
21
+ at open time — xarray's `_contains_datetime_like_objects` samples every
22
+ such variable to rule out `cftime.datetime`, independent of the existing
23
+ CF-time-like/dim-coord triggers Phase C already covers. Extends the walk's
24
+ parallel pre-fetch to cover this case (bounded by a 4096-element count cap
25
+ and an 8 MiB total-byte-size cap, since per-element size is unbounded for
26
+ strings unlike the existing fixed-width numeric cap), and adds the
27
+ matching `object` → declared-read-dtype cast on the eager path in
28
+ `backend.py` (mirroring the lazy path's existing cast from #71). Scoped to
29
+ scalars and self-named 1-D coords only, so an ordinary small string data
30
+ variable doesn't lose its dask laziness just because it's small. Verified
31
+ on the live `s3://nexrad-arco/KLOT` store: ~48% faster `open_datatree`
32
+ (8.223s → 4.241s mean over 4 trials), 42 serial lazy reads eliminated.
33
+
34
+ ### Changed
35
+
36
+ - Routine dependency and CI-action bumps via Dependabot ([#72], [#74],
37
+ [#75], [#76]). Cargo: `quinn-proto` 0.11.14 → 0.11.16 ([#72]); cargo-minor
38
+ group — `tokio` 1.53.0 → 1.53.1, `thiserror` 2.0.18 → 2.0.19, `async-trait`
39
+ 0.1.89 → 0.1.91, `serde` 1.0.228 → 1.0.229, `zarrs_storage` 0.4.4 → 0.4.5,
40
+ `serde_json` 1.0.150 → 1.0.151 ([#75]); `zarrs_object_store` 0.6.2 → 0.7.0
41
+ ([#76]). CI: `actions/setup-python` 6 → 7 ([#74]).
42
+
14
43
  ## [0.4.0] - 2026-07-24
15
44
 
16
45
  ### Added
@@ -835,7 +864,8 @@ below.
835
864
  intentionally not normalized — relative-vs-absolute glob
836
865
  semantics differ in `PurePosixPath.match`.
837
866
 
838
- [Unreleased]: https://github.com/aladinor/rustytree/compare/v0.4.0...HEAD
867
+ [Unreleased]: https://github.com/aladinor/rustytree/compare/v0.5.0...HEAD
868
+ [0.5.0]: https://github.com/aladinor/rustytree/compare/v0.4.0...v0.5.0
839
869
  [0.4.0]: https://github.com/aladinor/rustytree/compare/v0.3.0...v0.4.0
840
870
  [0.3.0]: https://github.com/aladinor/rustytree/compare/v0.2.1...v0.3.0
841
871
  [0.2.1]: https://github.com/aladinor/rustytree/compare/v0.2.0...v0.2.1
@@ -884,3 +914,8 @@ below.
884
914
  [#64]: https://github.com/aladinor/rustytree/pull/64
885
915
  [#68]: https://github.com/aladinor/rustytree/pull/68
886
916
  [#71]: https://github.com/aladinor/rustytree/pull/71
917
+ [#72]: https://github.com/aladinor/rustytree/pull/72
918
+ [#74]: https://github.com/aladinor/rustytree/pull/74
919
+ [#75]: https://github.com/aladinor/rustytree/pull/75
920
+ [#76]: https://github.com/aladinor/rustytree/pull/76
921
+ [#77]: https://github.com/aladinor/rustytree/pull/77
@@ -120,13 +120,13 @@ dependencies = [
120
120
 
121
121
  [[package]]
122
122
  name = "async-trait"
123
- version = "0.1.89"
123
+ version = "0.1.91"
124
124
  source = "registry+https://github.com/rust-lang/crates.io-index"
125
- checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
125
+ checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
126
126
  dependencies = [
127
127
  "proc-macro2",
128
128
  "quote",
129
- "syn 2.0.117",
129
+ "syn 3.0.2",
130
130
  ]
131
131
 
132
132
  [[package]]
@@ -1529,11 +1529,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1529
1529
  checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
1530
1530
  dependencies = [
1531
1531
  "cfg-if",
1532
+ "js-sys",
1532
1533
  "libc",
1533
1534
  "r-efi 6.0.0",
1534
1535
  "rand_core 0.10.1",
1535
1536
  "wasip2",
1536
1537
  "wasip3",
1538
+ "wasm-bindgen",
1537
1539
  ]
1538
1540
 
1539
1541
  [[package]]
@@ -1900,7 +1902,7 @@ dependencies = [
1900
1902
  "icechunk-types",
1901
1903
  "itertools 0.15.0",
1902
1904
  "quick_cache",
1903
- "rand 0.10.1",
1905
+ "rand",
1904
1906
  "regex",
1905
1907
  "reqwest 0.13.3",
1906
1908
  "rmp-serde",
@@ -1932,8 +1934,8 @@ dependencies = [
1932
1934
  "http 1.4.0",
1933
1935
  "icechunk-storage",
1934
1936
  "icechunk-types",
1935
- "object_store",
1936
- "rand 0.10.1",
1937
+ "object_store 0.13.2",
1938
+ "rand",
1937
1939
  "serde",
1938
1940
  "tokio",
1939
1941
  "tokio-util",
@@ -1957,7 +1959,7 @@ dependencies = [
1957
1959
  "icechunk-types",
1958
1960
  "itertools 0.15.0",
1959
1961
  "quick_cache",
1960
- "rand 0.10.1",
1962
+ "rand",
1961
1963
  "rmp-serde",
1962
1964
  "serde",
1963
1965
  "serde_bytes",
@@ -2486,9 +2488,9 @@ dependencies = [
2486
2488
 
2487
2489
  [[package]]
2488
2490
  name = "ndarray"
2489
- version = "0.16.1"
2491
+ version = "0.17.2"
2490
2492
  source = "registry+https://github.com/rust-lang/crates.io-index"
2491
- checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841"
2493
+ checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d"
2492
2494
  dependencies = [
2493
2495
  "matrixmultiply",
2494
2496
  "num-complex",
@@ -2500,18 +2502,15 @@ dependencies = [
2500
2502
  ]
2501
2503
 
2502
2504
  [[package]]
2503
- name = "ndarray"
2504
- version = "0.17.2"
2505
+ name = "nix"
2506
+ version = "0.31.3"
2505
2507
  source = "registry+https://github.com/rust-lang/crates.io-index"
2506
- checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d"
2508
+ checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
2507
2509
  dependencies = [
2508
- "matrixmultiply",
2509
- "num-complex",
2510
- "num-integer",
2511
- "num-traits",
2512
- "portable-atomic",
2513
- "portable-atomic-util",
2514
- "rawpointer",
2510
+ "bitflags 2.11.1",
2511
+ "cfg-if",
2512
+ "cfg_aliases",
2513
+ "libc",
2515
2514
  ]
2516
2515
 
2517
2516
  [[package]]
@@ -2622,7 +2621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2622
2621
  checksum = "6a5b15d63a5ff39e378daed0e1340d3a5964703ea9712eb09a0dc66fade996f4"
2623
2622
  dependencies = [
2624
2623
  "libc",
2625
- "ndarray 0.16.1",
2624
+ "ndarray",
2626
2625
  "num-complex",
2627
2626
  "num-integer",
2628
2627
  "num-traits",
@@ -2654,8 +2653,8 @@ dependencies = [
2654
2653
  "md-5 0.10.6",
2655
2654
  "parking_lot",
2656
2655
  "percent-encoding",
2657
- "quick-xml",
2658
- "rand 0.10.1",
2656
+ "quick-xml 0.39.3",
2657
+ "rand",
2659
2658
  "reqwest 0.12.28",
2660
2659
  "ring",
2661
2660
  "rustls-pki-types",
@@ -2671,6 +2670,48 @@ dependencies = [
2671
2670
  "web-time",
2672
2671
  ]
2673
2672
 
2673
+ [[package]]
2674
+ name = "object_store"
2675
+ version = "0.14.1"
2676
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2677
+ checksum = "d354792e39fa5f0009e47623cf8b15b099bf9a652fa55c6f817fe28ac84fea50"
2678
+ dependencies = [
2679
+ "async-trait",
2680
+ "aws-lc-rs",
2681
+ "base64",
2682
+ "bytes",
2683
+ "chrono",
2684
+ "crc-fast",
2685
+ "form_urlencoded",
2686
+ "futures-channel",
2687
+ "futures-core",
2688
+ "futures-util",
2689
+ "http 1.4.0",
2690
+ "http-body-util",
2691
+ "humantime",
2692
+ "hyper 1.9.0",
2693
+ "itertools 0.15.0",
2694
+ "md-5 0.11.0",
2695
+ "nix",
2696
+ "parking_lot",
2697
+ "percent-encoding",
2698
+ "quick-xml 0.41.0",
2699
+ "rand",
2700
+ "reqwest 0.13.3",
2701
+ "rustls-pki-types",
2702
+ "serde",
2703
+ "serde_json",
2704
+ "serde_urlencoded",
2705
+ "thiserror",
2706
+ "tokio",
2707
+ "tracing",
2708
+ "url",
2709
+ "walkdir",
2710
+ "wasm-bindgen-futures",
2711
+ "web-time",
2712
+ "windows-sys 0.61.2",
2713
+ ]
2714
+
2674
2715
  [[package]]
2675
2716
  name = "once_cell"
2676
2717
  version = "1.21.4"
@@ -2826,15 +2867,6 @@ version = "0.2.0"
2826
2867
  source = "registry+https://github.com/rust-lang/crates.io-index"
2827
2868
  checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
2828
2869
 
2829
- [[package]]
2830
- name = "ppv-lite86"
2831
- version = "0.2.21"
2832
- source = "registry+https://github.com/rust-lang/crates.io-index"
2833
- checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
2834
- dependencies = [
2835
- "zerocopy",
2836
- ]
2837
-
2838
2870
  [[package]]
2839
2871
  name = "prettyplease"
2840
2872
  version = "0.2.37"
@@ -2932,6 +2964,16 @@ dependencies = [
2932
2964
  "serde",
2933
2965
  ]
2934
2966
 
2967
+ [[package]]
2968
+ name = "quick-xml"
2969
+ version = "0.41.0"
2970
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2971
+ checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
2972
+ dependencies = [
2973
+ "memchr",
2974
+ "serde",
2975
+ ]
2976
+
2935
2977
  [[package]]
2936
2978
  name = "quick_cache"
2937
2979
  version = "0.6.24"
@@ -2966,15 +3008,16 @@ dependencies = [
2966
3008
 
2967
3009
  [[package]]
2968
3010
  name = "quinn-proto"
2969
- version = "0.11.14"
3011
+ version = "0.11.16"
2970
3012
  source = "registry+https://github.com/rust-lang/crates.io-index"
2971
- checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
3013
+ checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
2972
3014
  dependencies = [
2973
3015
  "aws-lc-rs",
2974
3016
  "bytes",
2975
- "getrandom 0.3.4",
3017
+ "getrandom 0.4.2",
2976
3018
  "lru-slab",
2977
- "rand 0.9.4",
3019
+ "rand",
3020
+ "rand_pcg",
2978
3021
  "ring",
2979
3022
  "rustc-hash",
2980
3023
  "rustls 0.23.40",
@@ -3021,16 +3064,6 @@ version = "6.0.0"
3021
3064
  source = "registry+https://github.com/rust-lang/crates.io-index"
3022
3065
  checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
3023
3066
 
3024
- [[package]]
3025
- name = "rand"
3026
- version = "0.9.4"
3027
- source = "registry+https://github.com/rust-lang/crates.io-index"
3028
- checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
3029
- dependencies = [
3030
- "rand_chacha",
3031
- "rand_core 0.9.5",
3032
- ]
3033
-
3034
3067
  [[package]]
3035
3068
  name = "rand"
3036
3069
  version = "0.10.1"
@@ -3042,16 +3075,6 @@ dependencies = [
3042
3075
  "rand_core 0.10.1",
3043
3076
  ]
3044
3077
 
3045
- [[package]]
3046
- name = "rand_chacha"
3047
- version = "0.9.0"
3048
- source = "registry+https://github.com/rust-lang/crates.io-index"
3049
- checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
3050
- dependencies = [
3051
- "ppv-lite86",
3052
- "rand_core 0.9.5",
3053
- ]
3054
-
3055
3078
  [[package]]
3056
3079
  name = "rand_core"
3057
3080
  version = "0.6.4"
@@ -3063,18 +3086,18 @@ dependencies = [
3063
3086
 
3064
3087
  [[package]]
3065
3088
  name = "rand_core"
3066
- version = "0.9.5"
3089
+ version = "0.10.1"
3067
3090
  source = "registry+https://github.com/rust-lang/crates.io-index"
3068
- checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
3069
- dependencies = [
3070
- "getrandom 0.3.4",
3071
- ]
3091
+ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
3072
3092
 
3073
3093
  [[package]]
3074
- name = "rand_core"
3075
- version = "0.10.1"
3094
+ name = "rand_pcg"
3095
+ version = "0.10.2"
3076
3096
  source = "registry+https://github.com/rust-lang/crates.io-index"
3077
- checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
3097
+ checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
3098
+ dependencies = [
3099
+ "rand_core 0.10.1",
3100
+ ]
3078
3101
 
3079
3102
  [[package]]
3080
3103
  name = "rawpointer"
@@ -3213,7 +3236,7 @@ dependencies = [
3213
3236
  "url",
3214
3237
  "wasm-bindgen",
3215
3238
  "wasm-bindgen-futures",
3216
- "wasm-streams",
3239
+ "wasm-streams 0.4.2",
3217
3240
  "web-sys",
3218
3241
  ]
3219
3242
 
@@ -3227,6 +3250,7 @@ dependencies = [
3227
3250
  "bytes",
3228
3251
  "encoding_rs",
3229
3252
  "futures-core",
3253
+ "futures-util",
3230
3254
  "h2 0.4.14",
3231
3255
  "http 1.4.0",
3232
3256
  "http-body 1.0.1",
@@ -3246,12 +3270,14 @@ dependencies = [
3246
3270
  "sync_wrapper",
3247
3271
  "tokio",
3248
3272
  "tokio-rustls 0.26.4",
3273
+ "tokio-util",
3249
3274
  "tower",
3250
3275
  "tower-http",
3251
3276
  "tower-service",
3252
3277
  "url",
3253
3278
  "wasm-bindgen",
3254
3279
  "wasm-bindgen-futures",
3280
+ "wasm-streams 0.5.0",
3255
3281
  "web-sys",
3256
3282
  ]
3257
3283
 
@@ -3420,7 +3446,7 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
3420
3446
 
3421
3447
  [[package]]
3422
3448
  name = "rustytree"
3423
- version = "0.4.0"
3449
+ version = "0.5.0"
3424
3450
  dependencies = [
3425
3451
  "async-trait",
3426
3452
  "chrono",
@@ -3549,9 +3575,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
3549
3575
 
3550
3576
  [[package]]
3551
3577
  name = "serde"
3552
- version = "1.0.228"
3578
+ version = "1.0.229"
3553
3579
  source = "registry+https://github.com/rust-lang/crates.io-index"
3554
- checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
3580
+ checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
3555
3581
  dependencies = [
3556
3582
  "serde_core",
3557
3583
  "serde_derive",
@@ -3569,29 +3595,29 @@ dependencies = [
3569
3595
 
3570
3596
  [[package]]
3571
3597
  name = "serde_core"
3572
- version = "1.0.228"
3598
+ version = "1.0.229"
3573
3599
  source = "registry+https://github.com/rust-lang/crates.io-index"
3574
- checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
3600
+ checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
3575
3601
  dependencies = [
3576
3602
  "serde_derive",
3577
3603
  ]
3578
3604
 
3579
3605
  [[package]]
3580
3606
  name = "serde_derive"
3581
- version = "1.0.228"
3607
+ version = "1.0.229"
3582
3608
  source = "registry+https://github.com/rust-lang/crates.io-index"
3583
- checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
3609
+ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
3584
3610
  dependencies = [
3585
3611
  "proc-macro2",
3586
3612
  "quote",
3587
- "syn 2.0.117",
3613
+ "syn 3.0.2",
3588
3614
  ]
3589
3615
 
3590
3616
  [[package]]
3591
3617
  name = "serde_json"
3592
- version = "1.0.150"
3618
+ version = "1.0.151"
3593
3619
  source = "registry+https://github.com/rust-lang/crates.io-index"
3594
- checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
3620
+ checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
3595
3621
  dependencies = [
3596
3622
  "indexmap 2.14.0",
3597
3623
  "itoa",
@@ -3940,22 +3966,22 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
3940
3966
 
3941
3967
  [[package]]
3942
3968
  name = "thiserror"
3943
- version = "2.0.18"
3969
+ version = "2.0.19"
3944
3970
  source = "registry+https://github.com/rust-lang/crates.io-index"
3945
- checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
3971
+ checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
3946
3972
  dependencies = [
3947
3973
  "thiserror-impl",
3948
3974
  ]
3949
3975
 
3950
3976
  [[package]]
3951
3977
  name = "thiserror-impl"
3952
- version = "2.0.18"
3978
+ version = "2.0.19"
3953
3979
  source = "registry+https://github.com/rust-lang/crates.io-index"
3954
- checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
3980
+ checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
3955
3981
  dependencies = [
3956
3982
  "proc-macro2",
3957
3983
  "quote",
3958
- "syn 2.0.117",
3984
+ "syn 3.0.2",
3959
3985
  ]
3960
3986
 
3961
3987
  [[package]]
@@ -4025,9 +4051,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
4025
4051
 
4026
4052
  [[package]]
4027
4053
  name = "tokio"
4028
- version = "1.53.0"
4054
+ version = "1.53.1"
4029
4055
  source = "registry+https://github.com/rust-lang/crates.io-index"
4030
- checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee"
4056
+ checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
4031
4057
  dependencies = [
4032
4058
  "bytes",
4033
4059
  "libc",
@@ -4474,6 +4500,19 @@ dependencies = [
4474
4500
  "web-sys",
4475
4501
  ]
4476
4502
 
4503
+ [[package]]
4504
+ name = "wasm-streams"
4505
+ version = "0.5.0"
4506
+ source = "registry+https://github.com/rust-lang/crates.io-index"
4507
+ checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
4508
+ dependencies = [
4509
+ "futures-util",
4510
+ "js-sys",
4511
+ "wasm-bindgen",
4512
+ "wasm-bindgen-futures",
4513
+ "web-sys",
4514
+ ]
4515
+
4477
4516
  [[package]]
4478
4517
  name = "wasmparser"
4479
4518
  version = "0.244.0"
@@ -4937,7 +4976,7 @@ dependencies = [
4937
4976
  "log",
4938
4977
  "lru",
4939
4978
  "moka",
4940
- "ndarray 0.17.2",
4979
+ "ndarray",
4941
4980
  "num",
4942
4981
  "num-complex",
4943
4982
  "paste",
@@ -5094,13 +5133,13 @@ dependencies = [
5094
5133
 
5095
5134
  [[package]]
5096
5135
  name = "zarrs_object_store"
5097
- version = "0.6.2"
5136
+ version = "0.7.0"
5098
5137
  source = "registry+https://github.com/rust-lang/crates.io-index"
5099
- checksum = "ba1662bcdc585be1923a8b98ee5d6314d19af8c5775d6516a69ca33fd88b46af"
5138
+ checksum = "f39632e2ce9e862f81e45ae3526ae70cb2ceb4ae0e24e9580d85441e75f16a43"
5100
5139
  dependencies = [
5101
5140
  "async-trait",
5102
5141
  "futures",
5103
- "object_store",
5142
+ "object_store 0.14.1",
5104
5143
  "zarrs_storage",
5105
5144
  ]
5106
5145
 
@@ -5118,9 +5157,9 @@ dependencies = [
5118
5157
 
5119
5158
  [[package]]
5120
5159
  name = "zarrs_storage"
5121
- version = "0.4.4"
5160
+ version = "0.4.5"
5122
5161
  source = "registry+https://github.com/rust-lang/crates.io-index"
5123
- checksum = "cf372205f5ab996c7e48ead8c68188c0bc3aaf205f3aa3afe8d7eb8db178a592"
5162
+ checksum = "e13f043c9bd3de69637574f7a2c4b3450f8e310d650fe5c2a78a08d13095cbf9"
5124
5163
  dependencies = [
5125
5164
  "async-trait",
5126
5165
  "auto_impl",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rustytree"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  edition = "2024"
5
5
  rust-version = "1.91.1"
6
6
  license = "Apache-2.0"
@@ -61,7 +61,7 @@ serde = { version = "1", features = ["derive"] }
61
61
  # crc32c) come from zarrs's default features, which we keep enabled.
62
62
  zarrs = { version = "0.23", features = ["async", "zlib"] }
63
63
  zarrs_storage = { version = "0.4", features = ["async"] }
64
- zarrs_object_store = { version = "0.6", features = ["fs", "aws"] }
64
+ zarrs_object_store = { version = "0.7", features = ["fs", "aws"] }
65
65
  serde_json = "1"
66
66
 
67
67
  # icechunk = transactional Zarr v3 storage layer. `zarrs_icechunk` wraps an
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rustytree-xarray
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -10,7 +10,7 @@ build-backend = "maturin"
10
10
  # `-`/`_`/case so they collapse). Users `pip install rustytree-xarray`,
11
11
  # then `import rustytree`.
12
12
  name = "rustytree-xarray"
13
- version = "0.4.0"
13
+ version = "0.5.0"
14
14
  description = "Rust-backed xarray DataTree backend for fast Zarr access from object storage"
15
15
  readme = "README.md"
16
16
  requires-python = ">=3.12"
@@ -8,4 +8,4 @@ plugin discovery) doesn't pay the cdylib load cost upfront.
8
8
  from rustytree.backend import RustytreeBackendEntrypoint
9
9
 
10
10
  __all__ = ["RustytreeBackendEntrypoint"]
11
- __version__ = "0.4.0"
11
+ __version__ = "0.5.0"
@@ -17,6 +17,17 @@ from xarray.backends.common import BackendArray
17
17
  from xarray.core import indexing
18
18
 
19
19
 
20
+ def cast_to_read_dtype(arr: np.ndarray, read_dtype: np.dtype) -> np.ndarray:
21
+ """Cast `arr` to the dtype its read actually materialises, if it doesn't
22
+ already match. A no-op (`astype(..., copy=False)` skips the copy when the
23
+ dtype already matches) for every dtype except vlen `string` (declared
24
+ `object`, read as `StringDType`) — see `RustyBackendArray.__init__`.
25
+ Shared by the lazy read path below and the eager path in `backend.py`,
26
+ which both need the same declared-dtype/read-dtype reconciliation.
27
+ """
28
+ return arr.astype(read_dtype, copy=False)
29
+
30
+
20
31
  class RustyBackendArray(BackendArray):
21
32
  """Lazy view over a Rust-side `ZarrsArrayHandle`.
22
33
 
@@ -92,8 +103,6 @@ class RustyBackendArray(BackendArray):
92
103
  # String-like dtypes come back from Rust as an `object` array of Python
93
104
  # `str` (the `numpy` crate can only build `object` arrays); cast to the
94
105
  # dtype the read materialises — `StringDType` for `string`, `<U…` for
95
- # `fixed_length_utf32`. Numeric reads already match `_read_dtype`, so the
96
- # guard skips the (copying) `astype` for them.
97
- if out.dtype != self._read_dtype:
98
- out = out.astype(self._read_dtype)
99
- return out
106
+ # `fixed_length_utf32`. Numeric reads already match `_read_dtype`, so
107
+ # this is a no-op copy-wise for them.
108
+ return cast_to_read_dtype(out, self._read_dtype)
@@ -43,7 +43,7 @@ from xarray.core.dataset import Dataset
43
43
  from xarray.core.datatree import DataTree
44
44
  from xarray.core.variable import Variable
45
45
 
46
- from rustytree._array import RustyBackendArray
46
+ from rustytree._array import RustyBackendArray, cast_to_read_dtype
47
47
 
48
48
  ROOT = "/"
49
49
 
@@ -360,12 +360,15 @@ class _RustyDataStore(AbstractDataStore):
360
360
  # Phase C may have pre-fetched the variable's full contents
361
361
  # (1-D self-named dim coords + CF time-likes); other vars
362
362
  # stay lazy through `RustyBackendArray`.
363
- data: Any = (
364
- var["data"]
365
- if "data" in var
366
- else indexing.LazilyIndexedArray(RustyBackendArray(var["handle"]))
367
- )
368
363
  handle = var["handle"]
364
+ if "data" in var:
365
+ # Eager path (Phase C): eager vars bypass `RustyBackendArray`
366
+ # entirely, so the declared-dtype/read-dtype reconciliation
367
+ # (`object`-declared/`StringDType`-materialized vlen strings,
368
+ # added for #71) has to be applied here explicitly instead.
369
+ data: Any = cast_to_read_dtype(var["data"], np.dtype(handle.read_dtype))
370
+ else:
371
+ data = indexing.LazilyIndexedArray(RustyBackendArray(handle))
369
372
  chunks = tuple(handle.chunks)
370
373
  attrs = dict(var["attrs"])
371
374
  # Mirror xarray's zarr backend: decode a base64 str/bytes `_FillValue`
@@ -449,13 +449,25 @@ fn strings_to_object_pyarray<'py>(
449
449
  request_shape: &[u64],
450
450
  ) -> PyResult<Bound<'py, PyAny>> {
451
451
  let sliced = slice_nd(strings, aligned_shape, offsets, request_shape);
452
+ strings_to_pyobject_array(py, &sliced)
453
+ }
454
+
455
+ /// Build a flat 1-D numpy `object` array of `PyString`s from a string slice.
456
+ /// Shared tail of [`strings_to_object_pyarray`] (the lazy, possibly-sliced
457
+ /// read path) and Phase C's eager-fetch path (`lib.rs::eager_to_pyarray`,
458
+ /// which reads the whole array and reshapes separately, so needs no slicing
459
+ /// here).
460
+ pub(crate) fn strings_to_pyobject_array<'py>(
461
+ py: Python<'py>,
462
+ strings: &[String],
463
+ ) -> PyResult<Bound<'py, PyAny>> {
452
464
  // `from_slice` (not `from_vec`): for object dtype it clones each ref into a
453
465
  // numpy-owned buffer, so numpy and the local `objs` Vec own their
454
466
  // references independently — no double-decref hazard if the array is later
455
467
  // mutated. One incref/element, negligible at coord/scalar sizes.
456
- let objs: Vec<Py<PyAny>> = sliced
457
- .into_iter()
458
- .map(|s| PyString::new(py, &s).into_any().unbind())
468
+ let objs: Vec<Py<PyAny>> = strings
469
+ .iter()
470
+ .map(|s| PyString::new(py, s).into_any().unbind())
459
471
  .collect();
460
472
  PyArray1::from_slice(py, &objs).into_bound_py_any(py)
461
473
  }