|
3 | 3 | import asyncio |
4 | 4 | import dataclasses |
5 | 5 | import warnings |
6 | | -from typing import TYPE_CHECKING, Any, Literal, cast |
| 6 | +from typing import TYPE_CHECKING, Any, Literal |
7 | 7 |
|
8 | 8 | import numpy as np |
9 | 9 | import numpy.typing as npt |
10 | 10 | from typing_extensions import deprecated |
11 | 11 |
|
12 | | -from zarr.core.array import Array, AsyncArray, create_array, from_array, get_array_metadata |
| 12 | +from zarr.core.array import Array, AsyncArray, create_array, from_array |
13 | 13 | from zarr.core.array_spec import ArrayConfig, ArrayConfigLike, ArrayConfigParams |
14 | 14 | from zarr.core.buffer import NDArrayLike |
15 | 15 | from zarr.core.common import ( |
|
25 | 25 | ) |
26 | 26 | from zarr.core.group import ( |
27 | 27 | AsyncGroup, |
28 | | - ConsolidatedMetadata, |
29 | | - GroupMetadata, |
30 | 28 | create_hierarchy, |
| 29 | + get_node, |
31 | 30 | ) |
32 | | -from zarr.core.metadata import ArrayMetadataDict, ArrayV2Metadata, ArrayV3Metadata |
| 31 | +from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata |
| 32 | +from zarr.core.metadata.group import ConsolidatedMetadata, GroupMetadata |
33 | 33 | from zarr.core.metadata.v2 import _default_compressor, _default_filters |
34 | 34 | from zarr.errors import ( |
35 | 35 | ArrayNotFoundError, |
| 36 | + ContainsArrayError, |
| 37 | + ContainsGroupError, |
36 | 38 | GroupNotFoundError, |
37 | 39 | NodeNotFoundError, |
38 | | - NodeTypeValidationError, |
39 | 40 | ) |
40 | 41 | from zarr.storage._common import make_store_path |
41 | 42 |
|
@@ -320,27 +321,46 @@ async def open( |
320 | 321 | zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format) |
321 | 322 |
|
322 | 323 | store_path = await make_store_path(store, mode=mode, path=path, storage_options=storage_options) |
323 | | - # TODO: the mode check below seems wrong! |
324 | | - if "shape" not in kwargs and mode in {"a", "r", "r+", "w"}: |
| 324 | + |
| 325 | + extant_node: AsyncGroup | AsyncArray[Any] = None |
| 326 | + # All of these modes will defer to an existing mode |
| 327 | + if mode in {"a", "r", "r+", "w-"}: |
325 | 328 | try: |
326 | | - metadata_dict = await get_array_metadata(store_path, zarr_format=zarr_format) |
327 | | - # TODO: remove this cast when we fix typing for array metadata dicts |
328 | | - _metadata_dict = cast(ArrayMetadataDict, metadata_dict) |
329 | | - # for v2, the above would already have raised an exception if not an array |
330 | | - zarr_format = _metadata_dict["zarr_format"] |
331 | | - is_v3_array = zarr_format == 3 and _metadata_dict.get("node_type") == "array" |
332 | | - if is_v3_array or zarr_format == 2: |
333 | | - return AsyncArray(store_path=store_path, metadata=_metadata_dict) |
334 | | - except (AssertionError, ArrayNotFoundError, NodeTypeValidationError): |
| 329 | + extant_node = await get_node( |
| 330 | + store=store_path.store, path=store_path.path, zarr_format=zarr_format |
| 331 | + ) |
| 332 | + except NodeNotFoundError: |
335 | 333 | pass |
336 | | - try: |
337 | | - return await open_group(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) |
338 | | - except GroupNotFoundError as e: |
| 334 | + # we successfully found an existing node |
| 335 | + if extant_node is not None: |
| 336 | + # an existing node is an error if mode == w- |
| 337 | + if mode == "w-": |
| 338 | + if isinstance(extant_node, AsyncArray): |
| 339 | + node_type = "array" |
| 340 | + exc = ContainsArrayError |
| 341 | + else: |
| 342 | + node_type = "group" |
| 343 | + exc = ContainsGroupError |
| 344 | + msg = ( |
| 345 | + f"A Zarr V{extant_node.zarr_format} {node_type} exists in store " |
| 346 | + f"{store_path.store!r} at path {store_path.path!r}. " |
| 347 | + f"Attempting to open a pre-existing {node_type} with access mode {mode} is an error. " |
| 348 | + f"Remove the {node_type} from storage, or use an access mode that is compatible with " |
| 349 | + "a pre-existing array, such as one of ('r','r+','a','w')." |
| 350 | + ) |
| 351 | + raise exc(msg) |
| 352 | + else: |
| 353 | + # otherwise, return the existing node |
| 354 | + return extant_node |
| 355 | + else: |
| 356 | + if mode in ("r", "r+"): |
339 | 357 | msg = ( |
340 | | - "'Neither array nor group metadata were found in '" |
341 | | - f"store {store_path.store} at path {store_path.path!r}" |
| 358 | + f"Neither array nor group metadata were found in store {store_path.store!r} at " |
| 359 | + f"path {store_path.path!r}. Attempting to open an non-existent node with access mode " |
| 360 | + f"{mode} is an error. Create an array or group first, or use an access mode that " |
| 361 | + "create an array or group, such as one of ('a', 'w', 'w-')." |
342 | 362 | ) |
343 | | - raise NodeNotFoundError(msg) from e |
| 363 | + raise NodeNotFoundError(msg) |
344 | 364 | if "shape" in kwargs: |
345 | 365 | return await open_array(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs) |
346 | 366 | else: |
|
0 commit comments