diff --git a/changes/4305.bugfix.md b/changes/4305.bugfix.md new file mode 100644 index 0000000000..13221d8e3b --- /dev/null +++ b/changes/4305.bugfix.md @@ -0,0 +1 @@ +Fixed an infinite loop when creating a 0-dimensional array with `shards="auto"` while the `array.target_shard_size_bytes` config option is set. Such arrays now resolve to `shards=()`, matching the behavior when no shard size target is configured. diff --git a/src/zarr/core/chunk_grids.py b/src/zarr/core/chunk_grids.py index 584829bc6c..5e19364cae 100644 --- a/src/zarr/core/chunk_grids.py +++ b/src/zarr/core/chunk_grids.py @@ -865,6 +865,8 @@ def _guess_num_chunks_per_axis_shard( if max_bytes < bytes_per_chunk: return 1 num_axes = len(chunk_shape) + if num_axes == 0: + return 1 chunks_per_shard = 1 # First check for byte size, second check to make sure we don't go bigger than the array shape while (bytes_per_chunk * ((chunks_per_shard + 1) ** num_axes)) <= max_bytes and all( diff --git a/tests/test_chunk_grids.py b/tests/test_chunk_grids.py index 4640c43d1c..4c3c437eb2 100644 --- a/tests/test_chunk_grids.py +++ b/tests/test_chunk_grids.py @@ -3,14 +3,17 @@ import numpy as np import pytest +import zarr from tests.conftest import Expect, ExpectFail from zarr.core.chunk_grids import ( ChunkLayout, + _guess_num_chunks_per_axis_shard, _guess_regular_chunks, normalize_chunks_1d, normalize_chunks_nd, resolve_outer_and_inner_chunks, ) +from zarr.errors import ZarrUserWarning def _assert_chunks_equal( @@ -277,3 +280,26 @@ def test_normalize_chunks_1d_returns_int64_array( assert result.dtype == np.int64 assert result.ndim == 1 assert result.tolist() == case.output + + +def test_guess_num_chunks_per_axis_shard_0d() -> None: + """Regression test for https://github.com/zarr-developers/zarr-python/issues/4304.""" + assert ( + _guess_num_chunks_per_axis_shard( + chunk_shape=(), item_size=8, max_bytes=128 * 1024 * 1024, array_shape=() + ) + == 1 + ) + + +def test_create_0d_array_auto_shards_with_target_shard_size() -> None: + """A 0-dimensional array with shards="auto" and a shard size budget must not hang. + + Regression test for https://github.com/zarr-developers/zarr-python/issues/4304. + """ + with ( + zarr.config.set({"array.target_shard_size_bytes": 128 * 1024 * 1024}), + pytest.warns(ZarrUserWarning, match="Automatic shard shape inference is experimental"), + ): + arr = zarr.create_array(store={}, shape=(), dtype="int64", shards="auto") + assert arr.shards == ()