Skip to content

Commit 29cf195

Browse files
jrbourbeaujakirkham
authored andcommitted
Add recurse keyword to array_keys and arrays (#458)
* Adds recurse keyword to array_keys and arrays * Adds item to release notes
1 parent 6f1d212 commit 29cf195

File tree

3 files changed

+56
-10
lines changed

3 files changed

+56
-10
lines changed

docs/release.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Release notes
44
Upcoming Release
55
----------------
66

7+
* Add ``recurse`` keyword to ``Group.array_keys`` and ``Group.arrays`` methods.
8+
By :user:`James Bourbeau <jrbourbeau>`; :issue:`458`
9+
710
* Use uniform chunking for all dimensions when specifying ``chunks`` as an integer.
811
Also adds support for specifying ``-1`` to chunk across an entire dimension.
912
By :user:`James Bourbeau <jrbourbeau>`; :issue:`456`.

zarr/hierarchy.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,16 @@ def groups(self):
406406
cache_attrs=self.attrs.cache,
407407
synchronizer=self._synchronizer)
408408

409-
def array_keys(self):
409+
def array_keys(self, recurse=False):
410410
"""Return an iterator over member names for arrays only.
411411
412+
Parameters
413+
----------
414+
recurse : recurse, optional
415+
Option to return member names for all arrays, even from groups
416+
below the current one. If False, only member names for arrays in
417+
the current group will be returned. Default value is False.
418+
412419
Examples
413420
--------
414421
>>> import zarr
@@ -421,14 +428,20 @@ def array_keys(self):
421428
['baz', 'quux']
422429
423430
"""
424-
for key in sorted(listdir(self._store, self._path)):
425-
path = self._key_prefix + key
426-
if contains_array(self._store, path):
427-
yield key
431+
return self._array_iter(keys_only=True,
432+
method='array_keys',
433+
recurse=recurse)
428434

429-
def arrays(self):
435+
def arrays(self, recurse=False):
430436
"""Return an iterator over (name, value) pairs for arrays only.
431437
438+
Parameters
439+
----------
440+
recurse : recurse, optional
441+
Option to return (name, value) pairs for all arrays, even from groups
442+
below the current one. If False, only (name, value) pairs for arrays in
443+
the current group will be returned. Default value is False.
444+
432445
Examples
433446
--------
434447
>>> import zarr
@@ -443,13 +456,19 @@ def arrays(self):
443456
quux <class 'zarr.core.Array'>
444457
445458
"""
459+
return self._array_iter(keys_only=False,
460+
method='arrays',
461+
recurse=recurse)
462+
463+
def _array_iter(self, keys_only, method, recurse):
446464
for key in sorted(listdir(self._store, self._path)):
447465
path = self._key_prefix + key
448466
if contains_array(self._store, path):
449-
yield key, Array(self._store, path=path, read_only=self._read_only,
450-
chunk_store=self._chunk_store,
451-
cache_attrs=self.attrs.cache,
452-
synchronizer=self._synchronizer)
467+
yield key if keys_only else (key, self[key])
468+
elif recurse and contains_group(self._store, path):
469+
group = self[key]
470+
for i in getattr(group, method)(recurse=recurse):
471+
yield i
453472

454473
def visitvalues(self, func):
455474
"""Run ``func`` on each object.

zarr/tests/test_hierarchy.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,30 @@ def test_empty_getitem_contains_iterators(self):
636636
assert 0 == len(g)
637637
assert 'foo' not in g
638638

639+
def test_iterators_recurse(self):
640+
# setup
641+
g1 = self.create_group()
642+
g2 = g1.create_group('foo/bar')
643+
d1 = g2.create_dataset('/a/b/c', shape=1000, chunks=100)
644+
d1[:] = np.arange(1000)
645+
d2 = g1.create_dataset('foo/baz', shape=3000, chunks=300)
646+
d2[:] = np.arange(3000)
647+
d3 = g2.create_dataset('zab', shape=2000, chunks=200)
648+
d3[:] = np.arange(2000)
649+
650+
# test recursive array_keys
651+
array_keys = list(g1['foo'].array_keys(recurse=False))
652+
array_keys_recurse = list(g1['foo'].array_keys(recurse=True))
653+
assert len(array_keys_recurse) > len(array_keys)
654+
assert sorted(array_keys_recurse) == ['baz', 'zab']
655+
656+
# test recursive arrays
657+
arrays = list(g1['foo'].arrays(recurse=False))
658+
arrays_recurse = list(g1['foo'].arrays(recurse=True))
659+
assert len(arrays_recurse) > len(arrays)
660+
assert 'zab' == arrays_recurse[0][0]
661+
assert g1['foo']['bar']['zab'] == arrays_recurse[0][1]
662+
639663
def test_getattr(self):
640664
# setup
641665
g1 = self.create_group()

0 commit comments

Comments
 (0)