|
44 | 44 | default_serializer_v3, |
45 | 45 | ) |
46 | 46 | from zarr.core.buffer import NDArrayLike, NDArrayLikeOrScalar, default_buffer_prototype |
47 | | -from zarr.core.chunk_grids import _auto_partition |
| 47 | +from zarr.core.chunk_grids import RegularChunkGrid, _auto_partition |
48 | 48 | from zarr.core.chunk_key_encodings import ChunkKeyEncodingParams |
49 | 49 | from zarr.core.common import JSON, ZarrFormat, ceildiv |
50 | 50 | from zarr.core.dtype import ( |
|
80 | 80 |
|
81 | 81 | if TYPE_CHECKING: |
82 | 82 | from zarr.abc.codec import CodecJSON_V3 |
83 | | - from zarr.core.metadata.v3 import ArrayV3Metadata |
84 | 83 |
|
85 | 84 |
|
86 | 85 | @pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=["store"]) |
@@ -1451,6 +1450,74 @@ async def test_v2_no_shards(store: Store) -> None: |
1451 | 1450 | zarr_format=2, |
1452 | 1451 | ) |
1453 | 1452 |
|
| 1453 | + @staticmethod |
| 1454 | + async def test_v2_rejects_rectilinear_chunk_grid(store: Store) -> None: |
| 1455 | + """ |
| 1456 | + Test that creating a Zarr v2 array with RectilinearChunkGrid (nested chunks) raises an error. |
| 1457 | + Zarr v2 only supports RegularChunkGrid. |
| 1458 | + """ |
| 1459 | + msg = "Variable chunks.*only supported in Zarr format 3" |
| 1460 | + with pytest.raises(ValueError, match=msg): |
| 1461 | + _ = await create_array( |
| 1462 | + store=store, |
| 1463 | + dtype="uint8", |
| 1464 | + shape=(30, 20), |
| 1465 | + chunks=[[10, 10, 10], [5, 5, 5, 5]], # RectilinearChunkGrid |
| 1466 | + zarr_format=2, |
| 1467 | + ) |
| 1468 | + |
| 1469 | + @staticmethod |
| 1470 | + async def test_shards_dict_config(store: Store) -> None: |
| 1471 | + """ |
| 1472 | + Test that creating an array with dict-based shards configuration works. |
| 1473 | + This tests the code path where shards is a dict (lines 4760-4762 in array.py). |
| 1474 | + """ |
| 1475 | + from typing import cast |
| 1476 | + |
| 1477 | + from zarr.core.array import ShardsConfigParam |
| 1478 | + |
| 1479 | + arr = await create_array( |
| 1480 | + store=store, |
| 1481 | + dtype="uint8", |
| 1482 | + shape=(100, 100), |
| 1483 | + chunks=(10, 10), |
| 1484 | + shards=cast(ShardsConfigParam, {"shape": (20, 20)}), |
| 1485 | + zarr_format=3, |
| 1486 | + ) |
| 1487 | + # With sharding, chunk_grid represents the outer shard structure |
| 1488 | + assert isinstance(arr.metadata.chunk_grid, RegularChunkGrid) |
| 1489 | + assert arr.metadata.chunk_grid.chunk_shape == (20, 20) |
| 1490 | + # Verify sharding codec was applied with inner chunks (10, 10) |
| 1491 | + assert isinstance(arr.metadata, ArrayV3Metadata) |
| 1492 | + sharding_codecs = [c for c in arr.metadata.codecs if hasattr(c, "chunk_shape")] |
| 1493 | + assert len(sharding_codecs) == 1 |
| 1494 | + # Inner chunks (from chunks parameter) are stored in the sharding codec |
| 1495 | + assert sharding_codecs[0].chunk_shape == (10, 10) |
| 1496 | + |
| 1497 | + @staticmethod |
| 1498 | + async def test_shards_auto(store: Store) -> None: |
| 1499 | + """ |
| 1500 | + Test that creating an array with auto shards works. |
| 1501 | + This tests the code path where shards == "auto" (lines 4763-4770 in array.py). |
| 1502 | +
|
| 1503 | + Note: Auto sharding may or may not apply sharding depending on the heuristics. |
| 1504 | + This test just verifies the code path executes without error. |
| 1505 | + """ |
| 1506 | + arr = await create_array( |
| 1507 | + store=store, |
| 1508 | + dtype="uint8", |
| 1509 | + shape=(1000, 1000), |
| 1510 | + chunks=(10, 10), |
| 1511 | + shards="auto", |
| 1512 | + zarr_format=3, |
| 1513 | + ) |
| 1514 | + # Array should be created successfully |
| 1515 | + assert isinstance(arr.metadata.chunk_grid, RegularChunkGrid) |
| 1516 | + chunk_shape = arr.metadata.chunk_grid.chunk_shape |
| 1517 | + assert chunk_shape is not None |
| 1518 | + assert isinstance(chunk_shape, tuple) |
| 1519 | + assert len(chunk_shape) == 2 |
| 1520 | + |
1454 | 1521 | @staticmethod |
1455 | 1522 | @pytest.mark.parametrize("impl", ["sync", "async"]) |
1456 | 1523 | async def test_with_data(impl: Literal["sync", "async"], store: Store) -> None: |
|
0 commit comments