From: stevenknight Date: Thu, 4 Oct 2001 18:50:26 +0000 (+0000) Subject: Add a node Walker for descending the dependency tree. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=d721c710bf2e0c45aa02b8c7980c95daa65c2c8b;p=scons.git Add a node Walker for descending the dependency tree. git-svn-id: http://scons.tigris.org/svn/scons/trunk@86 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index e77e1b6d..309229e9 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -150,9 +150,50 @@ class NodeTestCase(unittest.TestCase): node.add_dependency(['four', 'five', 'six']) kids = node.children() kids.sort() - print kids assert kids == ['five', 'four', 'one', 'six', 'three', 'two'] + def test_walker(self): + """Test walking a Node tree. + """ + + class MyNode(SCons.Node.Node): + def __init__(self, name): + SCons.Node.Node.__init__(self) + self.name = name + + n1 = MyNode("n1") + + nw = SCons.Node.Walker(n1) + assert nw.next().name == "n1" + assert nw.next() == None + + n2 = MyNode("n2") + n3 = MyNode("n3") + n1.add_source([n2, n3]) + + nw = SCons.Node.Walker(n1) + assert nw.next().name == "n2" + assert nw.next().name == "n3" + assert nw.next().name == "n1" + assert nw.next() == None + + n4 = MyNode("n4") + n5 = MyNode("n5") + n6 = MyNode("n6") + n7 = MyNode("n7") + n2.add_source([n4, n5]) + n3.add_dependency([n6, n7]) + + nw = SCons.Node.Walker(n1) + assert nw.next().name == "n4" + assert nw.next().name == "n5" + assert nw.next().name == "n2" + assert nw.next().name == "n6" + assert nw.next().name == "n7" + assert nw.next().name == "n3" + assert nw.next().name == "n1" + assert nw.next() == None + if __name__ == "__main__": diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index a0c07ca4..8e1760dc 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -84,3 +84,51 @@ class Node: def children(self): return self.sources + self.depends + + + + +class Wrapper: + def __init__(self, node): + self.node = node + self.kids = node.children() + # XXX randomize kids here, if requested + +class Walker: + """An iterator for walking a Node tree. + + This is depth-first, children are visited before the parent. + The Walker object can be initialized with any node, and + returns the next node on the descent with each next() call. + """ + def __init__(self, node): + self.current = Wrapper(node) + self.stack = [] + self.top = self.current + + def next(self): + """Return the next node for this walk of the tree. + + This function is intentionally iterative, not recursive, + to sidestep any issues of stack size limitations. + """ + if not self.current: + return None + + while 1: + if self.current.kids: + k = Wrapper(self.current.kids[0]) + self.current.kids = self.current.kids[1:] + if k.kids: + self.stack.append(self.current) + self.current = k + else: + return k.node + else: + n = self.current.node + if self.stack: + self.current = self.stack[-1] + self.stack = self.stack[0:-1] + else: + self.current = None + return n