Clean up how the Environment dictionary is passed to function Actions. (Charles Crain)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 5 Apr 2002 17:19:03 +0000 (17:19 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 5 Apr 2002 17:19:03 +0000 (17:19 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@322 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Action.py
src/engine/SCons/ActionTests.py

index da541f33b7d6e1ca853c7b0b39a97a17de9eae15..e2a46e22a5174da14f3f20c8450870bd904614d2 100644 (file)
 
 RELEASE 0.07 - 
 
+  From Charles Crain:
+
+  - Internal cleanup of environment passing to function Actions.
+
   From Steven Knight:
 
   - Fix so that -c -n does *not* remove the targets!
index 9b65e389e49241ff830a8187cfc966b8589d5182..3ed3d73521c8822e1e08f51b4369e3d6a8bd4002 100644 (file)
@@ -29,11 +29,13 @@ XXX
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import copy
 import os
 import os.path
 import re
 import string
 import sys
+import UserDict
 
 import SCons.Util
 
@@ -259,6 +261,27 @@ class ActionBase:
 _rm = re.compile(r'\$[()]')
 _remove = re.compile(r'\$\(([^\$]|\$[^\(])*?\$\)')
 
+class EnvDictProxy(UserDict.UserDict):
+    """This is a dictionary-like class that contains the
+    Environment dictionary we pass to FunctionActions
+    and CommandGeneratorActions.
+
+    In addition to providing
+    normal dictionary-like access to the variables in the
+    Environment, it also exposes the functions subst()
+    and subst_list(), allowing users to easily do variable
+    interpolation when writing their FunctionActions
+    and CommandGeneratorActions."""
+
+    def __init__(self, env):
+        UserDict.UserDict.__init__(self, env)
+
+    def subst(self, string):
+        return SCons.Util.scons_subst(string, self.data, {}, _rm)
+
+    def subst_list(self, string):
+        return SCons.Util.scons_subst_list(string, self.data, {}, _rm)
+
 class CommandAction(ActionBase):
     """Class for command-execution actions."""
     def __init__(self, string):
@@ -325,7 +348,14 @@ class CommandGeneratorAction(ActionBase):
         if kw.has_key("target") and not SCons.Util.is_List(kw["target"]):
             kw["target"] = [kw["target"]]
 
-        gen_list = apply(self.generator, (), kw)
+        # Wrap the environment dictionary in an EnvDictProxy
+        # object to make variable interpolation easier for the
+        # client.
+        args = copy.copy(kw)
+        if args.has_key("env") and not isinstance(args["env"], EnvDictProxy):
+            args["env"] = EnvDictProxy(args["env"])
+
+        gen_list = apply(self.generator, (), args)
         gen_list = map(lambda x: map(str, x), gen_list)
 
         # Do environment variable substitution on returned command list
@@ -386,6 +416,8 @@ class FunctionAction(ActionBase):
             if kw.has_key('source') and not \
                SCons.Util.is_List(kw['source']):
                 kw['source'] = [ kw['source'] ]
+            if kw.has_key("env") and not isinstance(kw["env"], EnvDictProxy):
+                kw["env"] = EnvDictProxy(kw["env"])
             return apply(self.function, (), kw)
 
     def get_contents(self, **kw):
index 8b417a8f8d464c9039a448d2b0ee9adb24aa63e9..c7cad2d6aa9a107f1479b0faab4b741528d0bd4c 100644 (file)
@@ -158,6 +158,9 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
 
         def f(dummy, env, self=self):
             self.dummy = dummy
+            assert env.subst('$FOO') == 'foo baz\nbar ack', env.subst('$FOO')
+            assert env.subst_list('$FOO') == [ [ 'foo', 'baz' ],
+                                               [ 'bar', 'ack' ] ], env.subst_list('$FOO')
             return [["$FOO"]]
         def ch(cmd, args, env, self=self):
             self.cmd.append(cmd)
@@ -203,13 +206,16 @@ class FunctionActionTestCase(unittest.TestCase):
         """Test executing a function Action
         """
         self.inc = 0
-        def f(s, target, source):
+        def f(s, target, source, env):
             s.inc = s.inc + 1
             s.target = target
             s.source=source
+            assert env.subst("foo$BAR") == 'foofoo bar', env.subst("foo$BAR")
+            assert env.subst_list("foo$BAR") == [ [ 'foofoo', 'bar' ] ], \
+                   env.subst_list("foo$BAR")
             return 0
         a = SCons.Action.FunctionAction(f)
-        a.execute(s = self, target=1, source=2)
+        a.execute(s = self, target=1, source=2, env={'BAR':'foo bar'})
         assert self.inc == 1, self.inc
         assert self.source == [2], self.source
         assert self.target == [1], self.target