Skip to content

Commit 519f05e

Browse files
rabernatshoyerjhammandcherian
authored
Use zarr v3 dimension_names (#9669)
* use zarr v3 dimension_names * Update xarray/backends/zarr.py Co-authored-by: Stephan Hoyer <[email protected]> * Update xarray/backends/zarr.py Co-authored-by: Joe Hamman <[email protected]> --------- Co-authored-by: Stephan Hoyer <[email protected]> Co-authored-by: Joe Hamman <[email protected]> Co-authored-by: Deepak Cherian <[email protected]> Co-authored-by: Joe Hamman <[email protected]>
1 parent 5b2e6f1 commit 519f05e

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

xarray/backends/zarr.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,18 @@ def _determine_zarr_chunks(
308308

309309

310310
def _get_zarr_dims_and_attrs(zarr_obj, dimension_key, try_nczarr):
311+
# Zarr V3 explicitly stores the dimension names in the metadata
312+
try:
313+
# if this exists, we are looking at a Zarr V3 array
314+
# convert None to empty tuple
315+
dimensions = zarr_obj.metadata.dimension_names or ()
316+
except AttributeError:
317+
# continue to old code path
318+
pass
319+
else:
320+
attributes = dict(zarr_obj.attrs)
321+
return dimensions, attributes
322+
311323
# Zarr arrays do not have dimensions. To get around this problem, we add
312324
# an attribute that specifies the dimension. We have to hide this attribute
313325
# when we send the attributes to the user.
@@ -919,6 +931,7 @@ def set_variables(self, variables, check_encoding_set, writer, unlimited_dims=No
919931
import zarr
920932

921933
existing_keys = tuple(self.zarr_group.array_keys())
934+
is_zarr_v3_format = _zarr_v3() and self.zarr_group.metadata.zarr_format == 3
922935

923936
for vn, v in variables.items():
924937
name = _encode_variable_name(vn)
@@ -1022,7 +1035,10 @@ def set_variables(self, variables, check_encoding_set, writer, unlimited_dims=No
10221035
# new variable
10231036
encoded_attrs = {}
10241037
# the magic for storing the hidden dimension data
1025-
encoded_attrs[DIMENSION_KEY] = dims
1038+
if is_zarr_v3_format:
1039+
encoding["dimension_names"] = dims
1040+
else:
1041+
encoded_attrs[DIMENSION_KEY] = dims
10261042
for k2, v2 in attrs.items():
10271043
encoded_attrs[k2] = self.encode_attribute(v2)
10281044

xarray/tests/test_backends.py

+12
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,8 @@ def test_drop_encoding(self):
25592559
ds.to_zarr(store, encoding=encodings)
25602560

25612561
def test_hidden_zarr_keys(self) -> None:
2562+
skip_if_zarr_format_3("This test is unnecessary; no hidden Zarr keys")
2563+
25622564
expected = create_test_data()
25632565
with self.create_store() as store:
25642566
expected.dump_to_store(store)
@@ -2586,6 +2588,16 @@ def test_hidden_zarr_keys(self) -> None:
25862588
with xr.decode_cf(store):
25872589
pass
25882590

2591+
def test_dimension_names(self) -> None:
2592+
skip_if_zarr_format_2("No dimension names in V2")
2593+
2594+
expected = create_test_data()
2595+
with self.create_store() as store:
2596+
expected.dump_to_store(store)
2597+
zarr_group = store.ds
2598+
for var in zarr_group:
2599+
assert expected[var].dims == zarr_group[var].metadata.dimension_names
2600+
25892601
@pytest.mark.parametrize("group", [None, "group1"])
25902602
def test_write_persistence_modes(self, group) -> None:
25912603
original = create_test_data()

0 commit comments

Comments
 (0)