Make FunctionAction arguments be Nodes, not strings. (Charles Crain)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 16 Mar 2002 04:38:43 +0000 (04:38 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 16 Mar 2002 04:38:43 +0000 (04:38 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@295 fdb21ef1-2011-0410-befe-b5e4ea1792b1

15 files changed:
README
SConstruct
doc/man/scons.1
etc/SConscript
src/CHANGES.txt
src/RELEASE.txt
src/engine/SCons/Action.py
src/engine/SCons/ActionTests.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
test/BuildDir.py
test/Command.py
test/actions.py
test/sconsign.py

diff --git a/README b/README
index 82ae6f68782480b82fc0a33bfd8425a0e7065147..014b22b3cee81a23fbf456507dad2a5e91697b52 100644 (file)
--- a/README
+++ b/README
@@ -55,7 +55,7 @@ system, populate the build/scons/ directory by running:
 
         $ scons build/scons
 
-If you don't have SCons version 0.04 or later already installed on your
+If you don't have SCons version 0.06 or later already installed on your
 system, you can use SCons itself to populate the build/scons/ directory
 with a little more work:
 
@@ -124,13 +124,13 @@ the "TESTING PACKAGES" section below.
 BUILDING PACKAGES
 =================
 
-We now use SCons (version 0.04 or later) to build its own packages.
+We now use SCons (version 0.06 or later) to build its own packages.
 If you already have an appropriate version of SCons installed on your
 system, you can build everything by simply running it:
 
         $ scons
 
-If you don't have SCons version 0.04 or later already installed on your
+If you don't have SCons version 0.06 or later already installed on your
 system, you can build this version of SCons with itself with a little
 more work:
 
index 3503874f9157086e26d1bade4028404d4e30341c..5303c70aab54dddd19dab4cd9be37117118a99cd 100644 (file)
@@ -201,26 +201,28 @@ def SCons_revision(target, source, env):
     This is used to copy files into a tree that gets packaged up
     into the source file package.
     """
+    t = str(target[0])
+    s = str(source[0])
     # Note:  We don't use $VERSION from the environment so that
     # this routine will change when the version number changes
     # and things will get rebuilt properly.
     global version
-    print "SCons_revision() < %s > %s" % (source[0], target)
-    inf = open(source[0], 'rb')
-    outf = open(target, 'wb')
+    print "SCons_revision() < %s > %s" % (st)
+    inf = open(s, 'rb')
+    outf = open(t, 'wb')
     for line in inf.readlines():
         # Note:  We construct the __*__ substitution strings here
         # so that they don't get replaced when this file gets
         # copied into the tree for packaging.
         line = string.replace(line, '_' + '_DATE__', env['DATE'])
         line = string.replace(line, '_' + '_DEVELOPER__', env['DEVELOPER'])
-        line = string.replace(line, '_' + '_FILE__', source[0])
+        line = string.replace(line, '_' + '_FILE__', s)
         line = string.replace(line, '_' + '_REVISION__', env['REVISION'])
         line = string.replace(line, '_' + '_VERSION__', version)
         outf.write(line)
     inf.close()
     outf.close()
-    os.chmod(target, os.stat(source[0])[0])
+    os.chmod(t, os.stat(s)[0])
 
 revbuilder = Builder(name = 'SCons_revision', action = SCons_revision)
 
@@ -488,7 +490,7 @@ for p in [ scons ]:
     def copy(target, source, **kw):
         global src_files
        src_files.sort()
-        f = open(target, 'wb')
+        f = open(str(target[0]), 'wb')
         for file in src_files:
             f.write(file + "\n")
         f.close()
index 6e4b72b4d23a44dc5ccbfc15cb8b2d6b624df6b6..5d8a0a5ae3aa2d0b5bb5116c488bb9c216ccaf7e 100644 (file)
@@ -1285,9 +1285,9 @@ If the argument is a Python function,
 a function Action is returned.
 The Python function takes three keyword arguments,
 .B target
-(the name of the target file),
+(a Node object representing the target file),
 .B source
-(the name of the source file)
+(a Node object representing the source file)
 and
 .BR env
 (the construction environment
@@ -1296,8 +1296,15 @@ The
 .B target
 and
 .B source
-arguments may be lists of strings if there is
+arguments may be lists of Node objects if there is
 more than one target file or source file.
+The actual target and source file name(s) may
+be retrieved from their Node objects
+via the built-in Python str() function:
+.ES
+target_file_name = str(target)
+source_file_names = map(lambda x: str(x), source)
+.EE
 .IP
 The function should return
 .B 0
index a55fe676e17f678ab10221ea79441104a358ed86..96a464d1d982fa925643129fcdee75988cb40904 100644 (file)
@@ -36,8 +36,10 @@ files = [
 ]
 
 def copy(target, source, env):
-    print "copy() < %s > %s" % (source[0], target)
-    open(target, 'wb').write(open(source[0], 'rb').read())
+    t = str(target[0])
+    s = str(source[0])
+    print "copy() < %s > %s" % (s, t)
+    open(t, 'wb').write(open(s, 'rb').read())
 
 for file in files:
     # Guarantee that real copies of these files always exist in
index 46177bd6916ad5a2ef96dc37be80affbd45c2698..70ba009341f06f788c10f9a16910d76770deec7d 100644 (file)
 
 RELEASE 0.06 - 
 
+  From Charles Crain:
+
+  - Fix command generators to expand construction variables.
+
+  - Make FunctionAction arguments be Nodes, not strings.
+
   From Stephen Kennedy:
 
   - Performance:  Use a dictionary, not a list, for a Node's parents.
index 60aca866308941e3240c1a62b32a7004e9811ff0..733a2efcdc28ce7e340dc073f3e542743218bd14 100644 (file)
@@ -20,11 +20,25 @@ more effectively, please sign up for the scons-users mailing list at:
 
 
 
-RELEASE 0.05 - Thu, 21 Feb 2002 16:50:03 -0600
+RELEASE 0.06 - 
 
-  This is the fifth alpha release of SCons.  Please consult the
+  This is the sixth alpha release of SCons.  Please consult the
   CHANGES.txt file for a list of specific changes since last release.
 
+  Please note the following important changes since the previous
+  release:
+
+    - Python functions as Builder actions now take Node objects, not
+      strings, as arguments.  The string representation of a Node
+      object is the file name, so you should change your function
+      actions to use the str() built-in function to fetch the file
+      name:
+
+        def build_it(target = None, source = None, env = None):
+            print "Building %s from %s" % (str(target), str(source))
+           open(str(target), 'w').write(open(str(source), 'r').read())
+            return 0
+
   Owing to an extensive test suite, the SCons team believes that this
   release is of sufficient quality that you can use it for real work,
   despite the "alpha" label.
index 26595d664f1a3fc2de129bd1712bf9f00e924ea9..503fe15c818ecaf965c43997daadc69cff46684a 100644 (file)
@@ -383,13 +383,12 @@ class FunctionAction(ActionBase):
         # if print_actions:
         # XXX:  WHAT SHOULD WE PRINT HERE?
         if execute_actions:
-            if kw.has_key('target'):
-                if SCons.Util.is_List(kw['target']):
-                    kw['target'] = map(str, kw['target'])
-                else:
-                    kw['target'] = str(kw['target'])
-            if kw.has_key('source'):
-                kw['source'] = map(str, kw['source'])
+            if kw.has_key('target') and not \
+               SCons.Util.is_List(kw['target']):
+                kw['target'] = [ kw['target'] ]
+            if kw.has_key('source') and not \
+               SCons.Util.is_List(kw['source']):
+                kw['source'] = [ kw['source'] ]
             return apply(self.function, (), kw)
 
     def get_contents(self, **kw):
index 592fa82f8df52f33654001e1169da1047a94dee0..8b417a8f8d464c9039a448d2b0ee9adb24aa63e9 100644 (file)
@@ -203,12 +203,16 @@ class FunctionActionTestCase(unittest.TestCase):
         """Test executing a function Action
         """
         self.inc = 0
-        def f(s):
+        def f(s, target, source):
             s.inc = s.inc + 1
+            s.target = target
+            s.source=source
             return 0
         a = SCons.Action.FunctionAction(f)
-        a.execute(s = self)
+        a.execute(s = self, target=1, source=2)
         assert self.inc == 1, self.inc
+        assert self.source == [2], self.source
+        assert self.target == [1], self.target
 
     def test_get_contents(self):
         """Test fetching the contents of a function Action
index fc530abbb5b7b800ea76a04ff135fdee5676cf54..ab633179b453de6118141a61bfadf3d632813b05 100644 (file)
@@ -513,12 +513,10 @@ class BuilderTestCase(unittest.TestCase):
         def function2(tlist = [outfile, outfile2], **kw):
             global count
             count = count + 1
-            if not type(kw['target']) is type([]):
-                kw['target'] = [ kw['target'] ]
             for t in kw['target']:
-                open(t, 'w').write("function2\n")
+                open(str(t), 'w').write("function2\n")
             for t in tlist:
-                if not t in kw['target']:
+                if not t in map(str, kw['target']):
                     open(t, 'w').write("function2\n")
             return 1
 
@@ -543,12 +541,10 @@ class BuilderTestCase(unittest.TestCase):
         def function3(tlist = [sub1_out, sub2_out], **kw):
             global count
             count = count + 1
-            if not type(kw['target']) is type([]):
-                kw['target'] = [ kw['target'] ]
             for t in kw['target']:
-                open(t, 'w').write("function3\n")
+                open(str(t), 'w').write("function3\n")
             for t in tlist:
-                if not t in kw['target']:
+                if not t in map(str, kw['target']):
                     open(t, 'w').write("function3\n")
             return 1
 
index 49249f3ef9a48bf635b156c735ed1f638290e05a..d90e0295252eb3cbb82a168ff42be2ab8bd30a9c 100644 (file)
@@ -45,22 +45,22 @@ import shutil
 
 def installFunc(env, target, source):
     try:
-        os.unlink(target)
+        map(lambda t: os.unlink(str(t)), target)
     except OSError:
         pass
     
     try:
-        SCons.Node.FS.file_link(source[0], target)
+        SCons.Node.FS.file_link(str(source[0]), str(target[0]))
         print 'Install file: "%s" as "%s"' % \
-              (source[0], target)
+              (source[0], target[0])
         return 0
     except IOError, e:
         sys.stderr.write('Unable to install "%s" as "%s"\n%s\n' % \
-                         (source[0], target, str(e)))
+                         (source[0], target[0], str(e)))
         return -1
     except OSError, e:
         sys.stderr.write('Unable to install "%s" as "%s"\n%s\n' % \
-                         (source[0], target, str(e)))
+                         (source[0], target[0], str(e)))
         return -1
 
 InstallBuilder = SCons.Builder.Builder(name='Install',
index 40945a13107e4914b008c88ad693fd39ad1f59df..4917c83fa3d0d38253f4a0db59539c1833e7ddb7 100644 (file)
@@ -295,8 +295,8 @@ class EnvironmentTestCase(unittest.TestCase):
         assert 'foo2.in' in map(lambda x: x.path, t.sources)
 
         def testFunc(env, target, source):
-            assert target == 'foo.out'
-            assert 'foo1.in' in source and 'foo2.in' in source, source
+            assert str(target[0]) == 'foo.out'
+            assert 'foo1.in' in map(str, source) and 'foo2.in' in map(str, source), map(str, source)
             return 0
         t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
                         action=testFunc)
index 63b357e7e31664de53d932e7e1eb85407e1d12fe..a71d4ddab636f642d42e2109614db70657f98f95 100644 (file)
@@ -68,8 +68,8 @@ import os.path
 def buildIt(target, source, env):
     if not os.path.exists('build'):
         os.mkdir('build')
-    f1=open(source[0], 'r')
-    f2=open(target, 'w')
+    f1=open(str(source[0]), 'r')
+    f2=open(str(target[0]), 'w')
     f2.write(f1.read())
     f2.close()
     f1.close()
index ddf78ce9ad91ddb197b65c7b739b6229dd3d97d8..1f4a49091b2633baa6fd4e4dd0401f4f8086be6f 100644 (file)
@@ -41,8 +41,8 @@ file.close()
 
 test.write('SConstruct', """
 def buildIt(env, target, source):
-    contents = open(source[0], 'rb').read()
-    file = open(target, 'wb')
+    contents = open(str(source[0]), 'rb').read()
+    file = open(str(target[0]), 'wb')
     file.write(contents)
     file.close()
     return 0
index c6198ddc61551ea12a7879b0baa059a2dea1ba12..65fa01a950398f5de2f4f064e330b578881644cd 100644 (file)
@@ -70,7 +70,8 @@ test.write('SConstruct', """
 import os
 import string
 def func(env, target, source):
-    cmd = r'%s build.py %%s 3 %%s' %% (target, string.join(source, ' '))
+    cmd = r'%s build.py %%s 3 %%s' %% (string.join(map(str, target)),
+                                       string.join(map(str, source)))
     print cmd
     return os.system(cmd)
 B = Builder(name = 'B', action = func)
@@ -96,7 +97,8 @@ class bld:
        print cmd
         return os.system(cmd)
     def get_contents(self, env, target, source):
-        return self.cmd %% (target, string.join(source, ' '))
+        return self.cmd %% (string.join(map(str, target)),
+                            string.join(map(str, source)))
 B = Builder(name = 'B', action = bld())
 env = Environment(BUILDERS = [B])
 env.B(target = 'foo.out', source = 'foo.in')
index 396c3994c6c32bba976ba29ea2cfd267db96fe9d..a7c6971c39f632c9e76e0d1e85740bf97df9c2b8 100644 (file)
@@ -39,8 +39,8 @@ def build1(target, source, env):
 def build2(target, source, env):
     import os
     import os.path
-    open(str(target), 'wb').write(open(str(source[0]), 'rb').read())
-    dir, file = os.path.split(target)
+    open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+    dir, file = os.path.split(str(target[0]))
     os.chmod(dir, 0555)
     return None