Skip to content

Commit a03b294

Browse files
committed
fix some issues with DictStore
1 parent 04aeb50 commit a03b294

File tree

2 files changed

+98
-18
lines changed

2 files changed

+98
-18
lines changed

zarr/storage.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,10 @@ def __init__(self, cls=dict):
340340
def __getitem__(self, key):
341341
c = self.root
342342
for k in key.split('/'):
343-
c = c[k]
343+
if isinstance(c, self.cls):
344+
c = c[k]
345+
else:
346+
raise KeyError(key)
344347
if isinstance(c, self.cls):
345348
raise KeyError(key)
346349
return c
@@ -351,35 +354,48 @@ def __setitem__(self, key, value):
351354

352355
# ensure intermediate containers
353356
for k in keys[:-1]:
354-
try:
355-
c = c[k]
356-
if not isinstance(c, self.cls):
357-
raise KeyError(key)
358-
except KeyError:
359-
c[k] = self.cls()
360-
c = c[k]
357+
if isinstance(c, self.cls):
358+
try:
359+
c = c[k]
360+
except KeyError:
361+
c[k] = self.cls()
362+
c = c[k]
363+
else:
364+
raise KeyError(key)
361365

362-
# set final value
363-
c[keys[-1]] = value
366+
if isinstance(c, self.cls):
367+
# set final value
368+
c[keys[-1]] = value
369+
else:
370+
raise KeyError(key)
364371

365372
def __delitem__(self, key):
366373
c = self.root
367374
keys = key.split('/')
368375

369376
# obtain final container
370377
for k in keys[:-1]:
371-
c = c[k]
378+
if isinstance(c, self.cls):
379+
c = c[k]
380+
else:
381+
raise KeyError(key)
372382

373-
# delete item
374-
del c[keys[-1]]
383+
if isinstance(c, self.cls):
384+
# delete item
385+
del c[keys[-1]]
386+
else:
387+
raise KeyError(key)
375388

376389
def __contains__(self, key):
377390
keys = key.split('/')
378391
c = self.root
379392
for k in keys:
380-
try:
381-
c = c[k]
382-
except KeyError:
393+
if isinstance(c, self.cls):
394+
try:
395+
c = c[k]
396+
except KeyError:
397+
return False
398+
else:
383399
return False
384400
return not isinstance(c, self.cls)
385401

zarr/tests/test_hierarchy.py

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,22 +187,27 @@ def test_create_dataset(self):
187187
eq('/bar', d3.name)
188188
assert_is(store, d3.store)
189189

190-
def test_getitem_contains(self):
190+
def test_getitem_contains_iterators(self):
191191
# setup
192192
store = self.create_store()
193193
init_group(store)
194194
g1 = Group(store=store)
195195
g2 = g1.create_group('foo/bar')
196-
d1 = g1.create_dataset('a/b/c', shape=1000, chunks=100)
196+
d1 = g2.create_dataset('/a/b/c', shape=1000, chunks=100)
197197
d1[:] = np.arange(1000)
198+
d2 = g1.create_dataset('foo/baz', shape=3000, chunks=300)
199+
d2[:] = np.arange(3000)
198200

199201
# test __getitem__
200202
assert_is_instance(g1['foo'], Group)
201203
assert_is_instance(g1['foo']['bar'], Group)
202204
assert_is_instance(g1['foo/bar'], Group)
203205
assert_is_instance(g1['/foo/bar/'], Group)
206+
assert_is_instance(g1['foo/baz'], Array)
204207
eq(g2, g1['foo/bar'])
205208
eq(g1['foo']['bar'], g1['foo/bar'])
209+
eq(d2, g1['foo/baz'])
210+
assert_array_equal(d2[:], g1['foo/baz'])
206211
assert_is_instance(g1['a'], Group)
207212
assert_is_instance(g1['a']['b'], Group)
208213
assert_is_instance(g1['a/b'], Group)
@@ -215,27 +220,68 @@ def test_getitem_contains(self):
215220
# test __contains__
216221
assert 'foo' in g1
217222
assert 'foo/bar' in g1
223+
assert 'foo/baz' in g1
218224
assert 'bar' in g1['foo']
219225
assert 'a' in g1
220226
assert 'a/b' in g1
221227
assert 'a/b/c' in g1
222228
assert 'baz' not in g1
223229
assert 'a/b/c/d' not in g1
224230
assert 'a/z' not in g1
231+
assert 'quux' not in g1['foo']
225232

226233
# test key errors
227234
with assert_raises(KeyError):
228235
g1['baz']
229236
with assert_raises(KeyError):
230237
g1['x/y/z']
231238

239+
# test __len__
240+
eq(2, len(g1))
241+
eq(2, len(g1['foo']))
242+
eq(0, len(g1['foo/bar']))
243+
eq(1, len(g1['a']))
244+
eq(1, len(g1['a/b']))
245+
246+
# test keys()
247+
eq(['a', 'foo'], sorted(g1.keys()))
248+
eq(['bar', 'baz'], sorted(g1['foo'].keys()))
249+
eq([], sorted(g1['foo/bar'].keys()))
250+
251+
def test_empty_getitem_contains_iterators(self):
252+
# setup
253+
store = self.create_store()
254+
init_group(store)
255+
g = Group(store=store)
256+
257+
# test
258+
eq([], list(g.keys()))
259+
eq(0, len(g))
260+
assert 'foo' not in g
261+
262+
def test_group_repr(self):
263+
store = self.create_store()
264+
init_group(store)
265+
g = Group(store=store)
266+
expect = 'zarr.hierarchy.Group(/, 0)\n store: builtins.dict'
267+
actual = repr(g)
268+
eq(expect, actual)
269+
232270

233271
class TestGroupDictStore(TestGroup):
234272

235273
@staticmethod
236274
def create_store():
237275
return DictStore()
238276

277+
def test_group_repr(self):
278+
store = self.create_store()
279+
init_group(store)
280+
g = Group(store=store)
281+
expect = 'zarr.hierarchy.Group(/, 0)\n store: zarr.storage.DictStore'
282+
actual = repr(g)
283+
eq(expect, actual)
284+
239285

240286
def rmtree_if_exists(path, rmtree=shutil.rmtree, isdir=os.path.isdir):
241287
if isdir(path):
@@ -251,6 +297,15 @@ def create_store():
251297
store = DirectoryStore(path)
252298
return store
253299

300+
def test_group_repr(self):
301+
store = self.create_store()
302+
init_group(store)
303+
g = Group(store=store)
304+
expect = 'zarr.hierarchy.Group(/, 0)\n' \
305+
' store: zarr.storage.DirectoryStore'
306+
actual = repr(g)
307+
eq(expect, actual)
308+
254309

255310
class TestGroupZipStore(TestGroup):
256311

@@ -260,3 +315,12 @@ def create_store():
260315
atexit.register(os.remove, path)
261316
store = ZipStore(path)
262317
return store
318+
319+
def test_group_repr(self):
320+
store = self.create_store()
321+
init_group(store)
322+
g = Group(store=store)
323+
expect = 'zarr.hierarchy.Group(/, 0)\n' \
324+
' store: zarr.storage.ZipStore'
325+
actual = repr(g)
326+
eq(expect, actual)

0 commit comments

Comments
 (0)