33import json
44from asyncio import gather
55from dataclasses import dataclass , field , replace
6+ from logging import getLogger
67from typing import TYPE_CHECKING , Any , Literal , cast
78
89import numpy as np
910import numpy .typing as npt
1011
1112from zarr ._compat import _deprecate_positional_args
12- from zarr .abc .store import set_or_delete
13+ from zarr .abc .store import Store , set_or_delete
1314from zarr .codecs import BytesCodec
1415from zarr .codecs ._v2 import V2Compressor , V2Filters
1516from zarr .core .attributes import Attributes
1920 NDBuffer ,
2021 default_buffer_prototype ,
2122)
22- from zarr .core .chunk_grids import RegularChunkGrid , _guess_chunks
23+ from zarr .core .chunk_grids import RegularChunkGrid , normalize_chunks
2324from zarr .core .chunk_key_encodings import (
2425 ChunkKeyEncoding ,
2526 DefaultChunkKeyEncoding ,
6768from zarr .core .metadata .v3 import ArrayV3Metadata
6869from zarr .core .sync import collect_aiterator , sync
6970from zarr .registry import get_pipeline_class
70- from zarr .store import StoreLike , StorePath , make_store_path
71- from zarr .store .common import (
72- ensure_no_existing_node ,
73- )
71+ from zarr .storage import StoreLike , make_store_path
72+ from zarr .storage .common import StorePath , ensure_no_existing_node
7473
7574if TYPE_CHECKING :
7675 from collections .abc import Iterable , Iterator , Sequence
8281# Array and AsyncArray are defined in the base ``zarr`` namespace
8382__all__ = ["create_codec_pipeline" , "parse_array_metadata" ]
8483
84+ logger = getLogger (__name__ )
85+
8586
8687def parse_array_metadata (data : Any ) -> ArrayV2Metadata | ArrayV3Metadata :
8788 if isinstance (data , ArrayV2Metadata | ArrayV3Metadata ):
@@ -222,15 +223,14 @@ async def create(
222223
223224 shape = parse_shapelike (shape )
224225
225- if chunk_shape is None :
226- if chunks is None :
227- chunk_shape = chunks = _guess_chunks (shape = shape , typesize = np .dtype (dtype ).itemsize )
228- else :
229- chunks = parse_shapelike (chunks )
226+ if chunks is not None and chunk_shape is not None :
227+ raise ValueError ("Only one of chunk_shape or chunks can be provided." )
230228
231- chunk_shape = chunks
232- elif chunks is not None :
233- raise ValueError ("Only one of chunk_shape or chunks must be provided." )
229+ dtype = np .dtype (dtype )
230+ if chunks :
231+ _chunks = normalize_chunks (chunks , shape , dtype .itemsize )
232+ else :
233+ _chunks = normalize_chunks (chunk_shape , shape , dtype .itemsize )
234234
235235 if zarr_format == 3 :
236236 if dimension_separator is not None :
@@ -253,7 +253,7 @@ async def create(
253253 store_path ,
254254 shape = shape ,
255255 dtype = dtype ,
256- chunk_shape = chunk_shape ,
256+ chunk_shape = _chunks ,
257257 fill_value = fill_value ,
258258 chunk_key_encoding = chunk_key_encoding ,
259259 codecs = codecs ,
@@ -276,7 +276,7 @@ async def create(
276276 store_path ,
277277 shape = shape ,
278278 dtype = dtype ,
279- chunks = chunk_shape ,
279+ chunks = _chunks ,
280280 dimension_separator = dimension_separator ,
281281 fill_value = fill_value ,
282282 order = order ,
@@ -404,6 +404,10 @@ async def open(
404404 metadata_dict = await get_array_metadata (store_path , zarr_format = zarr_format )
405405 return cls (store_path = store_path , metadata = metadata_dict )
406406
407+ @property
408+ def store (self ) -> Store :
409+ return self .store_path .store
410+
407411 @property
408412 def ndim (self ) -> int :
409413 return len (self .metadata .shape )
@@ -831,6 +835,10 @@ def open(
831835 async_array = sync (AsyncArray .open (store ))
832836 return cls (async_array )
833837
838+ @property
839+ def store (self ) -> Store :
840+ return self ._async_array .store
841+
834842 @property
835843 def ndim (self ) -> int :
836844 return self ._async_array .ndim
@@ -2380,15 +2388,26 @@ def chunks_initialized(array: Array | AsyncArray) -> tuple[str, ...]:
23802388def _build_parents (node : AsyncArray | AsyncGroup ) -> list [AsyncGroup ]:
23812389 from zarr .core .group import AsyncGroup , GroupMetadata
23822390
2383- required_parts = node .store_path .path .split ("/" )[:- 1 ]
2384- parents = []
2391+ store = node .store_path .store
2392+ path = node .store_path .path
2393+ if not path :
2394+ return []
2395+
2396+ required_parts = path .split ("/" )[:- 1 ]
2397+ parents = [
2398+ # the root group
2399+ AsyncGroup (
2400+ metadata = GroupMetadata (zarr_format = node .metadata .zarr_format ),
2401+ store_path = StorePath (store = store , path = "" ),
2402+ )
2403+ ]
23852404
23862405 for i , part in enumerate (required_parts ):
2387- path = "/" .join (required_parts [:i ] + [part ])
2406+ p = "/" .join (required_parts [:i ] + [part ])
23882407 parents .append (
23892408 AsyncGroup (
23902409 metadata = GroupMetadata (zarr_format = node .metadata .zarr_format ),
2391- store_path = StorePath (store = node . store_path . store , path = path ),
2410+ store_path = StorePath (store = store , path = p ),
23922411 )
23932412 )
23942413
0 commit comments