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 ):
@@ -228,15 +229,14 @@ async def create(
228229
229230 shape = parse_shapelike (shape )
230231
231- if chunk_shape is None :
232- if chunks is None :
233- chunk_shape = chunks = _guess_chunks (shape = shape , typesize = np .dtype (dtype ).itemsize )
234- else :
235- chunks = parse_shapelike (chunks )
232+ if chunks is not None and chunk_shape is not None :
233+ raise ValueError ("Only one of chunk_shape or chunks can be provided." )
236234
237- chunk_shape = chunks
238- elif chunks is not None :
239- raise ValueError ("Only one of chunk_shape or chunks must be provided." )
235+ dtype = np .dtype (dtype )
236+ if chunks :
237+ _chunks = normalize_chunks (chunks , shape , dtype .itemsize )
238+ else :
239+ _chunks = normalize_chunks (chunk_shape , shape , dtype .itemsize )
240240
241241 if zarr_format == 3 :
242242 if dimension_separator is not None :
@@ -259,7 +259,7 @@ async def create(
259259 store_path ,
260260 shape = shape ,
261261 dtype = dtype ,
262- chunk_shape = chunk_shape ,
262+ chunk_shape = _chunks ,
263263 fill_value = fill_value ,
264264 chunk_key_encoding = chunk_key_encoding ,
265265 codecs = codecs ,
@@ -282,7 +282,7 @@ async def create(
282282 store_path ,
283283 shape = shape ,
284284 dtype = dtype ,
285- chunks = chunk_shape ,
285+ chunks = _chunks ,
286286 dimension_separator = dimension_separator ,
287287 fill_value = fill_value ,
288288 order = order ,
@@ -410,6 +410,10 @@ async def open(
410410 metadata_dict = await get_array_metadata (store_path , zarr_format = zarr_format )
411411 return cls (store_path = store_path , metadata = metadata_dict )
412412
413+ @property
414+ def store (self ) -> Store :
415+ return self .store_path .store
416+
413417 @property
414418 def ndim (self ) -> int :
415419 return len (self .metadata .shape )
@@ -837,6 +841,10 @@ def open(
837841 async_array = sync (AsyncArray .open (store ))
838842 return cls (async_array )
839843
844+ @property
845+ def store (self ) -> Store :
846+ return self ._async_array .store
847+
840848 @property
841849 def ndim (self ) -> int :
842850 return self ._async_array .ndim
@@ -2386,15 +2394,26 @@ def chunks_initialized(array: Array | AsyncArray) -> tuple[str, ...]:
23862394def _build_parents (node : AsyncArray | AsyncGroup ) -> list [AsyncGroup ]:
23872395 from zarr .core .group import AsyncGroup , GroupMetadata
23882396
2389- required_parts = node .store_path .path .split ("/" )[:- 1 ]
2390- parents = []
2397+ store = node .store_path .store
2398+ path = node .store_path .path
2399+ if not path :
2400+ return []
2401+
2402+ required_parts = path .split ("/" )[:- 1 ]
2403+ parents = [
2404+ # the root group
2405+ AsyncGroup (
2406+ metadata = GroupMetadata (zarr_format = node .metadata .zarr_format ),
2407+ store_path = StorePath (store = store , path = "" ),
2408+ )
2409+ ]
23912410
23922411 for i , part in enumerate (required_parts ):
2393- path = "/" .join (required_parts [:i ] + [part ])
2412+ p = "/" .join (required_parts [:i ] + [part ])
23942413 parents .append (
23952414 AsyncGroup (
23962415 metadata = GroupMetadata (zarr_format = node .metadata .zarr_format ),
2397- store_path = StorePath (store = node . store_path . store , path = path ),
2416+ store_path = StorePath (store = store , path = p ),
23982417 )
23992418 )
24002419
0 commit comments