From: stevenknight Date: Mon, 24 Sep 2001 14:16:04 +0000 (+0000) Subject: Enhance Builders to take any type of node as input. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=e0906e951d08660ae07e1994ca4e16b325884e65;p=scons.git Enhance Builders to take any type of node as input. git-svn-id: http://scons.tigris.org/svn/scons/trunk@68 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 0d1d2745..72b01cf2 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -10,6 +10,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import SCons.Node.FS +import SCons.Util import string import types @@ -39,25 +40,17 @@ class Builder: return cmp(self.__dict__, other.__dict__) def __call__(self, env, target = None, source = None): - node = self.node_factory(target) - node.builder_set(self) - node.env_set(self) - - # XXX REACHING INTO ANOTHER OBJECT (this is only temporary): - assert type(source) is type("") - node.sources = source - node.derived = 1 - sources = string.split(source, " ") - sources = filter(lambda x: x, sources) - source_nodes = [] - for source in sources: - source_node = self.node_factory(source) - source_node.derived = 0 - source_node.source_nodes = [] - source_nodes.append(source_node) - node.source_nodes = source_nodes - - return node + tlist = SCons.Util.scons_str2nodes(target) + slist = SCons.Util.scons_str2nodes(source) + for t in tlist: + t.builder_set(self) + t.env_set(env) + t.derived = 1 + t.add_source(slist) + + if len(tlist) == 1: + tlist = tlist[0] + return tlist def execute(self, **kw): """Execute a builder's action to create an output object. diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index ab7e1227..0ea81f0b 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -29,6 +29,32 @@ outfile = test.workpath('outfile') class BuilderTestCase(unittest.TestCase): + def test__call__(self): + """Test calling a builder to establish source dependencies + """ + class Environment: + pass + env = Environment() + class Node: + def __init__(self, name): + self.name = name + self.sources = [] + self.derived = 0 + def builder_set(self, builder): + self.builder = builder + def env_set(self, env): + self.env = env + def add_source(self, source): + self.sources.extend(source) + builder = SCons.Builder.Builder(action = "foo") + n1 = Node("n1"); + n2 = Node("n2"); + builder(env, target = n1, source = n2) + assert n1.env == env + assert n1.builder == builder + assert n1.sources == [n2] + assert n1.derived == 1 + def test_action(self): """Test Builder creation diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index ee06089a..25957661 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -214,6 +214,9 @@ class Dir(Node): self.abspath = self.path = name self.entries['..'] = None + def __str__(self): + return self.path + def up(self): return self.entries['..'] @@ -258,6 +261,9 @@ class File(Node): self.path = os.path.join(directory.path, name) self.parent = directory + def __str__(self): + return self.path + def root(self): return self.parent.root() diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 87c6ed87..94ec5b0b 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -41,6 +41,8 @@ class FSTestCase(unittest.TestCase): dir = fileSys.Dir(lpath) assert dir.path == path, "Dir.path %s != expected path %s" % \ (dir.path, path) + assert str(dir) == path, "str(dir) %s != expected path %s" % \ + (str(dir), path) assert dir.abspath == abspath, "Dir.abspath %s != expected abs. path %s" % \ (dir.abspath, path) assert dir.up().path == up_path, "Dir.up().path %s != expected parent path %s" % \ @@ -62,12 +64,14 @@ class FSTestCase(unittest.TestCase): f1 = fs.File('f1', directory = d1) assert f1.path == 'd1/f1', "f1.path %s != d1/f1" % f1.path + assert str(f1) == 'd1/f1', "str(f1) %s != d1/f1" % str(f1) try: f2 = fs.File('f1/f2', directory = d1) except TypeError, x: node = x.args[0] assert node.path == 'd1/f1', "node.path %s != d1/f1" % node.path + assert str(node) == 'd1/f1', "str(node) %s != d1/f1" % str(node) assert node.__class__.__name__ == 'File' except: raise @@ -77,6 +81,7 @@ class FSTestCase(unittest.TestCase): except TypeError, x: node = x.args[0] assert node.path == 'd1/f1', "node.path %s != d1/f1" % node.path + assert str(node) == 'd1/f1', "str(node) %s != d1/f1" % str(node) assert node.__class__.__name__ == 'File' except: raise diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index ce8e225b..8609c57e 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -8,18 +8,24 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import string + + + class Node: """The base Node class, for entities that we know how to build, or use to build other Nodes. """ def __init__(self): - self.depends = [] self.sources = [] + self.depends = [] + self.derived = 0 self.env = None def build(self): - self.builder.execute(target = self.path, source = self.sources) + sources_str = string.join(map(lambda x: str(x), self.sources)) + self.builder.execute(target = str(self), source = sources_str) def builder_set(self, builder): self.builder = builder diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index 7fae807d..3a8e0b3e 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -27,6 +27,7 @@ class DummyNode: self.file = file self.path = file.path self.derived = file.derived + self.depends = [] def get_contents(self): # a file that doesn't exist has no contents: @@ -73,17 +74,17 @@ def create_files(test): def create_nodes(files): nodes = map(DummyNode, files) - nodes[0].source_nodes = [] - nodes[1].source_nodes = [nodes[0]] - nodes[2].source_nodes = [nodes[3]] - nodes[3].source_nodes = [] - nodes[4].source_nodes = [nodes[5]] - nodes[5].source_nodes = [nodes[6]] - nodes[6].source_nodes = [nodes[5]] - nodes[7].source_nodes = [nodes[2], nodes[4]] - nodes[8].source_nodes = [] - nodes[9].source_nodes = [nodes[8]] - nodes[10].source_nodes = [nodes[9]] + nodes[0].sources = [] + nodes[1].sources = [nodes[0]] + nodes[2].sources = [nodes[3]] + nodes[3].sources = [] + nodes[4].sources = [nodes[5]] + nodes[5].sources = [nodes[6]] + nodes[6].sources = [nodes[5]] + nodes[7].sources = [nodes[2], nodes[4]] + nodes[8].sources = [] + nodes[9].sources = [nodes[8]] + nodes[10].sources = [nodes[9]] return nodes diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index ea1820e3..a2c36b8b 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -91,7 +91,7 @@ class Calculator: signatures - the dictionary that the signatures will be gathered into. """ - for source_node in node.source_nodes: + for source_node in node.sources + node.depends: if not signatures.has_key(source_node): signature = self.signature(source_node) signatures[source_node] = signature diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 0167260e..0828db33 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -32,9 +32,15 @@ def scons_str2nodes(arg, fs=SCons.Node.FS.default_fs): for v in narg: if type(v) is types.StringType: nodes.append(fs.File(v)) - elif issubclass(v.__class__, SCons.Node.Node): - nodes.append(v) + # Do we enforce the following restriction? Maybe, but it + # also restricts what we can do for allowing people to + # use the engine with alternate Node implementations... + # Perhaps this should be split in two, with the SCons.Node + # logic in a wrapper somewhere under SCons.Node, and the + # string-parsing logic here...? + #elif not issubclass(v.__class__, SCons.Node.Node): + # raise TypeError else: - raise TypeError + nodes.append(v) return nodes diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 0e13047d..cb19c153 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -2,6 +2,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys import unittest +import SCons.Node import SCons.Node.FS from SCons.Util import scons_str2nodes @@ -38,6 +39,14 @@ class UtilTestCase(unittest.TestCase): assert nodes[0].path == "Util.py" assert nodes[1].path == "UtilTests.py" + class SConsNode(SCons.Node.Node): + pass + node = scons_str2nodes(SConsNode()) + + class OtherNode: + pass + node = scons_str2nodes(OtherNode()) + if __name__ == "__main__": suite = unittest.makeSuite(UtilTestCase, 'test_') diff --git a/test/Depends.py b/test/Depends.py index 5c6c4f16..ccbcf264 100644 --- a/test/Depends.py +++ b/test/Depends.py @@ -6,8 +6,6 @@ import TestSCons test = TestSCons.TestSCons() -test.pass_test() #XXX Short-circuit until this is implemented. - test.subdir('subdir') test.write('build.py', r""" @@ -24,16 +22,16 @@ Foo = Builder(name = "Foo", Bar = Builder(name = "Bar", action = "python build.py %(target)s %(source)s subdir/bar.dep") env = Environment(BUILDERS = [Foo, Bar]) -env.Depends(target = ['f1.out', 'f2.out'], source = 'subdir/foo.dep') -env.Depends(target = 'f3.out', source = 'subdir/bar.dep') +env.Depends(target = ['f1.out', 'f2.out'], dependency = 'subdir/foo.dep') +env.Depends(target = 'f3.out', dependency = 'subdir/bar.dep') env.Foo(target = 'f1.out', source = 'f1.in') env.Foo(target = 'f2.out', source = 'f2.in') env.Bar(target = 'f3.out', source = 'f3.in') -SConscript('subdir/SConscript') +Conscript('subdir/SConscript') """) test.write(['subdir', 'SConscript'], """ -env.Depends(target = 'f4.out', source = 'bar.dep') +env.Depends(target = 'f4.out', dependency = 'bar.dep') env.Foo(target = 'f4.out', source = 'f4.in') """) @@ -41,40 +39,45 @@ test.write('f1.in', "f1.in\n") test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") + test.write(['subdir', 'f4.in'], "subdir/f4.in\n") test.write(['subdir', 'foo.dep'], "subdir/foo.dep 1\n") test.write(['subdir', 'bar.dep'], "subdir/bar.dep 1\n") -test.run(arguments = '.') +#XXXtest.run(arguments = '.') +test.run(arguments = 'f1.out f2.out f3.out subdir/f4.out') test.fail_test(test.read('f1.out') != "f1.in\nsubdir/foo.dep 1\n") test.fail_test(test.read('f2.out') != "f2.in\nsubdir/foo.dep 1\n") test.fail_test(test.read('f3.out') != "f3.in\nsubdir/bar.dep 1\n") -test.fail_test(test.read('subdir', 'f4.out') != - "subdir/f4.in\nsubdir/bar.dep 1\n") +#XXXtest.fail_test(test.read(['subdir', 'f4.out']) != +#XXX "subdir/f4.in\nsubdir/bar.dep 1\n") test.write(['subdir', 'foo.dep'], "subdir/foo.dep 2\n") test.write(['subdir', 'bar.dep'], "subdir/bar.dep 2\n") -test.run(arguments = '.') +#XXXtest.run(arguments = '.') +test.run(arguments = 'f1.out f2.out f3.out subdir/f4.out') test.fail_test(test.read('f1.out') != "f1.in\nsubdir/foo.dep 2\n") test.fail_test(test.read('f2.out') != "f2.in\nsubdir/foo.dep 2\n") test.fail_test(test.read('f3.out') != "f3.in\nsubdir/bar.dep 2\n") -test.fail_test(test.read('subdir', 'f4.out') != - "subdir/f4.in\nsubdir/bar.dep 2\n") +#XXXtest.fail_test(test.read(['subdir', 'f4.out']) != +#XXX "subdir/f4.in\nsubdir/bar.dep 2\n") test.write(['subdir', 'bar.dep'], "subdir/bar.dep 3\n") -test.run(arguments = '.') +#XXXtest.run(arguments = '.') +test.run(arguments = 'f1.out f2.out f3.out subdir/f4.out') test.fail_test(test.read('f1.out') != "f1.in\nsubdir/foo.dep 2\n") test.fail_test(test.read('f2.out') != "f2.in\nsubdir/foo.dep 2\n") -test.fail_test(test.read('f3.out') != "f3.in\nsubdir/bar.dep 2\n") -test.fail_test(test.read('subdir', 'f4.out') != - "subdir/f4.in\nsubdir/bar.dep 3\n") +test.fail_test(test.read('f3.out') != "f3.in\nsubdir/bar.dep 3\n") +#XXXtest.fail_test(test.read(['subdir', 'f4.out']) != +#XXX "subdir/f4.in\nsubdir/bar.dep 3\n") test.pass_test()