4242from zarr .core .buffer .cpu import buffer_prototype as cpu_buffer_prototype
4343from zarr .core .chunk_grids import (
4444 ChunkGrid ,
45+ ChunksLike ,
4546 RegularChunkGrid ,
4647 _auto_partition ,
4748 _normalize_chunks ,
@@ -1048,17 +1049,20 @@ def shape(self) -> tuple[int, ...]:
10481049 return self .metadata .shape
10491050
10501051 @property
1051- def chunks (self ) -> tuple [int , ...]:
1052- """Returns the chunk shape of the Array.
1053- If sharding is used the inner chunk shape is returned.
1052+ def chunks (self ) -> tuple [int , ...] | tuple [tuple [int , ...], ...]:
1053+ """Returns the chunk specification of the Array.
10541054
1055- Only defined for arrays using using `RegularChunkGrid`.
1056- If array doesn't use `RegularChunkGrid`, `NotImplementedError` is raised.
1055+ For arrays using RegularChunkGrid: returns a tuple of ints representing
1056+ the uniform chunk shape. If sharding is used, the inner chunk shape is returned.
1057+
1058+ For arrays using RectilinearChunkGrid: returns a tuple of tuples, where
1059+ each inner tuple contains the chunk sizes along that dimension (not RLE encoded).
10571060
10581061 Returns
10591062 -------
1060- tuple[int, ...]:
1061- The chunk shape of the Array.
1063+ tuple[int, ...] | tuple[tuple[int, ...], ...]
1064+ For regular chunks: (chunk_size_dim0, chunk_size_dim1, ...)
1065+ For rectilinear chunks: ((sizes_dim0), (sizes_dim1), ...)
10621066 """
10631067 return self .metadata .chunks
10641068
@@ -1349,8 +1353,10 @@ async def example():
13491353 if self .shards is None :
13501354 chunks_per_shard = 1
13511355 else :
1356+ # Sharding only applies to RegularChunkGrid, so chunks is tuple[int, ...]
1357+ chunks = cast (tuple [int , ...], self .chunks )
13521358 chunks_per_shard = product (
1353- tuple (a // b for a , b in zip (self .shards , self . chunks , strict = True ))
1359+ tuple (a // b for a , b in zip (self .shards , chunks , strict = True ))
13541360 )
13551361 return (await self ._nshards_initialized ()) * chunks_per_shard
13561362
@@ -1856,7 +1862,7 @@ async def resize(self, new_shape: ShapeLike, delete_outside_chunks: bool = True)
18561862 if delete_outside_chunks :
18571863 # Remove all chunks outside of the new shape
18581864 old_chunk_coords = set (self .metadata .chunk_grid .all_chunk_coords (self .metadata .shape ))
1859- new_chunk_coords = set (self . metadata .chunk_grid .all_chunk_coords (new_shape ))
1865+ new_chunk_coords = set (new_metadata .chunk_grid .all_chunk_coords (new_shape ))
18601866
18611867 async def _delete_key (key : str ) -> None :
18621868 await (self .store_path / key ).delete ()
@@ -2340,17 +2346,20 @@ def shape(self, value: tuple[int, ...]) -> None:
23402346 self .resize (value )
23412347
23422348 @property
2343- def chunks (self ) -> tuple [int , ...]:
2344- """Returns a tuple of integers describing the length of each dimension of a chunk of the array.
2345- If sharding is used the inner chunk shape is returned.
2349+ def chunks (self ) -> tuple [int , ...] | tuple [tuple [int , ...], ...]:
2350+ """Returns the chunk specification of the Array.
23462351
2347- Only defined for arrays using using `RegularChunkGrid`.
2348- If array doesn't use `RegularChunkGrid`, `NotImplementedError` is raised.
2352+ For arrays using RegularChunkGrid: returns a tuple of ints representing
2353+ the uniform chunk shape. If sharding is used, the inner chunk shape is returned.
2354+
2355+ For arrays using RectilinearChunkGrid: returns a tuple of tuples, where
2356+ each inner tuple contains the chunk sizes along that dimension (not RLE encoded).
23492357
23502358 Returns
23512359 -------
2352- tuple
2353- A tuple of integers representing the length of each dimension of a chunk.
2360+ tuple[int, ...] | tuple[tuple[int, ...], ...]
2361+ For regular chunks: (chunk_size_dim0, chunk_size_dim1, ...)
2362+ For rectilinear chunks: ((sizes_dim0), (sizes_dim1), ...)
23542363 """
23552364 return self ._async_array .chunks
23562365
@@ -4504,7 +4513,7 @@ async def from_array(
45044513 zarr_format ,
45054514 chunk_key_encoding ,
45064515 dimension_names ,
4507- ) = _parse_keep_array_attr (
4516+ ) = _parse_keep_array_attr ( # type: ignore[assignment]
45084517 data = data ,
45094518 chunks = chunks ,
45104519 shards = shards ,
@@ -4529,7 +4538,7 @@ async def from_array(
45294538 item_size = zdtype .item_size
45304539
45314540 resolved = resolve_chunk_spec (
4532- chunks = chunks ,
4541+ chunks = cast ( ChunksLike , chunks ) ,
45334542 shards = shards ,
45344543 shape = data .shape ,
45354544 dtype_itemsize = item_size ,
@@ -4885,7 +4894,7 @@ async def create_array(
48854894 shape : ShapeLike | None = None ,
48864895 dtype : ZDTypeLike | None = None ,
48874896 data : np .ndarray [Any , np .dtype [Any ]] | None = None ,
4888- chunks : tuple [ int , ...] | Sequence [ Sequence [ int ]] | ChunkGrid | Literal [ "auto" ] = "auto" ,
4897+ chunks : ChunksLike = "auto" ,
48894898 shards : ShardsLike | None = None ,
48904899 filters : FiltersLike = "auto" ,
48914900 compressors : CompressorsLike = "auto" ,
@@ -4919,7 +4928,7 @@ async def create_array(
49194928 data : np.ndarray, optional
49204929 Array-like data to use for initializing the array. If this parameter is provided, the
49214930 ``shape`` and ``dtype`` parameters must be ``None``.
4922- chunks : tuple[int, ...] | Sequence[Sequence[int]] | ChunkGrid | Literal["auto"] , default="auto"
4931+ chunks : ChunksLike , default="auto"
49234932 Chunk shape of the array. Several formats are supported:
49244933
49254934 - tuple of ints: Creates a RegularChunkGrid with uniform chunks, e.g., ``(10, 10)``
@@ -5107,7 +5116,7 @@ def _parse_keep_array_attr(
51075116 chunk_key_encoding : ChunkKeyEncodingLike | None ,
51085117 dimension_names : DimensionNames ,
51095118) -> tuple [
5110- tuple [int , ...] | Literal ["auto" ],
5119+ tuple [int , ...] | tuple [ tuple [ int , ...], ...] | Literal ["auto" ],
51115120 ShardsLike | None ,
51125121 FiltersLike ,
51135122 CompressorsLike ,
@@ -5120,7 +5129,7 @@ def _parse_keep_array_attr(
51205129]:
51215130 if isinstance (data , Array ):
51225131 if chunks == "keep" :
5123- chunks = data .chunks
5132+ chunks = data .chunks # type: ignore[assignment]
51245133 if shards == "keep" :
51255134 shards = data .shards
51265135 if zarr_format is None :
@@ -5174,7 +5183,7 @@ def _parse_keep_array_attr(
51745183 compressors = "auto"
51755184 if serializer == "keep" :
51765185 serializer = "auto"
5177- return (
5186+ return ( # type: ignore[return-value]
51785187 chunks ,
51795188 shards ,
51805189 filters ,
@@ -5588,9 +5597,23 @@ def _iter_shard_regions(
55885597 ------
55895598 region: tuple[slice, ...]
55905599 A tuple of slice objects representing the region spanned by each shard in the selection.
5600+
5601+ Raises
5602+ ------
5603+ NotImplementedError
5604+ If the array uses RectilinearChunkGrid (variable-sized chunks).
55915605 """
5606+ chunks = array .chunks
5607+ if not isinstance (chunks [0 ], int ):
5608+ raise NotImplementedError (
5609+ "_iter_shard_regions is not supported for arrays with variable-sized chunks "
5610+ "(RectilinearChunkGrid). Use the chunk_grid API directly for variable chunk access."
5611+ )
5612+
5613+ # After the check above, chunks is tuple[int, ...]
5614+ regular_chunks = cast (tuple [int , ...], chunks )
55925615 if array .shards is None :
5593- shard_shape = array . chunks
5616+ shard_shape : Sequence [ int ] = regular_chunks
55945617 else :
55955618 shard_shape = array .shards
55965619
@@ -5606,7 +5629,7 @@ def _iter_chunk_regions(
56065629 selection_shape : Sequence [int ] | None = None ,
56075630) -> Iterator [tuple [slice , ...]]:
56085631 """
5609- Iterate over the regions spanned by each shard .
5632+ Iterate over the regions spanned by each chunk .
56105633
56115634 These are the smallest regions of the array that are efficient to read concurrently.
56125635
@@ -5622,9 +5645,26 @@ def _iter_chunk_regions(
56225645 Returns
56235646 -------
56245647 region: tuple[slice, ...]
5625- A tuple of slice objects representing the region spanned by each shard in the selection.
5648+ A tuple of slice objects representing the region spanned by each chunk in the selection.
5649+
5650+ Raises
5651+ ------
5652+ NotImplementedError
5653+ If the array uses RectilinearChunkGrid (variable-sized chunks).
56265654 """
5655+ chunks = array .chunks
5656+ if not isinstance (chunks [0 ], int ):
5657+ raise NotImplementedError (
5658+ "_iter_chunk_regions is not supported for arrays with variable-sized chunks "
5659+ "(RectilinearChunkGrid). Use the chunk_grid API directly for variable chunk access."
5660+ )
56275661
5662+ # After the check above, chunks is tuple[int, ...]
5663+ regular_chunks = cast (tuple [int , ...], chunks )
56285664 return _iter_regions (
5629- array .shape , array .chunks , origin = origin , selection_shape = selection_shape , trim_excess = True
5665+ array .shape ,
5666+ regular_chunks ,
5667+ origin = origin ,
5668+ selection_shape = selection_shape ,
5669+ trim_excess = True ,
56305670 )
0 commit comments