Skip to content

Commit 372704e

Browse files
committed
special type for array.chunks
1 parent b55cb8e commit 372704e

7 files changed

Lines changed: 411 additions & 46 deletions

File tree

src/zarr/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
zeros_like,
3636
)
3737
from zarr.core.array import Array, AsyncArray
38+
from zarr.core.chunk_grids import ChunksType, RectilinearChunks, RegularChunks
3839
from zarr.core.config import config
3940
from zarr.core.group import AsyncGroup, Group
4041

@@ -147,7 +148,10 @@ def set_format(log_format: str) -> None:
147148
"Array",
148149
"AsyncArray",
149150
"AsyncGroup",
151+
"ChunksType",
150152
"Group",
153+
"RectilinearChunks",
154+
"RegularChunks",
151155
"__version__",
152156
"array",
153157
"config",

src/zarr/core/array.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
from zarr.core.chunk_grids import (
4444
ChunkGrid,
4545
ChunksLike,
46+
ChunksType,
4647
RegularChunkGrid,
48+
RegularChunks,
4749
_auto_partition,
4850
_normalize_chunks,
4951
resolve_chunk_spec,
@@ -1050,20 +1052,33 @@ def shape(self) -> tuple[int, ...]:
10501052
return self.metadata.shape
10511053

10521054
@property
1053-
def chunks(self) -> tuple[int, ...] | tuple[tuple[int, ...], ...]:
1055+
def chunks(self) -> ChunksType:
10541056
"""Returns the chunk specification of the Array.
10551057
1056-
For arrays using RegularChunkGrid: returns a tuple of ints representing
1057-
the uniform chunk shape. If sharding is used, the inner chunk shape is returned.
1058+
Returns either RegularChunks (for uniform chunk sizes) or RectilinearChunks
1059+
(for variable chunk sizes per dimension). Both types behave like tuples but
1060+
provide richer semantics including named access when dimension_names are available.
10581061
1059-
For arrays using RectilinearChunkGrid: returns a tuple of tuples, where
1060-
each inner tuple contains the chunk sizes along that dimension (not RLE encoded).
1062+
For arrays using RegularChunkGrid: returns RegularChunks with uniform chunk sizes.
1063+
If sharding is used, the inner chunk shape is returned.
1064+
1065+
For arrays using RectilinearChunkGrid: returns RectilinearChunks where each
1066+
element is a tuple containing the chunk sizes along that dimension (not RLE encoded).
10611067
10621068
Returns
10631069
-------
1064-
tuple[int, ...] | tuple[tuple[int, ...], ...]
1065-
For regular chunks: (chunk_size_dim0, chunk_size_dim1, ...)
1066-
For rectilinear chunks: ((sizes_dim0), (sizes_dim1), ...)
1070+
ChunksType
1071+
RegularChunks for regular chunks or RectilinearChunks for variable chunks
1072+
1073+
Examples
1074+
--------
1075+
>>> arr = zarr.create_array(shape=(100, 200), chunks=(10, 20))
1076+
>>> arr.chunks
1077+
RegularChunks((10, 20))
1078+
>>> isinstance(arr.chunks, RegularChunks)
1079+
True
1080+
>>> tuple(arr.chunks)
1081+
(10, 20)
10671082
"""
10681083
return self.metadata.chunks
10691084

@@ -1274,11 +1289,10 @@ def _chunk_grid_shape(self) -> tuple[int, ...]:
12741289
# Handle 0-dimensional arrays
12751290
if len(chunks) == 0:
12761291
return ()
1277-
# For RegularChunkGrid (or sharded with RegularChunkGrid), chunks is tuple[int, ...]
1278-
if isinstance(chunks[0], int):
1292+
# For RegularChunkGrid (or sharded), use RegularChunks type check
1293+
if isinstance(chunks, RegularChunks):
12791294
return tuple(starmap(ceildiv, zip(self.shape, chunks, strict=True)))
1280-
# For RectilinearChunkGrid, chunks is tuple[tuple[int, ...], ...]
1281-
# Use the chunk_grid method
1295+
# For RectilinearChunkGrid, use the chunk_grid method
12821296
return self.metadata.chunk_grid.get_chunk_grid_shape(self.shape)
12831297

12841298
@property
@@ -1292,7 +1306,7 @@ def _shard_grid_shape(self) -> tuple[int, ...]:
12921306
The shape of the shard grid for this array.
12931307
"""
12941308
if self.shards is None:
1295-
shard_shape = self.chunks
1309+
shard_shape: tuple[int, ...] | ChunksType = self.chunks
12961310
else:
12971311
shard_shape = self.shards
12981312
return tuple(starmap(ceildiv, zip(self.shape, shard_shape, strict=True)))
@@ -5624,16 +5638,15 @@ def _iter_shard_regions(
56245638
If the array uses RectilinearChunkGrid (variable-sized chunks).
56255639
"""
56265640
chunks = array.chunks
5627-
if chunks and not isinstance(chunks[0], int):
5641+
if not isinstance(chunks, RegularChunks):
56285642
raise NotImplementedError(
56295643
"_iter_shard_regions is not supported for arrays with variable-sized chunks "
56305644
"(RectilinearChunkGrid). Use the chunk_grid API directly for variable chunk access."
56315645
)
56325646

5633-
# After the check above, chunks is tuple[int, ...]
5634-
regular_chunks = cast(tuple[int, ...], chunks)
5647+
# Type narrowing: chunks is now RegularChunks (subclass of tuple[int, ...])
56355648
if array.shards is None:
5636-
shard_shape: Sequence[int] = regular_chunks
5649+
shard_shape: Sequence[int] = chunks
56375650
else:
56385651
shard_shape = array.shards
56395652

@@ -5673,17 +5686,16 @@ def _iter_chunk_regions(
56735686
If the array uses RectilinearChunkGrid (variable-sized chunks).
56745687
"""
56755688
chunks = array.chunks
5676-
if chunks and not isinstance(chunks[0], int):
5689+
if not isinstance(chunks, RegularChunks):
56775690
raise NotImplementedError(
56785691
"_iter_chunk_regions is not supported for arrays with variable-sized chunks "
56795692
"(RectilinearChunkGrid). Use the chunk_grid API directly for variable chunk access."
56805693
)
56815694

5682-
# After the check above, chunks is tuple[int, ...]
5683-
regular_chunks = cast(tuple[int, ...], chunks)
5695+
# Type narrowing: chunks is now RegularChunks (subclass of tuple[int, ...])
56845696
return _iter_regions(
56855697
array.shape,
5686-
regular_chunks,
5698+
chunks,
56875699
origin=origin,
56885700
selection_shape=selection_shape,
56895701
trim_excess=True,

0 commit comments

Comments
 (0)