Fix env.subst() stack trace on var containing ListAction.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 27 Sep 2004 21:24:20 +0000 (21:24 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 27 Sep 2004 21:24:20 +0000 (21:24 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1108 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py
test/actions.py

index 4f50aecc9133c39faeefc18acec7335169a85833..7032d6914e1910c75f300d8960565e80cdbdedda 100644 (file)
@@ -76,6 +76,9 @@ RELEASE 0.97 - XXX
     through "chdir" keyword arguments to Action and Builder creation
     and calls.
 
+  - Fix handling of Action ojects (and other callables that don't match
+    our calling arguments) in construction variable expansions.
+
   From Clive Levinson:
 
   - Make ParseConfig() recognize and add -mno-cygwin to $LINKFLAGS and
index afcaf112a6069cd29283573e5e47b4f11b4d0a4a..984bb0217cdcca3812667e33d0e7f974fb02237b 100644 (file)
@@ -606,10 +606,16 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=No
                     r.append(self.conv(self.substitute(l, lvars)))
                 return string.join(r)
             elif callable(s):
-                s = s(target=self.target,
-                     source=self.source,
-                     env=self.env,
-                     for_signature=(self.mode != SUBST_CMD))
+                try:
+                    s = s(target=self.target,
+                         source=self.source,
+                         env=self.env,
+                         for_signature=(self.mode != SUBST_CMD))
+                except TypeError:
+                    # This probably indicates that it's a callable
+                    # object that doesn't match our calling arguments
+                    # (like an Action).
+                    s = str(s)
                 return self.substitute(s, lvars)
             elif s is None:
                 return ''
@@ -753,10 +759,16 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, di
                     self.substitute(a, lvars, 1)
                     self.next_word()
             elif callable(s):
-                s = s(target=self.target,
-                     source=self.source,
-                     env=self.env,
-                     for_signature=(self.mode != SUBST_CMD))
+                try:
+                    s = s(target=self.target,
+                         source=self.source,
+                         env=self.env,
+                         for_signature=(self.mode != SUBST_CMD))
+                except TypeError:
+                    # This probably indicates that it's a callable
+                    # object that doesn't match our calling arguments
+                    # (like an Action).
+                    s = str(s)
                 self.substitute(s, lvars, within_list)
             elif s is None:
                 self.this_word()
index 054d0b244f8164b0441e9af1ed23c128cf4047ec..5ac6ec00d781a9a13cbde8da2618d846a71f8d04 100644 (file)
@@ -130,6 +130,14 @@ class UtilTestCase(unittest.TestCase):
             def is_literal(self):
                 return 1
 
+        class TestCallable:
+            def __init__(self, value):
+                self.value = value
+            def __call__(self):
+                pass
+            def __str__(self):
+                return self.value
+
         def function_foo(arg):
             pass
 
@@ -194,6 +202,9 @@ class UtilTestCase(unittest.TestCase):
             'RECURSE'   : 'foo $RECURSE bar',
             'RRR'       : 'foo $SSS bar',
             'SSS'       : '$RRR',
+
+            # Test callables that don't match the calling arguments.
+            'CALLABLE'  : TestCallable('callable-1'),
         }
 
         env = DummyEnv(loc)
@@ -307,6 +318,9 @@ class UtilTestCase(unittest.TestCase):
 
             # Bug reported by Christoph Wiedemann.
             cvt('$xxx/bin'),        '/bin',
+
+            # Tests callables that don't match our calling arguments.
+            '$CALLABLE',            'callable-1',
         ]
 
         kwargs = {'target' : target, 'source' : source}
@@ -474,6 +488,14 @@ class UtilTestCase(unittest.TestCase):
                 self.attribute.attr1 = 'attr$1-' + os.path.basename(name)
                 self.attribute.attr2 = 'attr$2-' + os.path.basename(name)
 
+        class TestCallable:
+            def __init__(self, value):
+                self.value = value
+            def __call__(self):
+                pass
+            def __str__(self):
+                return self.value
+
         target = [ MyNode("./foo/bar.exe"),
                    MyNode("/bar/baz with spaces.obj"),
                    MyNode("../foo/baz.obj") ]
@@ -529,6 +551,9 @@ class UtilTestCase(unittest.TestCase):
             'RECURSE'   : 'foo $RECURSE bar',
             'RRR'       : 'foo $SSS bar',
             'SSS'       : '$RRR',
+
+            # Test callable objects that don't match our calling arguments.
+            'CALLABLE'  : TestCallable('callable-2'),
         }
 
         env = DummyEnv(loc)
@@ -660,6 +685,9 @@ class UtilTestCase(unittest.TestCase):
             '<$AAA',                [['<', 'a']],
             '>$AAA',                [['>', 'a']],
             '|$AAA',                [['|', 'a']],
+
+            # Test callables that don't match our calling arguments.
+            '$CALLABLE',            [['callable-2']],
         ]
 
         kwargs = {'target' : target, 'source' : source}
index 42b391cf5b04f423867fa8c6a222821bc75e7085..8a64a2427a0859fd5c2e511f8a5d05dfd8fb8672 100644 (file)
@@ -110,4 +110,24 @@ test.fail_test(test.read('foo.out') != "4\nfoo.in\n")
 
 test.up_to_date(arguments = '.')
 
+# Make sure we can expand actions in substitutions.
+test.write('SConstruct', """\
+def func(env, target, source):
+    pass
+env = Environment(S = Action('foo'),
+                  F = Action(func),
+                  L = Action(['arg1', 'arg2']))
+print env.subst('$S')
+print env.subst('$F')
+print env.subst('$L')
+""")
+
+test.run(arguments = '-Q .', stdout = """\
+foo
+func(env, target, source)
+arg1
+arg2
+scons: `.' is up to date.
+""")
+
 test.pass_test()