From c9aedcd41788c5e5866e8f7b324f566b46f49c63 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Sun, 29 Sep 2024 20:43:07 -0500 Subject: [PATCH 1/2] Fixed ArrayV2Metadata parameter names For things like dataclasses.repalce to work, we need the parameter names to match the attribute names. All the name change between what we have in memory and what the specs requires should happen during serialization / deserialization. Closes https://github.com/zarr-developers/zarr-python/issues/2269 --- src/zarr/core/array.py | 4 ++-- src/zarr/core/common.py | 8 +++++++- src/zarr/core/metadata/v2.py | 11 +++++++---- tests/v3/test_v2.py | 13 +++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/zarr/core/array.py b/src/zarr/core/array.py index e1de15c747..e48ff8797e 100644 --- a/src/zarr/core/array.py +++ b/src/zarr/core/array.py @@ -372,8 +372,8 @@ async def _create_v2( metadata = ArrayV2Metadata( shape=shape, - dtype=np.dtype(dtype), - chunks=chunks, + data_type=np.dtype(dtype), + chunk_grid=chunks, order=order, dimension_separator=dimension_separator, fill_value=0 if fill_value is None else fill_value, diff --git a/src/zarr/core/common.py b/src/zarr/core/common.py index 80c743cc90..5e29399cad 100644 --- a/src/zarr/core/common.py +++ b/src/zarr/core/common.py @@ -19,6 +19,8 @@ if TYPE_CHECKING: from collections.abc import Awaitable, Callable, Iterator + from zarr.core.chunk_grids import RegularChunkGrid + ZARR_JSON = "zarr.json" ZARRAY_JSON = ".zarray" @@ -133,11 +135,15 @@ def parse_named_configuration( return name_parsed, configuration_parsed -def parse_shapelike(data: int | Iterable[int]) -> tuple[int, ...]: +def parse_shapelike(data: int | Iterable[int] | RegularChunkGrid) -> tuple[int, ...]: + from zarr.core.chunk_grids import RegularChunkGrid + if isinstance(data, int): if data < 0: raise ValueError(f"Expected a non-negative integer. Got {data} instead") return (data,) + elif isinstance(data, RegularChunkGrid): + return data.chunk_shape try: data_tuple = tuple(data) except TypeError as e: diff --git a/src/zarr/core/metadata/v2.py b/src/zarr/core/metadata/v2.py index df7f2abaea..59298727b0 100644 --- a/src/zarr/core/metadata/v2.py +++ b/src/zarr/core/metadata/v2.py @@ -43,8 +43,8 @@ def __init__( self, *, shape: ChunkCoords, - dtype: npt.DTypeLike, - chunks: ChunkCoords, + data_type: npt.DTypeLike, + chunk_grid: ChunkCoords, fill_value: Any, order: Literal["C", "F"], dimension_separator: Literal[".", "/"] = ".", @@ -56,8 +56,8 @@ def __init__( Metadata for a Zarr version 2 array. """ shape_parsed = parse_shapelike(shape) - data_type_parsed = parse_dtype(dtype) - chunks_parsed = parse_shapelike(chunks) + data_type_parsed = parse_dtype(data_type) + chunks_parsed = parse_shapelike(chunk_grid) compressor_parsed = parse_compressor(compressor) order_parsed = parse_indexing_order(order) dimension_separator_parsed = parse_separator(dimension_separator) @@ -140,6 +140,9 @@ def from_dict(cls, data: dict[str, Any]) -> ArrayV2Metadata: _data = data.copy() # check that the zarr_format attribute is correct _ = parse_zarr_format(_data.pop("zarr_format")) + + _data["chunk_grid"] = _data.pop("chunks") + _data["data_type"] = _data.pop("dtype") return cls(**_data) def to_dict(self) -> dict[str, JSON]: diff --git a/tests/v3/test_v2.py b/tests/v3/test_v2.py index 943c425f54..9e05ba4b7c 100644 --- a/tests/v3/test_v2.py +++ b/tests/v3/test_v2.py @@ -46,3 +46,16 @@ def test_codec_pipeline() -> None: result = array[:] expected = np.ones(1) np.testing.assert_array_equal(result, expected) + + +def test_attrs(store: StorePath) -> None: + data = np.arange(0, 8, dtype="uint16") + a = Array.create( + store / "simple_v2", + zarr_format=2, + shape=data.shape, + chunks=(4,), + dtype=data.dtype, + fill_value=0, + ) + a.attrs.put({"key": 0}) From 74a45c6be034affc41ae2a0bada8bc887a0057da Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 8 Oct 2024 09:24:51 -0500 Subject: [PATCH 2/2] fixup --- src/zarr/core/metadata/v2.py | 2 +- tests/v3/test_metadata/test_v2.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zarr/core/metadata/v2.py b/src/zarr/core/metadata/v2.py index 67f37edca4..e1b4946706 100644 --- a/src/zarr/core/metadata/v2.py +++ b/src/zarr/core/metadata/v2.py @@ -144,7 +144,7 @@ def from_dict(cls, data: dict[str, Any]) -> ArrayV2Metadata: _data["chunk_grid"] = _data.pop("chunks") _data["data_type"] = _data.pop("dtype") - dtype = parse_dtype(_data["dtype"]) + dtype = parse_dtype(_data["data_type"]) if dtype.kind in "SV": fill_value_encoded = _data.get("fill_value") diff --git a/tests/v3/test_metadata/test_v2.py b/tests/v3/test_metadata/test_v2.py index 4cd222d812..070becfb05 100644 --- a/tests/v3/test_metadata/test_v2.py +++ b/tests/v3/test_metadata/test_v2.py @@ -92,8 +92,8 @@ def test_from_dict_extra_fields() -> None: expected = ArrayV2Metadata( attributes={"key": "value"}, shape=(8,), - dtype="float64", - chunks=(8,), + data_type="float64", + chunk_grid=(8,), fill_value=0.0, order="C", )