Skip to content

Commit 03176cf

Browse files
committed
review errors
1 parent c108183 commit 03176cf

5 files changed

Lines changed: 90 additions & 52 deletions

File tree

‎zarr/core.py‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from zarr.codecs import AsType, get_codec
1919
from zarr.indexing import (OIndex, OrthogonalIndexer, BasicIndexer, VIndex, CoordinateIndexer,
2020
MaskIndexer, check_fields, pop_fields, ensure_tuple, is_scalar,
21-
is_contiguous_selection)
21+
is_contiguous_selection, err_too_many_indices, check_no_multi_fields)
2222

2323

2424
# noinspection PyUnresolvedReferences
@@ -173,7 +173,7 @@ def _refresh_metadata_nosync(self):
173173

174174
def _flush_metadata_nosync(self):
175175
if self._is_view:
176-
raise PermissionError('not permitted for views')
176+
raise PermissionError('operation not permitted for views')
177177

178178
if self._compressor:
179179
compressor_config = self._compressor.get_config()
@@ -403,6 +403,7 @@ def __len__(self):
403403
if self.shape:
404404
return self.shape[0]
405405
else:
406+
# 0-dimensional array, same error message as numpy
406407
raise TypeError('len() of unsized object')
407408

408409
def __getitem__(self, selection):
@@ -662,7 +663,7 @@ def _get_basic_selection_zd(self, selection, out=None, fields=None):
662663
# check selection is valid
663664
selection = ensure_tuple(selection)
664665
if selection not in ((), (Ellipsis,)):
665-
raise IndexError('too many indices for array')
666+
err_too_many_indices(selection, ())
666667

667668
try:
668669
# obtain encoded data for chunk
@@ -1413,12 +1414,11 @@ def _set_basic_selection_zd(self, selection, value, fields=None):
14131414
# check selection is valid
14141415
selection = ensure_tuple(selection)
14151416
if selection not in ((), (Ellipsis,)):
1416-
raise IndexError('too many indices for array')
1417+
err_too_many_indices(selection, self._shape)
14171418

14181419
# check fields
14191420
check_fields(fields, self._dtype)
1420-
if fields and isinstance(fields, list):
1421-
raise ValueError('multi-field assignment is not supported')
1421+
fields = check_no_multi_fields(fields)
14221422

14231423
# obtain key for chunk
14241424
ckey = self._chunk_key((0,))
@@ -1467,8 +1467,7 @@ def _set_selection(self, indexer, value, fields=None):
14671467

14681468
# check fields are sensible
14691469
check_fields(fields, self._dtype)
1470-
if fields and isinstance(fields, list):
1471-
raise ValueError('multi-field assignment is not supported')
1470+
fields = check_no_multi_fields(fields)
14721471

14731472
# determine indices of chunks overlapping the selection
14741473
sel_shape = indexer.shape
@@ -1944,7 +1943,8 @@ def _append_nosync(self, data, axis=0):
19441943
data_shape_preserved = tuple(s for i, s in enumerate(data.shape)
19451944
if i != axis)
19461945
if self_shape_preserved != data_shape_preserved:
1947-
raise ValueError('shapes not compatible')
1946+
raise ValueError('shape of data to append is not compatible with the array; all '
1947+
'dimensions must match except for the dimension being appended')
19481948

19491949
# remember old shape
19501950
old_shape = self._shape
@@ -2074,7 +2074,7 @@ def view(self, shape=None, chunks=None, dtype=None,
20742074
... v.resize(20000)
20752075
... except PermissionError as e:
20762076
... print(e)
2077-
not permitted for views
2077+
operation not permitted for views
20782078
20792079
"""
20802080

‎zarr/errors.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,23 @@ def err_fspath_exists_notdir(fspath):
5050

5151
def err_read_only():
5252
raise PermissionError('object is read-only')
53+
54+
55+
def err_boundscheck(dim_len):
56+
raise IndexError('index out of bounds for dimension with length {}'
57+
.format(dim_len))
58+
59+
60+
def err_negative_step():
61+
raise IndexError('only slices with step >= 1 are supported')
62+
63+
64+
def err_too_many_indices(selection, shape):
65+
raise IndexError('too many indices for array; expected {}, got {}'
66+
.format(len(shape), len(selection)))
67+
68+
69+
def err_vindex_invalid_selection(selection):
70+
raise IndexError('unsupported selection type for vectorized indexing; only coordinate '
71+
'selection (tuple of integer arrays) and mask selection (single '
72+
'Boolean array) are supported; got {!r}'.format(selection))

‎zarr/hierarchy.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,21 +719,27 @@ def _require_dataset_nosync(self, name, shape, dtype=None, exact=False,
719719
path = self._item_path(name)
720720

721721
if contains_array(self._store, path):
722+
723+
# array already exists at path, validate that it is the right shape and type
724+
722725
synchronizer = kwargs.get('synchronizer', self._synchronizer)
723726
cache_metadata = kwargs.get('cache_metadata', True)
724727
a = Array(self._store, path=path, read_only=self._read_only,
725728
chunk_store=self._chunk_store, synchronizer=synchronizer,
726729
cache_metadata=cache_metadata)
727730
shape = normalize_shape(shape)
728731
if shape != a.shape:
729-
raise TypeError('shapes do not match')
732+
raise TypeError('shape do not match existing array; expected {}, got {}'
733+
.format(a.shape, shape))
730734
dtype = np.dtype(dtype)
731735
if exact:
732736
if dtype != a.dtype:
733-
raise TypeError('dtypes do not match exactly')
737+
raise TypeError('dtypes do not match exactly; expected {}, got {}'
738+
.format(a.dtype, dtype))
734739
else:
735740
if not np.can_cast(dtype, a.dtype):
736-
raise TypeError('dtypes cannot be safely cast')
741+
raise TypeError('dtypes ({}, {}) cannot be safely cast'
742+
.format(dtype, a.dtype))
737743
return a
738744

739745
else:

‎zarr/indexing.py‎

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import numpy as np
99

1010

11+
from zarr.errors import (err_too_many_indices, err_boundscheck, err_negative_step,
12+
err_vindex_invalid_selection)
13+
14+
1115
def is_integer(x):
1216
return isinstance(x, numbers.Integral)
1317

@@ -34,11 +38,6 @@ def is_scalar(value, dtype):
3438
return False
3539

3640

37-
def err_boundscheck(dim_len):
38-
raise IndexError('index out of bounds for dimension with length {}'
39-
.format(dim_len))
40-
41-
4241
def normalize_integer_selection(dim_sel, dim_len):
4342

4443
# normalize type to int
@@ -96,10 +95,6 @@ def ceildiv(a, b):
9695
return int(np.ceil(a / b))
9796

9897

99-
def err_negative_step():
100-
raise IndexError('only slices with step >= 1 are supported')
101-
102-
10398
class SliceDimIndexer(object):
10499

105100
def __init__(self, dim_sel, dim_len, dim_chunk_len):
@@ -160,6 +155,11 @@ def __iter__(self):
160155
yield ChunkDimProjection(dim_chunk_ix, dim_chunk_sel, dim_out_sel)
161156

162157

158+
def check_selection_length(selection, shape):
159+
if len(selection) > len(shape):
160+
err_too_many_indices(selection, shape)
161+
162+
163163
def replace_ellipsis(selection, shape):
164164

165165
selection = ensure_tuple(selection)
@@ -193,9 +193,7 @@ def replace_ellipsis(selection, shape):
193193
selection += (slice(None),) * (len(shape) - len(selection))
194194

195195
# check selection not too long
196-
if len(selection) > len(shape):
197-
raise IndexError('too many indices for array; expected {}, got {}'
198-
.format(len(shape), len(selection)))
196+
check_selection_length(selection, shape)
199197

200198
return selection
201199

@@ -732,12 +730,6 @@ def __init__(self, selection, array):
732730
super(MaskIndexer, self).__init__(selection, array)
733731

734732

735-
def err_vindex_invalid_selection(selection):
736-
raise IndexError('unsupported selection type for vectorized indexing; only coordinate '
737-
'selection (tuple of integer arrays) and mask selection (single '
738-
'Boolean array) are supported; got {!r}'.format(selection))
739-
740-
741733
class VIndex(object):
742734

743735
def __init__(self, array):
@@ -792,6 +784,15 @@ def check_fields(fields, dtype):
792784
return dtype
793785

794786

787+
def check_no_multi_fields(fields):
788+
if isinstance(fields, list):
789+
if len(fields) == 1:
790+
return fields[0]
791+
elif len(fields) > 1:
792+
raise IndexError('multiple fields are not supported for this operation')
793+
return fields
794+
795+
795796
def pop_fields(selection):
796797
if isinstance(selection, str):
797798
# single field selection

‎zarr/tests/test_indexing.py‎

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,9 @@ def test_set_basic_selection_0d():
324324
eq(v['bar'], z['bar'])
325325
eq(a['baz'], z['baz'])
326326
# multiple field assignment not supported
327-
with assert_raises(ValueError):
327+
with assert_raises(IndexError):
328328
z.set_basic_selection(Ellipsis, v[['foo', 'bar']], fields=['foo', 'bar'])
329-
with assert_raises(ValueError):
329+
with assert_raises(IndexError):
330330
z[..., 'foo', 'bar'] = v[['foo', 'bar']]
331331

332332

@@ -1213,6 +1213,7 @@ def test_set_selections_with_fields():
12131213

12141214
fields_fixture = [
12151215
'foo',
1216+
[],
12161217
['foo'],
12171218
['foo', 'bar'],
12181219
['foo', 'baz'],
@@ -1225,54 +1226,64 @@ def test_set_selections_with_fields():
12251226
for fields in fields_fixture:
12261227

12271228
# currently multi-field assignment is not supported in numpy, so we won't support it either
1228-
if isinstance(fields, list):
1229-
with assert_raises(ValueError):
1230-
z.set_basic_selection(Ellipsis, v[fields], fields=fields)
1231-
with assert_raises(ValueError):
1232-
z.set_orthogonal_selection([0, 2], v[fields], fields=fields)
1233-
with assert_raises(ValueError):
1234-
z.set_coordinate_selection([0, 2], v[fields], fields=fields)
1235-
with assert_raises(ValueError):
1236-
z.set_mask_selection([True, False, True], v[fields], fields=fields)
1229+
if isinstance(fields, list) and len(fields) > 1:
1230+
with assert_raises(IndexError):
1231+
z.set_basic_selection(Ellipsis, v, fields=fields)
1232+
with assert_raises(IndexError):
1233+
z.set_orthogonal_selection([0, 2], v, fields=fields)
1234+
with assert_raises(IndexError):
1235+
z.set_coordinate_selection([0, 2], v, fields=fields)
1236+
with assert_raises(IndexError):
1237+
z.set_mask_selection([True, False, True], v, fields=fields)
12371238

12381239
else:
12391240

1241+
if isinstance(fields, list) and len(fields) == 1:
1242+
# work around numpy does not support multi-field assignment even if there is only
1243+
# one field
1244+
key = fields[0]
1245+
elif isinstance(fields, list) and len(fields) == 0:
1246+
# work around numpy ambiguity about what is a field selection
1247+
key = Ellipsis
1248+
else:
1249+
key = fields
1250+
12401251
# setup expectation
12411252
a[:] = ('', 0, 0)
12421253
z[:] = ('', 0, 0)
12431254
assert_array_equal(a, z[:])
1244-
a[fields] = v[fields]
1255+
a[key] = v[key]
12451256
# total selection
1246-
z.set_basic_selection(Ellipsis, v[fields], fields=fields)
1257+
z.set_basic_selection(Ellipsis, v[key], fields=fields)
12471258
assert_array_equal(a, z[:])
12481259

12491260
# basic selection with slice
12501261
a[:] = ('', 0, 0)
12511262
z[:] = ('', 0, 0)
1252-
a[fields][0:2] = v[fields][0:2]
1253-
z.set_basic_selection(slice(0, 2), v[0:2][fields], fields=fields)
1263+
a[key][0:2] = v[key][0:2]
1264+
z.set_basic_selection(slice(0, 2), v[key][0:2], fields=fields)
12541265
assert_array_equal(a, z[:])
12551266

12561267
# orthogonal selection
12571268
a[:] = ('', 0, 0)
12581269
z[:] = ('', 0, 0)
12591270
ix = [0, 2]
1260-
a[fields][ix] = v[fields][ix]
1261-
z.set_orthogonal_selection(ix, v[fields][ix], fields=fields)
1271+
a[key][ix] = v[key][ix]
1272+
z.set_orthogonal_selection(ix, v[key][ix], fields=fields)
12621273
assert_array_equal(a, z[:])
12631274

12641275
# coordinate selection
12651276
a[:] = ('', 0, 0)
12661277
z[:] = ('', 0, 0)
12671278
ix = [0, 2]
1268-
a[fields][ix] = v[fields][ix]
1269-
z.set_coordinate_selection(ix, v[fields][ix], fields=fields)
1279+
a[key][ix] = v[key][ix]
1280+
z.set_coordinate_selection(ix, v[key][ix], fields=fields)
12701281
assert_array_equal(a, z[:])
12711282

12721283
# mask selection
12731284
a[:] = ('', 0, 0)
12741285
z[:] = ('', 0, 0)
12751286
ix = [True, False, True]
1276-
a[fields][ix] = v[fields][ix]
1277-
z.set_mask_selection(ix, v[fields][ix], fields=fields)
1287+
a[key][ix] = v[key][ix]
1288+
z.set_mask_selection(ix, v[key][ix], fields=fields)
12781289
assert_array_equal(a, z[:])

0 commit comments

Comments
 (0)