From aa79f2d8d81a8b67910b44d27e902ea6ed4eaf36 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 12:23:10 +0200 Subject: [PATCH 1/7] exclude notimplementederrors from test coverage --- src/zarr/abc/codec.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zarr/abc/codec.py b/src/zarr/abc/codec.py index f8a5447a70..01c164a303 100644 --- a/src/zarr/abc/codec.py +++ b/src/zarr/abc/codec.py @@ -114,7 +114,7 @@ def validate( """ async def _decode_single(self, chunk_data: CodecOutput, chunk_spec: ArraySpec) -> CodecInput: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def decode( self, @@ -137,7 +137,7 @@ async def decode( async def _encode_single( self, chunk_data: CodecInput, chunk_spec: ArraySpec ) -> CodecOutput | None: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def encode( self, @@ -218,7 +218,7 @@ async def _encode_partial_single( selection: SelectorTuple, chunk_spec: ArraySpec, ) -> None: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def encode_partial( self, From 85665e04d6e2184593ce53c051a59a60d9aaf2f9 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 14:05:59 +0200 Subject: [PATCH 2/7] add tests for untested features of api.asynchronous --- src/zarr/api/asynchronous.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zarr/api/asynchronous.py b/src/zarr/api/asynchronous.py index 78b68caf73..8836edcb58 100644 --- a/src/zarr/api/asynchronous.py +++ b/src/zarr/api/asynchronous.py @@ -363,7 +363,6 @@ async def open( except (AssertionError, FileNotFoundError, NodeTypeValidationError): pass return await open_group(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) - try: return await open_array(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) except (KeyError, NodeTypeValidationError): From 83799dfd82b3055ca177160d73f679d4e313bd5e Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 14:07:22 +0200 Subject: [PATCH 3/7] add tests for untested features of api.asynchronous --- tests/test_api/test_asynchronous.py | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tests/test_api/test_asynchronous.py diff --git a/tests/test_api/test_asynchronous.py b/tests/test_api/test_asynchronous.py new file mode 100644 index 0000000000..42eca8e34b --- /dev/null +++ b/tests/test_api/test_asynchronous.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import json +from dataclasses import dataclass + +import numpy as np +import pytest + +from zarr import create_array +from zarr.api.asynchronous import ArrayLike, _get_shape_chunks, _like_args, open +from zarr.core.buffer.core import default_buffer_prototype + + +@dataclass +class WithShape: + shape: tuple[int, ...] + + +@dataclass +class WithChunks(WithShape): + chunks: tuple[int, ...] + + +@dataclass +class WithChunkLen(WithShape): + chunklen: int + + +@pytest.mark.parametrize( + ("observed", "expected"), + [ + ({}, (None, None)), + (WithShape(shape=(1, 2)), ((1, 2), None)), + (WithChunks(shape=(1, 2), chunks=(1, 2)), ((1, 2), (1, 2))), + (WithChunkLen(shape=(10, 10), chunklen=1), ((10, 10), (1, 10))), + ], +) +def test_get_shape_chunks( + observed: object, expected: tuple[tuple[int, ...] | None, tuple[int, ...] | None] +) -> None: + """ + Test the _get_shape_chunks function + """ + assert _get_shape_chunks(observed) == expected + + +@pytest.mark.parametrize( + ("observed", "expected"), + [ + (np.arange(10, dtype="int"), {"shape": (10,), "dtype": np.dtype("int64")}), + (WithChunks(shape=(1, 2), chunks=(1, 2)), {"chunks": (1, 2), "shape": (1, 2)}), + ( + create_array( + {}, + chunks=(10,), + shape=(100,), + dtype="f8", + compressors=None, + filters=None, + zarr_format=2, + )._async_array, + { + "chunks": (10,), + "shape": (100,), + "dtype": np.dtype("f8"), + "compressor": None, + "filters": None, + "order": "C", + }, + ), + ], +) +def test_like_args(observed: ArrayLike, expected: object) -> None: + """ + Test the like_args function + """ + assert _like_args(observed, {}) == expected + + +async def test_open_no_array() -> None: + """ + Test that zarr.api.asynchronous.open attempts to open a group when is no array found, but shape was specified in kwargs. + This behavior makes no sense but we should still test it. + """ + store = { + "zarr.json": default_buffer_prototype().buffer.from_bytes( + json.dumps({"zarr_format": 3, "node_type": "group"}).encode("utf-8") + ) + } + with pytest.raises( + TypeError, match=r"open_group\(\) got an unexpected keyword argument 'shape'" + ): + await open(store=store, shape=(1,)) From d828ac7afff32b7d433338ff2c4bff2c1763f9f8 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 14:08:32 +0200 Subject: [PATCH 4/7] remove whitespace removal --- src/zarr/api/asynchronous.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zarr/api/asynchronous.py b/src/zarr/api/asynchronous.py index 8836edcb58..78b68caf73 100644 --- a/src/zarr/api/asynchronous.py +++ b/src/zarr/api/asynchronous.py @@ -363,6 +363,7 @@ async def open( except (AssertionError, FileNotFoundError, NodeTypeValidationError): pass return await open_group(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) + try: return await open_array(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) except (KeyError, NodeTypeValidationError): From 4b40f2e29644dd7d6dc1352fc95d596fe1d68085 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 14:22:17 +0200 Subject: [PATCH 5/7] fix import of arraylike --- tests/test_api/test_asynchronous.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/test_api/test_asynchronous.py b/tests/test_api/test_asynchronous.py index 42eca8e34b..5211b9f428 100644 --- a/tests/test_api/test_asynchronous.py +++ b/tests/test_api/test_asynchronous.py @@ -2,14 +2,23 @@ import json from dataclasses import dataclass +from typing import TYPE_CHECKING import numpy as np import pytest from zarr import create_array -from zarr.api.asynchronous import ArrayLike, _get_shape_chunks, _like_args, open +from zarr.api.asynchronous import _get_shape_chunks, _like_args, open from zarr.core.buffer.core import default_buffer_prototype +if TYPE_CHECKING: + from typing import Any + + import numpy.typing as npt + + from zarr.core.array import Array, AsyncArray + from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata + @dataclass class WithShape: @@ -70,7 +79,10 @@ def test_get_shape_chunks( ), ], ) -def test_like_args(observed: ArrayLike, expected: object) -> None: +def test_like_args( + observed: AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata] | Array | npt.NDArray[Any], + expected: object, +) -> None: """ Test the like_args function """ From 9117776d6db07b5eeae9dcaacb7725451ab71f83 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Wed, 6 Aug 2025 14:39:54 +0200 Subject: [PATCH 6/7] be more explicit about the data type --- tests/test_api/test_asynchronous.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api/test_asynchronous.py b/tests/test_api/test_asynchronous.py index 5211b9f428..35c803ad25 100644 --- a/tests/test_api/test_asynchronous.py +++ b/tests/test_api/test_asynchronous.py @@ -56,7 +56,7 @@ def test_get_shape_chunks( @pytest.mark.parametrize( ("observed", "expected"), [ - (np.arange(10, dtype="int"), {"shape": (10,), "dtype": np.dtype("int64")}), + (np.arange(10, dtype=np.dtype("int64")), {"shape": (10,), "dtype": np.dtype("int64")}), (WithChunks(shape=(1, 2), chunks=(1, 2)), {"chunks": (1, 2), "shape": (1, 2)}), ( create_array( From 9d13b60a8c9c342cdf12dfd9109466c5e0a482da Mon Sep 17 00:00:00 2001 From: Davis Bennett Date: Sun, 17 Aug 2025 19:58:01 +0200 Subject: [PATCH 7/7] Update tests/test_api/test_asynchronous.py Co-authored-by: Tom Augspurger --- tests/test_api/test_asynchronous.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api/test_asynchronous.py b/tests/test_api/test_asynchronous.py index 35c803ad25..910fd2883c 100644 --- a/tests/test_api/test_asynchronous.py +++ b/tests/test_api/test_asynchronous.py @@ -91,7 +91,7 @@ def test_like_args( async def test_open_no_array() -> None: """ - Test that zarr.api.asynchronous.open attempts to open a group when is no array found, but shape was specified in kwargs. + Test that zarr.api.asynchronous.open attempts to open a group when no array is found, but shape was specified in kwargs. This behavior makes no sense but we should still test it. """ store = {