Skip to content

Commit 536b0e6

Browse files
committed
use new errors
1 parent d1eb448 commit 536b0e6

File tree

7 files changed

+137
-112
lines changed

7 files changed

+137
-112
lines changed

src/zarr/api/asynchronous.py

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@
2828
ConsolidatedMetadata,
2929
GroupMetadata,
3030
create_hierarchy,
31-
get_node,
3231
)
3332
from zarr.core.metadata import ArrayMetadataDict, ArrayV2Metadata, ArrayV3Metadata
3433
from zarr.core.metadata.v2 import _default_compressor, _default_filters
35-
from zarr.errors import ArrayNotFoundError, GroupNotFoundError, NodeNotFoundError, NodeTypeValidationError
34+
from zarr.errors import (
35+
ArrayNotFoundError,
36+
GroupNotFoundError,
37+
NodeNotFoundError,
38+
NodeTypeValidationError,
39+
)
3640
from zarr.storage._common import make_store_path
37-
import contextlib
3841

3942
if TYPE_CHECKING:
4043
from collections.abc import Iterable
@@ -317,37 +320,32 @@ async def open(
317320
zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)
318321

319322
store_path = await make_store_path(store, mode=mode, path=path, storage_options=storage_options)
320-
extant_node: AsyncArray[Any] | AsyncGroup | None = None
321-
if mode in ('r', 'r+', 'a', 'w-'):
322-
# we need to check for an existing node.
323-
if zarr_format is None:
324-
try:
325-
extant_node = await get_node(store_path.store, store_path.path, zarr_format=3)
326-
except NodeNotFoundError:
327-
with contextlib.suppress(NodeNotFoundError):
328-
extant_node = await get_node(store_path.store, store_path.path, zarr_format=2)
329-
else:
330-
with contextlib.suppress(NodeNotFoundError):
331-
extant_node = await get_node(store_path.store, store_path.path, zarr_format=zarr_format)
332-
333-
if mode in ('r', 'r+') and extant_node is None:
334-
if zarr_format is None:
335-
msg = (
336-
"No Zarr V2 or V3 metadata documents were found in store "
337-
f"{store_path.store!r} at path {store_path.path!r}."
338-
)
339-
else:
323+
# TODO: the mode check below seems wrong!
324+
if "shape" not in kwargs and mode in {"a", "r", "r+", "w"}:
325+
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):
335+
pass
336+
try:
337+
return await open_group(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs)
338+
except GroupNotFoundError as e:
340339
msg = (
341-
f"No Zarr V{zarr_format} metadata documents were found in store "
342-
f"{store_path.store!r} at path {store_path.path!r}."
343-
)
344-
raise NodeNotFoundError(msg)
345-
340+
"'Neither array nor group metadata were found in '"
341+
f"store {store_path.store} at path {store_path.path!r}"
342+
)
343+
raise NodeNotFoundError(msg) from e
344+
if "shape" in kwargs:
345+
return await open_array(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs)
346346
else:
347-
if "shape" in kwargs:
348-
return await open_array(store=store_path, mode=mode, zarr_format=zarr_format, **kwargs)
349-
else:
350-
return await open_group(store=store_path, mode=mode, zarr_format=zarr_format, **kwargs)
347+
return await open_group(store=store_path, zarr_format=zarr_format, mode=mode, **kwargs)
348+
351349

352350
async def open_consolidated(
353351
*args: Any, use_consolidated: Literal[True] = True, **kwargs: Any

src/zarr/core/array.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
)
109109
from zarr.core.metadata.v3 import DataType, parse_node_type_array
110110
from zarr.core.sync import sync
111-
from zarr.errors import ArrayNotFoundError, MetadataValidationError
111+
from zarr.errors import ArrayNotFoundError
112112
from zarr.registry import (
113113
_parse_array_array_codec,
114114
_parse_array_bytes_codec,
@@ -171,8 +171,8 @@ async def get_array_metadata(
171171
)
172172
if zarray_bytes is None:
173173
msg = (
174-
"A Zarr V2 array metadata document was not found in store "
175-
f"{store_path.store!r} at path {store_path.path!r}."
174+
"A Zarr V2 array metadata document was not found in store "
175+
f"{store_path.store!r} at path {store_path.path!r}."
176176
)
177177
raise ArrayNotFoundError(msg)
178178
elif zarr_format == 3:
@@ -210,7 +210,7 @@ async def get_array_metadata(
210210
else:
211211
zarr_format = 2
212212
else:
213-
msg = f"Invalid value for zarr_format. Expected one of 2, 3 or None. Got {zarr_format}." # type: ignore[unreachable]
213+
msg = f"Invalid value for zarr_format. Expected one of 2, 3, or None. Got {zarr_format}." # type: ignore[unreachable]
214214
raise ValueError(msg)
215215

216216
metadata_dict: dict[str, JSON]

src/zarr/core/group.py

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from collections.abc import Iterator, Mapping
1010
from dataclasses import asdict, dataclass, field, fields, replace
1111
from itertools import accumulate
12-
from typing import TYPE_CHECKING, Literal, TypeVar, assert_never, cast, overload
12+
from typing import TYPE_CHECKING, Literal, TypeVar, assert_never, cast, get_args, overload
1313

1414
import numpy as np
1515
import numpy.typing as npt
@@ -52,7 +52,6 @@
5252
from zarr.core.metadata.v3 import V3JsonEncoder, _replace_special_floats
5353
from zarr.core.sync import SyncMixin, sync
5454
from zarr.errors import (
55-
ArrayNotFoundError,
5655
ContainsArrayError,
5756
ContainsGroupError,
5857
GroupNotFoundError,
@@ -83,19 +82,20 @@
8382
DefaultT = TypeVar("DefaultT")
8483

8584

86-
def parse_zarr_format(data: Any) -> ZarrFormat:
85+
def parse_zarr_format(data: object) -> ZarrFormat:
8786
"""Parse the zarr_format field from metadata."""
88-
if data in (2, 3):
87+
if data in get_args(ZarrFormat):
8988
return cast(ZarrFormat, data)
90-
msg = f"Invalid zarr_format. Expected one of 2 or 3. Got {data}."
89+
msg = f"Invalid zarr_format. Expected one of 2 or 3. Got {data!r}."
9190
raise ValueError(msg)
9291

9392

94-
def parse_node_type(data: Any) -> NodeType:
93+
def parse_node_type(data: object) -> NodeType:
9594
"""Parse the node_type field from metadata."""
96-
if data in ("array", "group"):
97-
return cast(Literal["array", "group"], data)
98-
raise MetadataValidationError("node_type", "array or group", data)
95+
if data in get_args(NodeType):
96+
return cast(NodeType, data)
97+
msg = (f"Invalid node_type. Expected 'array' or 'group'. Got {data!r}.",)
98+
raise ValueError(msg)
9999

100100

101101
# todo: convert None to empty dict
@@ -532,10 +532,10 @@ async def open(
532532
zarr_json_bytes = await (store_path / ZARR_JSON).get()
533533
if zarr_json_bytes is None:
534534
msg = (
535-
"Zarr V3 group metadata was not found in "
535+
"Zarr V3 group metadata was not found in store "
536536
f"{store_path.store!r} at path {store_path.path!r}."
537537
)
538-
raise GroupNotFoundError(store_path.store, store_path.path)
538+
raise GroupNotFoundError(msg)
539539
elif zarr_format is None:
540540
(
541541
zarr_json_bytes,
@@ -569,8 +569,10 @@ async def open(
569569
else:
570570
zarr_format = 2
571571
else:
572-
msg = f"Invalid value for zarr_format. Expected one of 2, 3 or None. Got {zarr_format}." # type: ignore[unreachable]
573-
raise MetadataValidationError(msg)
572+
msg = ( # type: ignore[unreachable]
573+
f"Invalid value for zarr_format. Expected one of 2, 3, or None. Got {zarr_format}."
574+
)
575+
raise ValueError(msg)
574576

575577
if zarr_format == 2:
576578
# this is checked above, asserting here for mypy
@@ -718,7 +720,7 @@ async def getitem(
718720
return await get_node(
719721
store=store_path.store, path=store_path.path, zarr_format=self.metadata.zarr_format
720722
)
721-
except (ArrayNotFoundError, GroupNotFoundError) as e:
723+
except NodeNotFoundError as e:
722724
raise KeyError(key) from e
723725

724726
def _getitem_consolidated(
@@ -3052,9 +3054,9 @@ async def create_hierarchy(
30523054
for key, extant_node in extant_node_query.items():
30533055
proposed_node = nodes_parsed[key]
30543056
if isinstance(extant_node, BaseException):
3055-
if isinstance(extant_node, (ArrayNotFoundError, GroupNotFoundError)):
3056-
# ignore ArrayNotFoundError / GroupNotFoundError.
3057-
# They represent nodes we can safely create.
3057+
if isinstance(extant_node, NodeNotFoundError):
3058+
# ignore NodeNotFoundErrpr.
3059+
# it represents a node we can safely create.
30583060
pass
30593061
else:
30603062
# Any other exception is a real error
@@ -3071,10 +3073,12 @@ async def create_hierarchy(
30713073
else:
30723074
# we have proposed an explicit group, which is an error, given that a
30733075
# group already exists.
3074-
raise ContainsGroupError(store, key)
3076+
msg = f"A group exists in store {store!r} at path {key!r}."
3077+
raise ContainsGroupError(msg)
30753078
elif isinstance(extant_node, ArrayV2Metadata | ArrayV3Metadata):
30763079
# we are trying to overwrite an existing array. this is an error.
3077-
raise ContainsArrayError(store, key)
3080+
msg = f"An array exists in store {store!r} at path {key!r}."
3081+
raise ContainsArrayError(msg)
30783082

30793083
nodes_explicit: dict[str, GroupMetadata | ArrayV2Metadata | ArrayV3Metadata] = {}
30803084

@@ -3435,15 +3439,14 @@ async def _read_metadata_v2(store: Store, path: str) -> ArrayV2Metadata | GroupM
34353439
if zarray_bytes is not None:
34363440
zmeta = json.loads(zarray_bytes.to_bytes())
34373441
else:
3438-
if zgroup_bytes is None:
3442+
if zgroup_bytes is not None:
3443+
zmeta = json.loads(zgroup_bytes.to_bytes())
3444+
else:
34393445
# neither .zarray or .zgroup were found results in NodeNotFoundError
34403446
msg = (
3441-
"Neither array nor group metadata were found in "
3442-
f"{store!r} at path {path!r}."
3447+
f"Neither array nor group metadata were found in store {store!r} at path {path!r}."
34433448
)
34443449
raise NodeNotFoundError(msg)
3445-
else:
3446-
zmeta = json.loads(zgroup_bytes.to_bytes())
34473450

34483451
return _build_metadata_v2(zmeta, zattrs)
34493452

@@ -3461,8 +3464,11 @@ async def _read_group_metadata_v2(store: Store, path: str) -> GroupMetadata:
34613464
msg = f"A group metadata document was not found in store {store!r} at path {path!r}."
34623465
raise GroupNotFoundError(msg) from e
34633466
if not isinstance(meta, GroupMetadata):
3464-
msg = (f"Group metadata was not found in store {store!r} at path {path!r}. ",)
3465-
"An array metadata document was found there instead."
3467+
# TODO: test this exception
3468+
msg = (
3469+
f"Group metadata was not found in store {store!r} at path {path!r}. "
3470+
"An array metadata document was found there instead."
3471+
)
34663472
raise GroupNotFoundError(msg)
34673473
return meta
34683474

@@ -3480,8 +3486,11 @@ async def _read_group_metadata_v3(store: Store, path: str) -> GroupMetadata:
34803486
msg = f"A group metadata document was not found in store {store!r} at path {path!r}."
34813487
raise GroupNotFoundError(msg) from e
34823488
if not isinstance(meta, GroupMetadata):
3483-
msg = (f"Group metadata was not found in store {store!r} at path {path!r}. ",)
3484-
"An array metadata document was found there instead."
3489+
# TODO: test this exception
3490+
msg = (
3491+
f"Group metadata was not found in store {store!r} at path {path!r}. "
3492+
"An array metadata document was found there instead."
3493+
)
34853494
raise GroupNotFoundError(msg)
34863495
return meta
34873496

@@ -3499,7 +3508,11 @@ def _build_metadata_v3(zarr_json: dict[str, JSON]) -> ArrayV3Metadata | GroupMet
34993508
Convert a dict representation of Zarr V3 metadata into the corresponding metadata class.
35003509
"""
35013510
if "node_type" not in zarr_json:
3502-
raise MetadataValidationError("node_type", "array or group", "nothing (the key is missing)")
3511+
msg = (
3512+
"Invalid value for 'node_type'. "
3513+
"Expected 'array' or 'group'. Got nothing (the key is missing)."
3514+
)
3515+
raise MetadataValidationError(msg)
35033516
match zarr_json:
35043517
case {"node_type": "array"}:
35053518
return ArrayV3Metadata.from_dict(zarr_json)

src/zarr/core/metadata/v3.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@
5555
def parse_zarr_format(data: object) -> Literal[3]:
5656
if data == 3:
5757
return 3
58-
raise MetadataValidationError("zarr_format", 3, data)
58+
msg = f"Invalid value for zarr_format. Expected 3. Got {data!r}."
59+
raise MetadataValidationError(msg)
5960

6061

6162
def parse_node_type_array(data: object) -> Literal["array"]:
6263
if data == "array":
6364
return "array"
64-
raise NodeTypeValidationError("node_type", "array", data)
65+
msg = f"Invalid value for node_type. Expected 'array'. Got {data!r}."
66+
raise NodeTypeValidationError(msg)
6567

6668

6769
def parse_codecs(data: object) -> tuple[Codec, ...]:

0 commit comments

Comments
 (0)