Merge "Use the node built-in 'dfs_iter' instead of recursion"
This commit is contained in:
commit
4677fdb30e
@ -21,7 +21,11 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _depth_first_reverse_iterate(node, idx=-1):
|
||||
"""Iterates connected (in reverse) nodes in tree (from starting node)."""
|
||||
"""Iterates connected (in reverse) nodes (from starting node).
|
||||
|
||||
Jumps through nodes with ``FLOW`` ``kind`` attribute (does not yield
|
||||
them back).
|
||||
"""
|
||||
# Always go left to right, since right to left is the pattern order
|
||||
# and we want to go backwards and not forwards through that ordering...
|
||||
if idx == -1:
|
||||
@ -29,15 +33,11 @@ def _depth_first_reverse_iterate(node, idx=-1):
|
||||
else:
|
||||
children_iter = reversed(node[0:idx])
|
||||
for child in children_iter:
|
||||
child_kind = child.metadata['kind']
|
||||
if child_kind == co.FLOW:
|
||||
if child.metadata['kind'] == co.FLOW:
|
||||
# Jump through these...
|
||||
#
|
||||
# TODO(harlowja): make this non-recursive and remove this
|
||||
# style of doing this when
|
||||
# https://review.openstack.org/#/c/205731/ merges...
|
||||
for atom in _depth_first_reverse_iterate(child):
|
||||
yield atom
|
||||
for child_child in child.dfs_iter(right_to_left=False):
|
||||
if child_child.metadata['kind'] in co.ATOMS:
|
||||
yield child_child.item
|
||||
else:
|
||||
yield child.item
|
||||
|
||||
|
@ -467,24 +467,38 @@ CEO
|
||||
self.assertEqual(set(['animal', 'reptile', 'mammal', 'horse',
|
||||
'primate', 'monkey', 'human']), set(things))
|
||||
|
||||
def test_dfs_itr_order(self):
|
||||
def test_dfs_itr_left_to_right(self):
|
||||
root = self._make_species()
|
||||
it = root.dfs_iter(include_self=False, right_to_left=False)
|
||||
things = list([n.item for n in it])
|
||||
self.assertEqual(['reptile', 'mammal', 'primate',
|
||||
'human', 'monkey', 'horse'], things)
|
||||
|
||||
def test_dfs_itr_no_self(self):
|
||||
root = self._make_species()
|
||||
things = list([n.item for n in root.dfs_iter(include_self=True)])
|
||||
self.assertEqual(['animal', 'mammal', 'horse', 'primate',
|
||||
'monkey', 'human', 'reptile'], things)
|
||||
things = list([n.item for n in root.dfs_iter(include_self=False)])
|
||||
self.assertEqual(['mammal', 'horse', 'primate',
|
||||
'monkey', 'human', 'reptile'], things)
|
||||
|
||||
def test_bfs_iter(self):
|
||||
def test_bfs_itr(self):
|
||||
root = self._make_species()
|
||||
things = list([n.item for n in root.bfs_iter(include_self=True)])
|
||||
self.assertEqual(['animal', 'reptile', 'mammal', 'primate',
|
||||
'horse', 'human', 'monkey'], things)
|
||||
|
||||
def test_bfs_itr_no_self(self):
|
||||
root = self._make_species()
|
||||
things = list([n.item for n in root.bfs_iter(include_self=False)])
|
||||
self.assertEqual(['reptile', 'mammal', 'primate',
|
||||
'horse', 'human', 'monkey'], things)
|
||||
|
||||
def test_bfs_itr_right_to_left(self):
|
||||
root = self._make_species()
|
||||
it = root.bfs_iter(include_self=False, right_to_left=True)
|
||||
things = list([n.item for n in it])
|
||||
self.assertEqual(['mammal', 'reptile', 'horse',
|
||||
'primate', 'monkey', 'human'], things)
|
||||
|
||||
|
||||
class OrderedSetTest(test.TestCase):
|
||||
|
||||
|
@ -36,8 +36,9 @@ class FrozenNode(Exception):
|
||||
class _DFSIter(object):
|
||||
"""Depth first iterator (non-recursive) over the child nodes."""
|
||||
|
||||
def __init__(self, root, include_self=False):
|
||||
def __init__(self, root, include_self=False, right_to_left=True):
|
||||
self.root = root
|
||||
self.right_to_left = bool(right_to_left)
|
||||
self.include_self = bool(include_self)
|
||||
|
||||
def __iter__(self):
|
||||
@ -45,20 +46,28 @@ class _DFSIter(object):
|
||||
if self.include_self:
|
||||
stack.append(self.root)
|
||||
else:
|
||||
if self.right_to_left:
|
||||
stack.extend(self.root.reverse_iter())
|
||||
else:
|
||||
# Traverse the left nodes first to the right nodes.
|
||||
stack.extend(iter(self.root))
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
# Visit the node.
|
||||
node = stack.pop()
|
||||
yield node
|
||||
# Traverse the left & right subtree.
|
||||
if self.right_to_left:
|
||||
stack.extend(node.reverse_iter())
|
||||
else:
|
||||
# Traverse the left nodes first to the right nodes.
|
||||
stack.extend(iter(node))
|
||||
|
||||
|
||||
class _BFSIter(object):
|
||||
"""Breadth first iterator (non-recursive) over the child nodes."""
|
||||
|
||||
def __init__(self, root, include_self=False):
|
||||
def __init__(self, root, include_self=False, right_to_left=False):
|
||||
self.root = root
|
||||
self.right_to_left = bool(right_to_left)
|
||||
self.include_self = bool(include_self)
|
||||
|
||||
def __iter__(self):
|
||||
@ -66,12 +75,19 @@ class _BFSIter(object):
|
||||
if self.include_self:
|
||||
q.append(self.root)
|
||||
else:
|
||||
if self.right_to_left:
|
||||
q.extend(iter(self.root))
|
||||
else:
|
||||
# Traverse the left nodes first to the right nodes.
|
||||
q.extend(self.root.reverse_iter())
|
||||
while q:
|
||||
node = q.popleft()
|
||||
# Visit the node.
|
||||
node = q.popleft()
|
||||
yield node
|
||||
# Traverse the left & right subtree.
|
||||
if self.right_to_left:
|
||||
q.extend(iter(node))
|
||||
else:
|
||||
# Traverse the left nodes first to the right nodes.
|
||||
q.extend(node.reverse_iter())
|
||||
|
||||
|
||||
@ -361,10 +377,14 @@ class Node(object):
|
||||
raise ValueError("%s is not contained in any child" % (item))
|
||||
return index_at
|
||||
|
||||
def dfs_iter(self, include_self=False):
|
||||
def dfs_iter(self, include_self=False, right_to_left=True):
|
||||
"""Depth first iteration (non-recursive) over the child nodes."""
|
||||
return _DFSIter(self, include_self=include_self)
|
||||
return _DFSIter(self,
|
||||
include_self=include_self,
|
||||
right_to_left=right_to_left)
|
||||
|
||||
def bfs_iter(self, include_self=False):
|
||||
def bfs_iter(self, include_self=False, right_to_left=False):
|
||||
"""Breadth first iteration (non-recursive) over the child nodes."""
|
||||
return _BFSIter(self, include_self=include_self)
|
||||
return _BFSIter(self,
|
||||
include_self=include_self,
|
||||
right_to_left=right_to_left)
|
||||
|
Loading…
Reference in New Issue
Block a user