Enhance Builders to take any type of node as input.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 24 Sep 2001 14:16:04 +0000 (14:16 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 24 Sep 2001 14:16:04 +0000 (14:16 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@68 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Node/__init__.py
src/engine/SCons/Sig/SigTests.py
src/engine/SCons/Sig/__init__.py
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py
test/Depends.py

index 0d1d27451165b4be801e2ba50778de827e63bd37..72b01cf2434aa349787170ab449e7750b2742d6a 100644 (file)
@@ -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.
index ab7e12274c513f73cdcbbaf5548141b9eb122ca7..0ea81f0bdbed84c095487b059866eaefc53f0315 100644 (file)
@@ -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
 
index ee06089ac35e1b3782a217b586f466c6aaa4f1ed..259576619c5aeb101f7244a559e7bd7cd1f5dc6d 100644 (file)
@@ -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()
 
index 87c6ed870bac124afc6f4c71f8e5adef27bf669d..94ec5b0bec39966c99bbd287368c4973433ba90e 100644 (file)
@@ -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
index ce8e225b04dd79113aaab2221ee8b5740d2e0a71..8609c57e2302b9e09351b1fa59bfecc3dd2edb26 100644 (file)
@@ -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
index 7fae807d5d38a84c3d170dcf8733cddda183aeb3..3a8e0b3ee9703b286b02955b5756112ffed3a652 100644 (file)
@@ -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
         
index ea1820e35f5ce26d330527d7ca384a8e1717f94a..a2c36b8b70af88c631a75e946356c0451157fca7 100644 (file)
@@ -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
index 0167260e24338e853ee080a1fb1cddea3aec3986..0828db33db46e3477f75fb59d9cce4ae5580927b 100644 (file)
@@ -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
index 0e13047de8c29ce2360f88b6577fad8eaa37e15d..cb19c1534a9542699a0cb7fff5ba849c04ca2bfd 100644 (file)
@@ -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_')
index 5c6c4f163319bd64cef2ab6d9e0c3e70442b6eab..ccbcf26433f4ea9792c95e27f3a91aa770a71c50 100644 (file)
@@ -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()