From 3ccdd2cb4b633d5d3603d1af53c2e578f1af8f1d Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Fri, 5 Apr 2002 17:19:03 +0000 Subject: Clean up how the Environment dictionary is passed to function Actions. (Charles Crain) --- src/CHANGES.txt | 4 ++++ src/engine/SCons/Action.py | 34 +++++++++++++++++++++++++++++++++- src/engine/SCons/ActionTests.py | 10 ++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index da541f3..e2a46e2 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,6 +10,10 @@ 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! diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 9b65e38..3ed3d73 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -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): diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 8b417a8..c7cad2d 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -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 -- cgit v0.12