77from dataclasses import dataclass , field
88from itertools import starmap
99from logging import getLogger
10- from typing import TYPE_CHECKING , Any , Generic , Literal , TypeAlias , cast , overload
10+ from typing import TYPE_CHECKING , Any , Generic , Literal , TypeAlias , TypedDict , cast , overload
1111from warnings import warn
1212
1313import numcodecs
109109 from typing import Self
110110
111111 from zarr .abc .codec import CodecPipeline
112+ from zarr .codecs .sharding import ShardingCodecIndexLocation
112113 from zarr .core .group import AsyncGroup
113114
115+
114116# Array and AsyncArray are defined in the base ``zarr`` namespace
115117__all__ = ["create_codec_pipeline" , "parse_array_metadata" ]
116118
@@ -271,7 +273,7 @@ def __init__(
271273 # this overload defines the function signature when zarr_format is 2
272274 @overload
273275 @classmethod
274- async def create (
276+ async def _create (
275277 cls ,
276278 store : StoreLike ,
277279 * ,
@@ -295,7 +297,7 @@ async def create(
295297 # this overload defines the function signature when zarr_format is 3
296298 @overload
297299 @classmethod
298- async def create (
300+ async def _create (
299301 cls ,
300302 store : StoreLike ,
301303 * ,
@@ -323,7 +325,7 @@ async def create(
323325
324326 @overload
325327 @classmethod
326- async def create (
328+ async def _create (
327329 cls ,
328330 store : StoreLike ,
329331 * ,
@@ -350,7 +352,7 @@ async def create(
350352 ) -> AsyncArray [ArrayV3Metadata ]: ...
351353 @overload
352354 @classmethod
353- async def create (
355+ async def _create (
354356 cls ,
355357 store : StoreLike ,
356358 * ,
@@ -383,7 +385,7 @@ async def create(
383385 ) -> AsyncArray [ArrayV3Metadata ] | AsyncArray [ArrayV2Metadata ]: ...
384386
385387 @classmethod
386- async def create (
388+ async def _create (
387389 cls ,
388390 store : StoreLike ,
389391 * ,
@@ -494,19 +496,6 @@ async def create(
494496 -------
495497 AsyncArray
496498 The created asynchronous array instance.
497-
498- Examples
499- --------
500- >>> import zarr
501- >>> store = zarr.storage.MemoryStore(mode='w')
502- >>> async_arr = await zarr.core.array.AsyncArray.create(
503- >>> store=store,
504- >>> shape=(100,100),
505- >>> chunks=(10,10),
506- >>> dtype='i4',
507- >>> fill_value=0)
508- <AsyncArray memory://140349042942400 shape=(100, 100) dtype=int32>
509-
510499 """
511500 store_path = await make_store_path (store )
512501
@@ -1148,7 +1137,7 @@ async def getitem(
11481137 --------
11491138 >>> import zarr
11501139 >>> store = zarr.storage.MemoryStore(mode='w')
1151- >>> async_arr = await zarr.core.array.AsyncArray.create (
1140+ >>> async_arr = await zarr.api.asynchronous.create_array (
11521141 ... store=store,
11531142 ... shape=(100,100),
11541143 ... chunks=(10,10),
@@ -1542,7 +1531,7 @@ class Array:
15421531
15431532 @classmethod
15441533 @_deprecate_positional_args
1545- def create (
1534+ def _create (
15461535 cls ,
15471536 store : StoreLike ,
15481537 * ,
@@ -1643,7 +1632,7 @@ def create(
16431632 Array created from the store.
16441633 """
16451634 async_array = sync (
1646- AsyncArray .create (
1635+ AsyncArray ._create (
16471636 store = store ,
16481637 shape = shape ,
16491638 dtype = dtype ,
@@ -2025,10 +2014,10 @@ def __getitem__(self, selection: Selection) -> NDArrayLike:
20252014 >>> import zarr
20262015 >>> import numpy as np
20272016 >>> data = np.arange(100, dtype="uint16")
2028- >>> z = Array.create (
2017+ >>> z = zarr.create_array (
20292018 >>> StorePath(MemoryStore(mode="w")),
20302019 >>> shape=data.shape,
2031- >>> chunk_shape =(10,),
2020+ >>> chunks =(10,),
20322021 >>> dtype=data.dtype,
20332022 >>> )
20342023 >>> z[:] = data
@@ -2059,10 +2048,10 @@ def __getitem__(self, selection: Selection) -> NDArrayLike:
20592048 Setup a 2-dimensional array::
20602049
20612050 >>> data = np.arange(100, dtype="uint16").reshape(10, 10)
2062- >>> z = Array.create (
2051+ >>> z = zarr.create_array (
20632052 >>> StorePath(MemoryStore(mode="w")),
20642053 >>> shape=data.shape,
2065- >>> chunk_shape =(10, 10),
2054+ >>> chunks =(10, 10),
20662055 >>> dtype=data.dtype,
20672056 >>> )
20682057 >>> z[:] = data
@@ -2290,10 +2279,10 @@ def get_basic_selection(
22902279 >>> import zarr
22912280 >>> import numpy as np
22922281 >>> data = np.arange(100, dtype="uint16")
2293- >>> z = Array.create (
2282+ >>> z = zarr.create_array (
22942283 >>> StorePath(MemoryStore(mode="w")),
22952284 >>> shape=data.shape,
2296- >>> chunk_shape =(3,),
2285+ >>> chunks =(3,),
22972286 >>> dtype=data.dtype,
22982287 >>> )
22992288 >>> z[:] = data
@@ -2319,10 +2308,10 @@ def get_basic_selection(
23192308 Setup a 3-dimensional array::
23202309
23212310 >>> data = np.arange(1000).reshape(10, 10, 10)
2322- >>> z = Array.create (
2311+ >>> z = zarr.create_array (
23232312 >>> StorePath(MemoryStore(mode="w")),
23242313 >>> shape=data.shape,
2325- >>> chunk_shape =(5, 5, 5),
2314+ >>> chunks =(5, 5, 5),
23262315 >>> dtype=data.dtype,
23272316 >>> )
23282317 >>> z[:] = data
@@ -2514,10 +2503,10 @@ def get_orthogonal_selection(
25142503 >>> import zarr
25152504 >>> import numpy as np
25162505 >>> data = np.arange(100).reshape(10, 10)
2517- >>> z = Array.create (
2506+ >>> z = zarr.create_array (
25182507 >>> StorePath(MemoryStore(mode="w")),
25192508 >>> shape=data.shape,
2520- >>> chunk_shape =data.shape,
2509+ >>> chunks =data.shape,
25212510 >>> dtype=data.dtype,
25222511 >>> )
25232512 >>> z[:] = data
@@ -2748,10 +2737,10 @@ def get_mask_selection(
27482737 >>> import zarr
27492738 >>> import numpy as np
27502739 >>> data = np.arange(100).reshape(10, 10)
2751- >>> z = Array.create (
2740+ >>> z = zarr.create_array (
27522741 >>> StorePath(MemoryStore(mode="w")),
27532742 >>> shape=data.shape,
2754- >>> chunk_shape =data.shape,
2743+ >>> chunks =data.shape,
27552744 >>> dtype=data.dtype,
27562745 >>> )
27572746 >>> z[:] = data
@@ -2908,10 +2897,10 @@ def get_coordinate_selection(
29082897 >>> import zarr
29092898 >>> import numpy as np
29102899 >>> data = np.arange(0, 100, dtype="uint16").reshape((10, 10))
2911- >>> z = Array.create (
2900+ >>> z = zarr.create_array (
29122901 >>> StorePath(MemoryStore(mode="w")),
29132902 >>> shape=data.shape,
2914- >>> chunk_shape =(3, 3),
2903+ >>> chunks =(3, 3),
29152904 >>> dtype=data.dtype,
29162905 >>> )
29172906 >>> z[:] = data
@@ -3096,10 +3085,10 @@ def get_block_selection(
30963085 >>> import zarr
30973086 >>> import numpy as np
30983087 >>> data = np.arange(0, 100, dtype="uint16").reshape((10, 10))
3099- >>> z = Array.create (
3088+ >>> z = zarr.create_array (
31003089 >>> StorePath(MemoryStore(mode="w")),
31013090 >>> shape=data.shape,
3102- >>> chunk_shape =(3, 3),
3091+ >>> chunks =(3, 3),
31033092 >>> dtype=data.dtype,
31043093 >>> )
31053094 >>> z[:] = data
@@ -3517,14 +3506,22 @@ def _get_default_codecs(
35173506)
35183507
35193508
3509+ class ShardsConfigParam (TypedDict ):
3510+ shape : ChunkCoords
3511+ index_location : ShardingCodecIndexLocation | None
3512+
3513+
3514+ ShardsParam : TypeAlias = ChunkCoords | ShardsConfigParam | Literal ["auto" ]
3515+
3516+
35203517async def create_array (
35213518 store : str | StoreLike ,
35223519 * ,
35233520 name : str | None = None ,
35243521 shape : ShapeLike ,
35253522 dtype : npt .DTypeLike ,
35263523 chunks : ChunkCoords | Literal ["auto" ] = "auto" ,
3527- shards : ChunkCoords | Literal [ "auto" ] | None = None ,
3524+ shards : ShardsParam | None = None ,
35283525 filters : FiltersParam = "auto" ,
35293526 compressors : CompressorsParam = "auto" ,
35303527 fill_value : Any | None = 0 ,
@@ -3616,13 +3613,24 @@ async def create_array(
36163613 -------
36173614 z : array
36183615 The array.
3616+
3617+ Examples
3618+ --------
3619+ >>> import zarr
3620+ >>> store = zarr.storage.MemoryStore(mode='w')
3621+ >>> async_arr = await zarr.api.asynchronous.create_array(
3622+ >>> store=store,
3623+ >>> shape=(100,100),
3624+ >>> chunks=(10,10),
3625+ >>> dtype='i4',
3626+ >>> fill_value=0)
3627+ <AsyncArray memory://140349042942400 shape=(100, 100) dtype=int32>
36193628 """
36203629
36213630 if zarr_format is None :
36223631 zarr_format = _default_zarr_version ()
36233632
3624- # TODO: figure out why putting these imports at top-level causes circular imports
3625- from zarr .codecs .sharding import ShardingCodec
3633+ from zarr .codecs .sharding import ShardingCodec , ShardingCodecIndexLocation
36263634
36273635 mode : Literal ["a" ] = "a"
36283636 dtype_parsed = parse_dtype (dtype , zarr_format = zarr_format )
@@ -3677,7 +3685,14 @@ async def create_array(
36773685 sub_codecs = cast (tuple [Codec , ...], (* array_array , array_bytes , * bytes_bytes ))
36783686 codecs_out : tuple [Codec , ...]
36793687 if shard_shape_parsed is not None :
3680- sharding_codec = ShardingCodec (chunk_shape = chunk_shape_parsed , codecs = sub_codecs )
3688+ index_location = None
3689+ if isinstance (shards , dict ):
3690+ index_location = ShardingCodecIndexLocation (shards .get ("index_location" , None ))
3691+ if index_location is None :
3692+ index_location = ShardingCodecIndexLocation .end
3693+ sharding_codec = ShardingCodec (
3694+ chunk_shape = chunk_shape_parsed , codecs = sub_codecs , index_location = index_location
3695+ )
36813696 sharding_codec .validate (
36823697 shape = chunk_shape_parsed ,
36833698 dtype = dtype_parsed ,
0 commit comments