Skip to content

Commit ed1f3a6

Browse files
committed
Fix unreleased bug in DataTree.to_zarr() with mode='r+'
Writing to zarr with `mode='r+'` was broken by pydata#10625, due to a Zarr bug (zarr-developers/zarr-python#3428). This add a work-around that works on older versions of Zarr. The PR that introduced this bug has not yet appeared in an xarray release, so there's no need for a release note.
1 parent 722f0ad commit ed1f3a6

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

xarray/core/datatree_io.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,13 @@ def _datatree_to_zarr(
211211
writer = ArrayWriter()
212212

213213
try:
214-
for node in dt.subtree:
214+
for rel_path, node in dt.subtree_with_keys:
215215
at_root = node is dt
216216
dataset = node.to_dataset(inherit=write_inherited_coords or at_root)
217-
node_store = (
218-
root_store if at_root else root_store.get_child_store(node.path)
219-
)
217+
# Use a relative path for group, because absolute paths are broken
218+
# with consolidated metadata in zarr 3.1.2 and earlier:
219+
# https://github.com/zarr-developers/zarr-python/pull/3428
220+
node_store = root_store if at_root else root_store.get_child_store(rel_path)
220221

221222
dataset = node_store._validate_and_autodetect_region(dataset)
222223
node_store._validate_encoding(encoding)

xarray/tests/test_backends_datatree.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,16 @@ def assert_expected_zarr_files_exist(
804804
with open_datatree(str(storepath), engine="zarr") as written_dt:
805805
assert_identical(written_dt, original_dt)
806806

807+
def test_rplus_mode(
808+
self, tmp_path: Path, simple_datatree: DataTree, zarr_format: Literal[2, 3]
809+
) -> None:
810+
storepath = tmp_path / "test.zarr"
811+
original_dt = simple_datatree.chunk()
812+
original_dt.to_zarr(storepath, compute=False, zarr_format=zarr_format)
813+
original_dt.to_zarr(storepath, mode="r+")
814+
with open_datatree(str(storepath), engine="zarr") as written_dt:
815+
assert_identical(written_dt, original_dt)
816+
807817
@requires_dask
808818
def test_to_zarr_no_redundant_computation(self, tmpdir, zarr_format) -> None:
809819
import dask.array as da

0 commit comments

Comments
 (0)