28
28
29
29
from zarr .core .common import ceildiv , product
30
30
from zarr .core .metadata import T_ArrayMetadata
31
+ from zarr .errors import (
32
+ ArrayIndexError ,
33
+ BoundsCheckError ,
34
+ NegativeStepError ,
35
+ VindexInvalidSelectionError ,
36
+ )
31
37
32
38
if TYPE_CHECKING :
33
39
from zarr .core .array import Array , AsyncArray
51
57
Fields = str | list [str ] | tuple [str , ...]
52
58
53
59
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
-
77
60
def err_too_many_indices (selection : Any , shape : tuple [int , ...]) -> None :
78
61
raise IndexError (f"too many indices for array; expected { len (shape )} , got { len (selection )} " )
79
62
@@ -361,7 +344,8 @@ def normalize_integer_selection(dim_sel: int, dim_len: int) -> int:
361
344
362
345
# handle out of bounds
363
346
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 )
365
349
366
350
return dim_sel
367
351
@@ -421,7 +405,7 @@ def __init__(self, dim_sel: slice, dim_len: int, dim_chunk_len: int) -> None:
421
405
# normalize
422
406
start , stop , step = dim_sel .indices (dim_len )
423
407
if step < 1 :
424
- raise NegativeStepError
408
+ raise NegativeStepError ( "only slices with step >= 1 are supported." )
425
409
426
410
object .__setattr__ (self , "start" , start )
427
411
object .__setattr__ (self , "stop" , stop )
@@ -744,7 +728,8 @@ def wraparound_indices(x: npt.NDArray[Any], dim_len: int) -> None:
744
728
745
729
def boundscheck_indices (x : npt .NDArray [Any ], dim_len : int ) -> None :
746
730
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 )
748
733
749
734
750
735
@dataclass (frozen = True )
@@ -1098,7 +1083,8 @@ def __init__(
1098
1083
dim_indexers .append (dim_indexer )
1099
1084
1100
1085
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 )
1102
1088
1103
1089
shape = tuple (s .nitems for s in dim_indexers )
1104
1090
@@ -1329,7 +1315,12 @@ def __getitem__(
1329
1315
elif is_mask_selection (new_selection , self .array .shape ):
1330
1316
return self .array .get_mask_selection (new_selection , fields = fields )
1331
1317
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 )
1333
1324
1334
1325
def __setitem__ (
1335
1326
self , selection : CoordinateSelection | MaskSelection , value : npt .ArrayLike
@@ -1342,7 +1333,12 @@ def __setitem__(
1342
1333
elif is_mask_selection (new_selection , self .array .shape ):
1343
1334
self .array .set_mask_selection (new_selection , value , fields = fields )
1344
1335
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 )
1346
1342
1347
1343
1348
1344
@dataclass (frozen = True )
@@ -1368,7 +1364,12 @@ async def getitem(
1368
1364
elif is_mask_selection (new_selection , self .array .shape ):
1369
1365
return await self .array .get_mask_selection (new_selection , fields = fields )
1370
1366
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 )
1372
1373
1373
1374
1374
1375
def check_fields (fields : Fields | None , dtype : np .dtype [Any ]) -> np .dtype [Any ]:
@@ -1487,7 +1488,12 @@ def get_indexer(
1487
1488
elif is_mask_selection (new_selection , shape ):
1488
1489
return MaskIndexer (cast ("MaskSelection" , selection ), shape , chunk_grid )
1489
1490
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 )
1491
1497
elif is_pure_orthogonal_indexing (pure_selection , len (shape )):
1492
1498
return OrthogonalIndexer (cast ("OrthogonalSelection" , selection ), shape , chunk_grid )
1493
1499
else :
0 commit comments