From ce7b1d2c92e901f213f71c4c3e4d9c5f2145ff70 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Tue, 24 Mar 2015 11:39:42 -0700 Subject: [PATCH] Allow ls() to list recursively (using breadth-first) Make it easier to list the contents of the full in-memory filesystem by allowing the ls() function to take a recursive keyword argument (which by default is false). This makes it easier to analyze the contents of the full in memory filesystem; saving people from creating similar code themselves. Change-Id: I573797945255cb81728e7a86b58768b848110ee7 --- taskflow/examples/dump_memory_backend.py | 7 +---- taskflow/persistence/backends/impl_memory.py | 20 +++++++++++-- .../persistence/test_memory_persistence.py | 29 +++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/taskflow/examples/dump_memory_backend.py b/taskflow/examples/dump_memory_backend.py index 7209dda0..2e3aee71 100644 --- a/taskflow/examples/dump_memory_backend.py +++ b/taskflow/examples/dump_memory_backend.py @@ -70,14 +70,9 @@ e.run() print("---------") print("After run") print("---------") -entries = [os.path.join(backend.memory.root_path, child) - for child in backend.memory.ls(backend.memory.root_path)] -while entries: - path = entries.pop() +for path in backend.memory.ls(backend.memory.root_path, recursive=True): value = backend.memory[path] if value: print("%s -> %s" % (path, value)) else: print("%s" % (path)) - entries.extend(os.path.join(path, child) - for child in backend.memory.ls(path)) diff --git a/taskflow/persistence/backends/impl_memory.py b/taskflow/persistence/backends/impl_memory.py index 7efe6ec0..778eb97a 100644 --- a/taskflow/persistence/backends/impl_memory.py +++ b/taskflow/persistence/backends/impl_memory.py @@ -110,9 +110,25 @@ class FakeFilesystem(object): else: return self._copier(node.metadata['value']) - def ls(self, path): + def ls(self, path, recursive=False): """Return list of all children of the given path.""" - return [node.item for node in self._fetch_node(path)] + if not recursive: + return [node.item for node in self._fetch_node(path)] + else: + paths = [] + node = self._fetch_node(path) + for child in node.bfs_iter(): + # Reconstruct the child's path... + hops = [child.item] + for parent in child.path_iter(include_self=False): + hops.append(parent.item) + hops.reverse() + # This avoids getting '//a/b' (duplicated sep at start)... + child_path = pp.sep.join(hops) + if child_path.startswith("//"): + child_path = child_path[1:] + paths.append(child_path) + return paths def _iter_pieces(self, path, include_root=False): if path == self._root.item: diff --git a/taskflow/tests/unit/persistence/test_memory_persistence.py b/taskflow/tests/unit/persistence/test_memory_persistence.py index 1c9f451b..069e88de 100644 --- a/taskflow/tests/unit/persistence/test_memory_persistence.py +++ b/taskflow/tests/unit/persistence/test_memory_persistence.py @@ -71,6 +71,35 @@ class MemoryFilesystemTest(test.TestCase): self.assertEqual('c', fs['/c']) self.assertEqual('db', fs['/d/b']) + def test_ls_recursive(self): + fs = impl_memory.FakeFilesystem() + fs.ensure_path("/d") + fs.ensure_path("/c/d") + fs.ensure_path("/b/c/d") + fs.ensure_path("/a/b/c/d") + contents = fs.ls("/", recursive=True) + self.assertEqual([ + '/a', + '/b', + '/c', + '/d', + '/a/b', + '/b/c', + '/c/d', + '/a/b/c', + '/b/c/d', + '/a/b/c/d', + ], contents) + + def test_ls_recursive_targeted(self): + fs = impl_memory.FakeFilesystem() + fs.ensure_path("/d") + fs.ensure_path("/c/d") + fs.ensure_path("/b/c/d") + fs.ensure_path("/a/b/c/d") + contents = fs.ls("/a/b", recursive=True) + self.assertEqual(['/a/b/c', '/a/b/c/d'], contents) + def test_ensure_path(self): fs = impl_memory.FakeFilesystem() pieces = ['a', 'b', 'c']