2828
2929from zarr .core .common import ceildiv , product
3030from zarr .core .metadata import T_ArrayMetadata
31+ from zarr .errors import (
32+ ArrayIndexError ,
33+ BoundsCheckError ,
34+ NegativeStepError ,
35+ VindexInvalidSelectionError ,
36+ )
3137
3238if TYPE_CHECKING :
3339 from zarr .core .array import Array , AsyncArray
5157Fields = str | list [str ] | tuple [str , ...]
5258
5359
54- class ArrayIndexError (IndexError ):
55- pass
56-
57-
58- class BoundsCheckError (IndexError ):
59- _msg = ""
60-
61- def __init__ (self , dim_len : int ) -> None :
62- self ._msg = f"index out of bounds for dimension with length { dim_len } "
63-
64-
65- class NegativeStepError (IndexError ):
66- _msg = "only slices with step >= 1 are supported"
67-
68-
69- class VindexInvalidSelectionError (IndexError ):
70- _msg = (
71- "unsupported selection type for vectorized indexing; only "
72- "coordinate selection (tuple of integer arrays) and mask selection "
73- "(single Boolean array) are supported; got {!r}"
74- )
75-
76-
7760def err_too_many_indices (selection : Any , shape : tuple [int , ...]) -> None :
7861 raise IndexError (f"too many indices for array; expected { len (shape )} , got { len (selection )} " )
7962
@@ -361,7 +344,8 @@ def normalize_integer_selection(dim_sel: int, dim_len: int) -> int:
361344
362345 # handle out of bounds
363346 if dim_sel >= dim_len or dim_sel < 0 :
364- raise BoundsCheckError (dim_len )
347+ msg = f"index out of bounds for dimension with length { dim_len } "
348+ raise BoundsCheckError (msg )
365349
366350 return dim_sel
367351
@@ -421,7 +405,7 @@ def __init__(self, dim_sel: slice, dim_len: int, dim_chunk_len: int) -> None:
421405 # normalize
422406 start , stop , step = dim_sel .indices (dim_len )
423407 if step < 1 :
424- raise NegativeStepError
408+ raise NegativeStepError ( "only slices with step >= 1 are supported." )
425409
426410 object .__setattr__ (self , "start" , start )
427411 object .__setattr__ (self , "stop" , stop )
@@ -744,7 +728,8 @@ def wraparound_indices(x: npt.NDArray[Any], dim_len: int) -> None:
744728
745729def boundscheck_indices (x : npt .NDArray [Any ], dim_len : int ) -> None :
746730 if np .any (x < 0 ) or np .any (x >= dim_len ):
747- raise BoundsCheckError (dim_len )
731+ msg = f"index out of bounds for dimension with length { dim_len } "
732+ raise BoundsCheckError (msg )
748733
749734
750735@dataclass (frozen = True )
@@ -1098,7 +1083,8 @@ def __init__(
10981083 dim_indexers .append (dim_indexer )
10991084
11001085 if start >= dim_len or start < 0 :
1101- raise BoundsCheckError (dim_len )
1086+ msg = f"index out of bounds for dimension with length { dim_len } "
1087+ raise BoundsCheckError (msg )
11021088
11031089 shape = tuple (s .nitems for s in dim_indexers )
11041090
@@ -1329,7 +1315,12 @@ def __getitem__(
13291315 elif is_mask_selection (new_selection , self .array .shape ):
13301316 return self .array .get_mask_selection (new_selection , fields = fields )
13311317 else :
1332- raise VindexInvalidSelectionError (new_selection )
1318+ msg = (
1319+ "unsupported selection type for vectorized indexing; only "
1320+ "coordinate selection (tuple of integer arrays) and mask selection "
1321+ f"(single Boolean array) are supported; got { new_selection !r} "
1322+ )
1323+ raise VindexInvalidSelectionError (msg )
13331324
13341325 def __setitem__ (
13351326 self , selection : CoordinateSelection | MaskSelection , value : npt .ArrayLike
@@ -1342,7 +1333,12 @@ def __setitem__(
13421333 elif is_mask_selection (new_selection , self .array .shape ):
13431334 self .array .set_mask_selection (new_selection , value , fields = fields )
13441335 else :
1345- raise VindexInvalidSelectionError (new_selection )
1336+ msg = (
1337+ "unsupported selection type for vectorized indexing; only "
1338+ "coordinate selection (tuple of integer arrays) and mask selection "
1339+ f"(single Boolean array) are supported; got { new_selection !r} "
1340+ )
1341+ raise VindexInvalidSelectionError (msg )
13461342
13471343
13481344@dataclass (frozen = True )
@@ -1368,7 +1364,12 @@ async def getitem(
13681364 elif is_mask_selection (new_selection , self .array .shape ):
13691365 return await self .array .get_mask_selection (new_selection , fields = fields )
13701366 else :
1371- raise VindexInvalidSelectionError (new_selection )
1367+ msg = (
1368+ "unsupported selection type for vectorized indexing; only "
1369+ "coordinate selection (tuple of integer arrays) and mask selection "
1370+ f"(single Boolean array) are supported; got { new_selection !r} "
1371+ )
1372+ raise VindexInvalidSelectionError (msg )
13721373
13731374
13741375def check_fields (fields : Fields | None , dtype : np .dtype [Any ]) -> np .dtype [Any ]:
@@ -1487,7 +1488,12 @@ def get_indexer(
14871488 elif is_mask_selection (new_selection , shape ):
14881489 return MaskIndexer (cast ("MaskSelection" , selection ), shape , chunk_grid )
14891490 else :
1490- raise VindexInvalidSelectionError (new_selection )
1491+ msg = (
1492+ "unsupported selection type for vectorized indexing; only "
1493+ "coordinate selection (tuple of integer arrays) and mask selection "
1494+ f"(single Boolean array) are supported; got { new_selection !r} "
1495+ )
1496+ raise VindexInvalidSelectionError (msg )
14911497 elif is_pure_orthogonal_indexing (pure_selection , len (shape )):
14921498 return OrthogonalIndexer (cast ("OrthogonalSelection" , selection ), shape , chunk_grid )
14931499 else :
0 commit comments