summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-10-24 14:18:02 (GMT)
committerSteven Knight <knight@baldmt.com>2001-10-24 14:18:02 (GMT)
commit6a98a941a75eab2e4c22fa3e19cb973046f613b6 (patch)
treefbedd2a2caa8c7d0e4a1e4b774adc6e1b1ed6d8e /src/engine/SCons/Node
parent908b74a3a3ecba5eccc6fd1f844505050d9dad2f (diff)
downloadSCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.zip
SCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.tar.gz
SCons-6a98a941a75eab2e4c22fa3e19cb973046f613b6.tar.bz2
Add -k support and more
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/FSTests.py6
-rw-r--r--src/engine/SCons/Node/NodeTests.py127
-rw-r--r--src/engine/SCons/Node/__init__.py60
3 files changed, 154 insertions, 39 deletions
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 6f2a5a7..044f83f 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -160,15 +160,17 @@ class FSTestCase(unittest.TestCase):
built_it = None
assert not built_it
- d1.add_source(["d"]) # XXX FAKE SUBCLASS ATTRIBUTE
+ d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
d1.builder_set(Builder())
d1.env_set(Environment())
d1.build()
assert built_it
+ assert d1.get_parents() == []
+
built_it = None
assert not built_it
- f1.add_source(["f"]) # XXX FAKE SUBCLASS ATTRIBUTE
+ f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
f1.builder_set(Builder())
f1.env_set(Environment())
f1.build()
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 02b34b5..b8015c2 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -128,42 +128,96 @@ class NodeTestCase(unittest.TestCase):
"""
node = SCons.Node.Node()
assert node.depends == []
- try:
- node.add_dependency('zero')
+
+ zero = SCons.Node.Node()
+ try:
+ node.add_dependency(zero)
except TypeError:
pass
- node.add_dependency(['one'])
- assert node.depends == ['one']
- node.add_dependency(['two', 'three'])
- assert node.depends == ['one', 'two', 'three']
- node.add_dependency(['three', 'four', 'one'])
- assert node.depends == ['one', 'two', 'three', 'four']
+ else:
+ assert 0
+
+ one = SCons.Node.Node()
+ two = SCons.Node.Node()
+ three = SCons.Node.Node()
+ four = SCons.Node.Node()
+
+ node.add_dependency([one])
+ assert node.depends == [one]
+ node.add_dependency([two, three])
+ assert node.depends == [one, two, three]
+ node.add_dependency([three, four, one])
+ assert node.depends == [one, two, three, four]
+
+ assert zero.get_parents() == []
+ assert one.get_parents() == [node]
+ assert two.get_parents() == [node]
+ assert three.get_parents() == [node]
+ assert four.get_parents() == [node]
+
def test_add_source(self):
"""Test adding sources to a Node's list.
"""
node = SCons.Node.Node()
assert node.sources == []
+
+ zero = SCons.Node.Node()
try:
- node.add_source('zero')
+ node.add_source(zero)
except TypeError:
pass
- node.add_source(['one'])
- assert node.sources == ['one']
- node.add_source(['two', 'three'])
- assert node.sources == ['one', 'two', 'three']
- node.add_source(['three', 'four', 'one'])
- assert node.sources == ['one', 'two', 'three', 'four']
+ else:
+ assert 0
+
+ one = SCons.Node.Node()
+ two = SCons.Node.Node()
+ three = SCons.Node.Node()
+ four = SCons.Node.Node()
+
+ node.add_source([one])
+ assert node.sources == [one]
+ node.add_source([two, three])
+ assert node.sources == [one, two, three]
+ node.add_source([three, four, one])
+ assert node.sources == [one, two, three, four]
+
+ assert zero.get_parents() == []
+ assert one.get_parents() == [node]
+ assert two.get_parents() == [node]
+ assert three.get_parents() == [node]
+ assert four.get_parents() == [node]
def test_children(self):
"""Test fetching the "children" of a Node.
"""
node = SCons.Node.Node()
- node.add_source(['one', 'two', 'three'])
- node.add_dependency(['four', 'five', 'six'])
- kids = node.children()
- kids.sort()
- assert kids == ['five', 'four', 'one', 'six', 'three', 'two']
+ one = SCons.Node.Node()
+ two = SCons.Node.Node()
+ three = SCons.Node.Node()
+ four = SCons.Node.Node()
+ five = SCons.Node.Node()
+ six = SCons.Node.Node()
+
+ node.add_source([one, two, three])
+ node.add_dependency([four, five, six])
+ kids = node.children()
+ assert len(kids) == 6
+ assert one in kids
+ assert two in kids
+ assert three in kids
+ assert four in kids
+ assert five in kids
+ assert six in kids
+
+ def test_add_parent(self):
+ """Test adding parents to a Node."""
+ node = SCons.Node.Node()
+ parent = SCons.Node.Node()
+ node._add_parent(parent)
+ assert node.get_parents() == [parent]
+ node._add_parent(parent)
+ assert node.get_parents() == [parent]
def test_state(self):
"""Test setting and getting the state of a node
@@ -217,6 +271,39 @@ class NodeTestCase(unittest.TestCase):
assert nw.next().name == "n1"
assert nw.next() == None
+ def test_children_are_executed(self):
+ n1 = SCons.Node.Node()
+ n2 = SCons.Node.Node()
+ n3 = SCons.Node.Node()
+ n4 = SCons.Node.Node()
+
+ n4.add_source([n3])
+ n3.add_source([n1, n2])
+
+ assert not n4.children_are_executed()
+ assert not n3.children_are_executed()
+ assert n2.children_are_executed()
+ assert n1.children_are_executed()
+
+ n1.set_state(SCons.Node.executed)
+ assert not n4.children_are_executed()
+ assert not n3.children_are_executed()
+ assert n2.children_are_executed()
+ assert n1.children_are_executed()
+
+ n2.set_state(SCons.Node.executed)
+ assert not n4.children_are_executed()
+ assert n3.children_are_executed()
+ assert n2.children_are_executed()
+ assert n1.children_are_executed()
+
+ n3.set_state(SCons.Node.executed)
+ assert n4.children_are_executed()
+ assert n3.children_are_executed()
+ assert n2.children_are_executed()
+ assert n1.children_are_executed()
+
+
if __name__ == "__main__":
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 265071e..b7bdecf 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -41,7 +41,7 @@ executing = 1
executed = 2
up_to_date = 3
failed = 4
-
+pending = 5
class Node:
"""The base Node class, for entities that we know how to
@@ -51,6 +51,7 @@ class Node:
def __init__(self):
self.sources = []
self.depends = []
+ self.parents = []
self.builder = None
self.env = None
self.state = None
@@ -82,24 +83,35 @@ class Node:
return self.signature
def add_dependency(self, depend):
- """Adds dependencies. The depends argument must be a list."""
- if type(depend) is not type([]):
- raise TypeError("depend must be a list")
- depend = filter(lambda x, d=self.depends: x not in d, depend)
- if len(depend):
- self.depends.extend(depend)
+ """Adds dependencies. The depend argument must be a list."""
+ self._add_child(self.depends, depend)
def add_source(self, source):
"""Adds sources. The source argument must be a list."""
- if type(source) is not type([]):
- raise TypeError("source must be a list")
- source = filter(lambda x, s=self.sources: x not in s, source)
- if len(source):
- self.sources.extend(source)
+ self._add_child(self.sources, source)
+
+ def _add_child(self, collection, child):
+ """Adds 'child' to 'collection'. The 'child' argument must be a list"""
+ if type(child) is not type([]):
+ raise TypeError("child must be a list")
+ child = filter(lambda x, s=collection: x not in s, child)
+ if child:
+ collection.extend(child)
+
+ for c in child:
+ c._add_parent(self)
+
+ def _add_parent(self, parent):
+ """Adds 'parent' to the list of parents of this node"""
+
+ if parent not in self.parents: self.parents.append(parent)
def children(self):
return self.sources + self.depends
+ def get_parents(self):
+ return self.parents
+
def set_state(self, state):
self.state = state
@@ -109,10 +121,20 @@ class Node:
def current(self):
return None
+ def children_are_executed(self):
+ return reduce(lambda x,y: ((y.get_state() == executed
+ or y.get_state() == up_to_date)
+ and x),
+ self.children(),
+ 1)
+
+def get_children(node): return node.children()
+
class Wrapper:
- def __init__(self, node):
+ def __init__(self, node, kids_func):
self.node = node
- self.kids = copy.copy(node.children())
+ self.kids = copy.copy(kids_func(node))
+
# XXX randomize kids here, if requested
class Walker:
@@ -121,9 +143,12 @@ class Walker:
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.
+ 'kids_func' is an optional function that will be called to
+ get the children of a node instead of calling 'children'.
"""
- def __init__(self, node):
- self.stack = [Wrapper(node)]
+ def __init__(self, node, kids_func=get_children):
+ self.kids_func = kids_func
+ self.stack = [Wrapper(node, self.kids_func)]
def next(self):
"""Return the next node for this walk of the tree.
@@ -134,7 +159,8 @@ class Walker:
while self.stack:
if self.stack[-1].kids:
- self.stack.append(Wrapper(self.stack[-1].kids.pop(0)))
+ self.stack.append(Wrapper(self.stack[-1].kids.pop(0),
+ self.kids_func))
else:
return self.stack.pop().node