@@ -106,6 +106,53 @@ def create_codec_pipeline(metadata: ArrayV2Metadata | ArrayV3Metadata) -> CodecP
106
106
raise TypeError
107
107
108
108
109
+ async def get_array_metadata (
110
+ store_path : StorePath , zarr_format : ZarrFormat | None = 3
111
+ ) -> dict [str , Any ]:
112
+ if zarr_format == 2 :
113
+ zarray_bytes , zattrs_bytes = await gather (
114
+ (store_path / ZARRAY_JSON ).get (), (store_path / ZATTRS_JSON ).get ()
115
+ )
116
+ if zarray_bytes is None :
117
+ raise FileNotFoundError (store_path )
118
+ elif zarr_format == 3 :
119
+ zarr_json_bytes = await (store_path / ZARR_JSON ).get ()
120
+ if zarr_json_bytes is None :
121
+ raise FileNotFoundError (store_path )
122
+ elif zarr_format is None :
123
+ zarr_json_bytes , zarray_bytes , zattrs_bytes = await gather (
124
+ (store_path / ZARR_JSON ).get (),
125
+ (store_path / ZARRAY_JSON ).get (),
126
+ (store_path / ZATTRS_JSON ).get (),
127
+ )
128
+ if zarr_json_bytes is not None and zarray_bytes is not None :
129
+ # TODO: revisit this exception type
130
+ # alternatively, we could warn and favor v3
131
+ raise ValueError ("Both zarr.json and .zarray objects exist" )
132
+ if zarr_json_bytes is None and zarray_bytes is None :
133
+ raise FileNotFoundError (store_path )
134
+ # set zarr_format based on which keys were found
135
+ if zarr_json_bytes is not None :
136
+ zarr_format = 3
137
+ else :
138
+ zarr_format = 2
139
+ else :
140
+ raise ValueError (f"unexpected zarr_format: { zarr_format } " )
141
+
142
+ metadata_dict : dict [str , Any ]
143
+ if zarr_format == 2 :
144
+ # V2 arrays are comprised of a .zarray and .zattrs objects
145
+ assert zarray_bytes is not None
146
+ metadata_dict = json .loads (zarray_bytes .to_bytes ())
147
+ zattrs_dict = json .loads (zattrs_bytes .to_bytes ()) if zattrs_bytes is not None else {}
148
+ metadata_dict ["attributes" ] = zattrs_dict
149
+ else :
150
+ # V3 arrays are comprised of a zarr.json object
151
+ assert zarr_json_bytes is not None
152
+ metadata_dict = json .loads (zarr_json_bytes .to_bytes ())
153
+ return metadata_dict
154
+
155
+
109
156
@dataclass (frozen = True )
110
157
class AsyncArray :
111
158
metadata : ArrayMetadata
@@ -115,10 +162,17 @@ class AsyncArray:
115
162
116
163
def __init__ (
117
164
self ,
118
- metadata : ArrayMetadata ,
165
+ metadata : ArrayMetadata | dict [ str , Any ] ,
119
166
store_path : StorePath ,
120
167
order : Literal ["C" , "F" ] | None = None ,
121
168
) -> None :
169
+ if isinstance (metadata , dict ):
170
+ zarr_format = metadata ["zarr_format" ]
171
+ if zarr_format == 2 :
172
+ metadata = ArrayV2Metadata .from_dict (metadata )
173
+ else :
174
+ metadata = ArrayV3Metadata .from_dict (metadata )
175
+
122
176
metadata_parsed = parse_array_metadata (metadata )
123
177
order_parsed = parse_indexing_order (order or config .get ("array.order" ))
124
178
@@ -341,51 +395,8 @@ async def open(
341
395
zarr_format : ZarrFormat | None = 3 ,
342
396
) -> AsyncArray :
343
397
store_path = await make_store_path (store )
344
-
345
- if zarr_format == 2 :
346
- zarray_bytes , zattrs_bytes = await gather (
347
- (store_path / ZARRAY_JSON ).get (), (store_path / ZATTRS_JSON ).get ()
348
- )
349
- if zarray_bytes is None :
350
- raise FileNotFoundError (store_path )
351
- elif zarr_format == 3 :
352
- zarr_json_bytes = await (store_path / ZARR_JSON ).get ()
353
- if zarr_json_bytes is None :
354
- raise FileNotFoundError (store_path )
355
- elif zarr_format is None :
356
- zarr_json_bytes , zarray_bytes , zattrs_bytes = await gather (
357
- (store_path / ZARR_JSON ).get (),
358
- (store_path / ZARRAY_JSON ).get (),
359
- (store_path / ZATTRS_JSON ).get (),
360
- )
361
- if zarr_json_bytes is not None and zarray_bytes is not None :
362
- # TODO: revisit this exception type
363
- # alternatively, we could warn and favor v3
364
- raise ValueError ("Both zarr.json and .zarray objects exist" )
365
- if zarr_json_bytes is None and zarray_bytes is None :
366
- raise FileNotFoundError (store_path )
367
- # set zarr_format based on which keys were found
368
- if zarr_json_bytes is not None :
369
- zarr_format = 3
370
- else :
371
- zarr_format = 2
372
- else :
373
- raise ValueError (f"unexpected zarr_format: { zarr_format } " )
374
-
375
- if zarr_format == 2 :
376
- # V2 arrays are comprised of a .zarray and .zattrs objects
377
- assert zarray_bytes is not None
378
- zarray_dict = json .loads (zarray_bytes .to_bytes ())
379
- zattrs_dict = json .loads (zattrs_bytes .to_bytes ()) if zattrs_bytes is not None else {}
380
- zarray_dict ["attributes" ] = zattrs_dict
381
- return cls (store_path = store_path , metadata = ArrayV2Metadata .from_dict (zarray_dict ))
382
- else :
383
- # V3 arrays are comprised of a zarr.json object
384
- assert zarr_json_bytes is not None
385
- return cls (
386
- store_path = store_path ,
387
- metadata = ArrayV3Metadata .from_dict (json .loads (zarr_json_bytes .to_bytes ())),
388
- )
398
+ metadata_dict = await get_array_metadata (store_path , zarr_format = zarr_format )
399
+ return cls (store_path = store_path , metadata = metadata_dict )
389
400
390
401
@property
391
402
def ndim (self ) -> int :
0 commit comments