@@ -4744,15 +4744,8 @@ async def init_array(
47444744 sub_codecs = cast ("tuple[Codec, ...]" , (* array_array , array_bytes , * bytes_bytes ))
47454745 codecs_out : tuple [Codec , ...]
47464746
4747- # Validate that RectilinearChunkGrid is not used with sharding
4748- if shard_shape_parsed is not None and chunk_grid is not None :
4749- from zarr .core .chunk_grids import RectilinearChunkGrid
4750-
4751- if isinstance (chunk_grid , RectilinearChunkGrid ):
4752- raise ValueError (
4753- "Sharding is not supported with RectilinearChunkGrid (variable-sized chunks). "
4754- "Use RegularChunkGrid (uniform chunks) with sharding, or use RectilinearChunkGrid without sharding."
4755- )
4747+ # Note: RectilinearChunkGrid + sharding validation is now handled in resolve_chunk_spec()
4748+ # which is called in create_array() before calling init_array()
47564749
47574750 if shard_shape_parsed is not None :
47584751 index_location = None
@@ -4941,73 +4934,44 @@ async def create_array(
49414934 >>> fill_value=0)
49424935 <AsyncArray memory://140349042942400 shape=(100, 100) dtype=int32>
49434936 """
4944- # Handle chunks as ChunkGrid or nested sequence - convert to chunk_grid for init_array
4945- chunk_grid : ChunkGrid | None = None
4946-
4947- if isinstance (chunks , ChunkGrid ):
4948- chunk_grid = chunks
4949- chunks = "auto" # Will be ignored since chunk_grid is set
4950- elif chunks != "auto" and not isinstance (chunks , (tuple , int )):
4951- # Check if it's a nested sequence for RectilinearChunkGrid
4952- # We need to distinguish between flat sequences like [10, 10] and nested like [[10, 20], [5, 5]]
4953- is_nested = False
4954- try :
4955- # Try to iterate and check if elements are sequences
4956- if hasattr (chunks , "__iter__" ) and not isinstance (chunks , (str , bytes )): # type: ignore[unreachable]
4957- first_elem = next (iter (chunks ), None )
4958- if (
4959- first_elem is not None
4960- and hasattr (first_elem , "__iter__" )
4961- and not isinstance (first_elem , (str , bytes , int ))
4962- ):
4963- is_nested = True
4964- except (TypeError , StopIteration ):
4965- pass
4937+ data_parsed , shape_param , dtype_parsed = _parse_data_params (data = data , shape = shape , dtype = dtype )
49664938
4967- if is_nested :
4968- # It's a nested sequence - create RectilinearChunkGrid
4969- from zarr .core .chunk_grids import RectilinearChunkGrid
4939+ # Parse shape to tuple for resolve_chunk_spec
4940+ shape_parsed = parse_shapelike (shape_param )
49704941
4971- if zarr_format == 2 :
4972- raise ValueError (
4973- "Variable chunks (nested sequences) are only supported in Zarr format 3. "
4974- "Use zarr_format=3 or provide a regular tuple for chunks."
4975- )
4942+ # Parse dtype to get item_size for chunk grid parsing
4943+ # Ensure zarr_format is not None for resolve_chunk_spec
4944+ zarr_format_resolved : ZarrFormat = zarr_format or 3
4945+ zdtype = parse_dtype (dtype_parsed , zarr_format = zarr_format_resolved )
4946+ item_size = 1
4947+ if isinstance (zdtype , HasItemSize ):
4948+ item_size = zdtype .item_size
49764949
4977- try :
4978- # Convert nested sequence to list of lists for RectilinearChunkGrid
4979- chunk_shapes = [list (dim ) for dim in chunks ]
4980- chunk_grid = RectilinearChunkGrid (chunk_shapes = chunk_shapes )
4981- chunks = "auto" # Will be ignored since chunk_grid is set
4982- except (TypeError , ValueError ) as e :
4983- raise TypeError (
4984- f"Invalid chunks argument: { chunks } . "
4985- "Expected a tuple of integers, a nested sequence for variable chunks, "
4986- f"a ChunkGrid instance, or 'auto'. Got error: { e } "
4987- ) from e
4988- # else: it's a flat sequence like [10, 10] or single int, let it pass through to existing code
4989-
4990- data_parsed , shape_parsed , dtype_parsed = _parse_data_params (
4991- data = data , shape = shape , dtype = dtype
4950+ # Resolve chunk specification using consolidated function
4951+ # This handles all validation and returns resolved chunks, shards, and chunk_grid
4952+ from zarr .core .chunk_grids import resolve_chunk_spec
4953+
4954+ resolved = resolve_chunk_spec (
4955+ chunks = chunks ,
4956+ shards = shards ,
4957+ shape = shape_parsed ,
4958+ dtype_itemsize = item_size ,
4959+ zarr_format = zarr_format_resolved ,
4960+ has_data = data_parsed is not None ,
49924961 )
4993- if data_parsed is not None :
4994- # from_array doesn't support ChunkGrid parameter, so error if chunk_grid was set
4995- if chunk_grid is not None :
4996- raise ValueError (
4997- "Cannot use ChunkGrid or nested sequences for chunks when creating array from data. "
4998- "Use a regular tuple for chunks instead."
4999- )
5000- # At this point, chunks must be Literal["auto"] | tuple[int, ...] since chunk_grid is None
5001- from typing import cast
50024962
5003- chunks_narrowed = cast ("Literal['auto', 'keep'] | tuple[int, ...]" , chunks )
4963+ chunks_param = resolved .chunks
4964+ shards_param = resolved .shards
4965+ chunk_grid_param = resolved .chunk_grid
4966+
4967+ if data_parsed is not None :
50044968 return await from_array (
50054969 store ,
50064970 data = data_parsed ,
50074971 write_data = write_data ,
50084972 name = name ,
5009- chunks = chunks_narrowed ,
5010- shards = shards ,
4973+ chunks = chunks_param ,
4974+ shards = shards_param ,
50114975 filters = filters ,
50124976 compressors = compressors ,
50134977 serializer = serializer ,
@@ -5027,16 +4991,12 @@ async def create_array(
50274991 store_path = await make_store_path (
50284992 store , path = name , mode = mode , storage_options = storage_options
50294993 )
5030- # At this point, chunks must be Literal["auto"] | tuple[int, ...] since we set it to "auto" when chunk_grid is set
5031- from typing import cast
5032-
5033- chunks_narrowed = cast ("tuple[int, ...] | Literal['auto']" , chunks )
50344994 return await init_array (
50354995 store_path = store_path ,
50364996 shape = shape_parsed ,
50374997 dtype = dtype_parsed ,
5038- chunks = chunks_narrowed ,
5039- shards = shards ,
4998+ chunks = chunks_param ,
4999+ shards = shards_param ,
50405000 filters = filters ,
50415001 compressors = compressors ,
50425002 serializer = serializer ,
@@ -5048,7 +5008,7 @@ async def create_array(
50485008 dimension_names = dimension_names ,
50495009 overwrite = overwrite ,
50505010 config = config ,
5051- chunk_grid = chunk_grid ,
5011+ chunk_grid = chunk_grid_param ,
50525012 )
50535013
50545014
0 commit comments