From: stevenknight Date: Fri, 12 Oct 2001 02:17:49 +0000 (+0000) Subject: Refactor construction variable expansion. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=25761b5fe89c721f748f5e8f85dceab7936bbdb9;p=scons.git Refactor construction variable expansion. git-svn-id: http://scons.tigris.org/svn/scons/trunk@96 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 9e84a7d8..ac24e7f4 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -33,7 +33,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import SCons.Node.FS -from SCons.Util import PathList, scons_str2nodes, scons_varrepl +from SCons.Util import PathList, scons_str2nodes, scons_subst import string import types @@ -210,21 +210,25 @@ class CommandAction(ActionBase): self.command = string def execute(self, **kw): - try: - t = kw['target'] - if type(t) is types.StringType: - t = [t] - tgt = PathList(map(os.path.normpath, t)) - except: - tgt = PathList() - try: - s = kw['source'] - if type(s) is types.StringType: - s = [s] - src = PathList(map(os.path.normpath, s)) - except: - src = PathList() - cmd = scons_varrepl(self.command, tgt, src) + loc = {} + if kw.has_key('target'): + t = kw['target'] + if type(t) is type(""): + t = [t] + loc['targets'] = PathList(map(os.path.normpath, t)) + loc['target'] = loc['targets'][0] + if kw.has_key('source'): + s = kw['source'] + if type(s) is type(""): + s = [s] + loc['sources'] = PathList(map(os.path.normpath, s)) + + try: + glob = self.env.Dictionary() + except: + glob = {} + + cmd = scons_subst(self.command, loc, glob) if print_actions: self.show(cmd) ret = 0 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 16032b9e..468c9b4f 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -49,10 +49,6 @@ def InstallAs(): -_cv = re.compile(r'%([_a-zA-Z]\w*|{[_a-zA-Z]\w*})') - - - def _deepcopy_atomic(x, memo): return x copy._deepcopy_dispatch[types.ModuleType] = _deepcopy_atomic @@ -173,20 +169,11 @@ class Environment: def subst(self, string): """Recursively interpolates construction variables from the Environment into the specified string, returning the expanded - result. Construction variables are specified by a % prefix + result. Construction variables are specified by a $ prefix in the string and begin with an initial underscore or alphabetic character followed by any number of underscores or alphanumeric characters. The construction variable names may be surrounded by curly braces to separate the name from trailing characters. """ - def repl(m, _self=self): - key = m.group(1) - if key[:1] == '{' and key[-1:] == '}': - key = key[1:-1] - if _self._dict.has_key(key): return _self._dict[key] - else: return '' - n = 1 - while n != 0: - string, n = _cv.subn(repl, string) - return string + return SCons.Util.scons_subst(string, self._dict, {}) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 9035cd4f..07e84a4e 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -172,10 +172,10 @@ class EnvironmentTestCase(unittest.TestCase): """Test the Command() method.""" env = Environment() t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'], - action='buildfoo %(target)s %(source)s') + action='buildfoo $target $source') assert t.derived assert t.builder.action.__class__.__name__ == 'CommandAction' - assert t.builder.action.command == 'buildfoo %(target)s %(source)s' + assert t.builder.action.command == 'buildfoo $target $source' assert 'foo1.in' in map(lambda x: x.path, t.sources) assert 'foo2.in' in map(lambda x: x.path, t.sources) @@ -192,13 +192,13 @@ class EnvironmentTestCase(unittest.TestCase): of variables into other variables. """ env = Environment(AAA = 'a', BBB = 'b') - str = env.subst("%AAA %{AAA}A %BBBB %BBB") + str = env.subst("$AAA ${AAA}A $BBBB $BBB") assert str == "a aA b", str - env = Environment(AAA = '%BBB', BBB = 'b', BBBA = 'foo') - str = env.subst("%AAA %{AAA}A %{AAA}B %BBB") + env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') + str = env.subst("$AAA ${AAA}A ${AAA}B $BBB") assert str == "b foo b", str - env = Environment(AAA = '%BBB', BBB = '%CCC', CCC = 'c') - str = env.subst("%AAA %{AAA}A %{AAA}B %BBB") + env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') + str = env.subst("$AAA ${AAA}A ${AAA}B $BBB") assert str == "c c", str diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2a6858c2..00a83301 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -158,32 +158,31 @@ class PathList(UserList): return self.__class__([ UserList.__getitem__(self, item), ]) -__tcv = re.compile(r'\$(\{?targets?(\[[0-9:]+\])?(\.[a-z]+)?\}?)') -__scv = re.compile(r'\$(\{?sources(\[[0-9:]+\])?(\.[a-z]+)?\}?)') -def scons_varrepl(command, targets, sources): - """This routine handles variable interpolation for the $targets and - $sources variables in the 'command' argument. The targets and sources - given in the other arguements must be lists containing 'Node's.""" - - def repl(m, targets=targets, sources=sources): - globals = {} - key = m.group(1) - if key[0] == '{': - if key[-1] == '}': - key = key[1:-1] - else: - raise SyntaxError, "Bad regular expression" - - if key[:6] == 'target': - globals['targets'] = targets - globals['target'] = targets[0] - if key[:7] == 'sources': - globals['sources'] = sources - if globals: - return str(eval(key, globals )) - - command = __tcv.sub(repl, command) - command = __scv.sub(repl, command) - return command +_tok = r'[_a-zA-Z]\w*' +_cv = re.compile(r'\$(%s|{%s(\[[-0-9:]*\])?(\.\w+)?})' % (_tok, _tok)) + +def scons_subst(string, locals, globals): + """Recursively interpolates dictionary variables into + the specified string, returning the expanded result. + Variables are specified by a $ prefix in the string and + begin with an initial underscore or alphabetic character + followed by any number of underscores or alphanumeric + characters. The construction variable names may be + surrounded by curly braces to separate the name from + trailing characters. + """ + def repl(m, locals=locals, globals=globals): + key = m.group(1) + if key[:1] == '{' and key[-1:] == '}': + key = key[1:-1] + try: + s = str(eval(key, locals, globals)) + except NameError: + s = '' + return s + n = 1 + while n != 0: + string, n = _cv.subn(repl, string) + return string diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index db4d7a14..bbaf851f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -28,7 +28,7 @@ import os.path import unittest import SCons.Node import SCons.Node.FS -from SCons.Util import scons_str2nodes, scons_varrepl, PathList +from SCons.Util import scons_str2nodes, scons_subst, PathList class UtilTestCase(unittest.TestCase): @@ -72,43 +72,45 @@ class UtilTestCase(unittest.TestCase): node = scons_str2nodes(OtherNode()) - def test_varrepl(self): - """Test the varrepl function.""" - targets = PathList(map(os.path.normpath, [ "./foo/bar.exe", - "/bar/baz.obj", - "../foo/baz.obj" ])) - sources = PathList(map(os.path.normpath, [ "./foo/blah.cpp", - "/bar/ack.cpp", - "../foo/ack.c" ])) + def test_subst(self): + """Test the subst function.""" + loc = {} + loc['targets'] = PathList(map(os.path.normpath, [ "./foo/bar.exe", + "/bar/baz.obj", + "../foo/baz.obj" ])) + loc['target'] = loc['targets'][0] + loc['sources'] = PathList(map(os.path.normpath, [ "./foo/blah.cpp", + "/bar/ack.cpp", + "../foo/ack.c" ])) - newcom = scons_varrepl("test $targets $sources", targets, sources) + newcom = scons_subst("test $targets $sources", loc, {}) assert newcom == "test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp /bar/ack.cpp ../foo/ack.c" - newcom = scons_varrepl("test $targets[:] $sources[0]", targets, sources) + newcom = scons_subst("test ${targets[:]} ${sources[0]}", loc, {}) assert newcom == "test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp" - newcom = scons_varrepl("test ${targets[1:]}v", targets, sources) + newcom = scons_subst("test ${targets[1:]}v", loc, {}) assert newcom == "test /bar/baz.obj ../foo/baz.objv" - newcom = scons_varrepl("test $target", targets, sources) + newcom = scons_subst("test $target", loc, {}) assert newcom == "test foo/bar.exe" - newcom = scons_varrepl("test $target$source[0]", targets, sources) - assert newcom == "test foo/bar.exe$source[0]" + newcom = scons_subst("test $target$source[0]", loc, {}) + assert newcom == "test foo/bar.exe[0]" - newcom = scons_varrepl("test ${target.file}", targets, sources) + newcom = scons_subst("test ${target.file}", loc, {}) assert newcom == "test bar.exe" - newcom = scons_varrepl("test ${target.filebase}", targets, sources) + newcom = scons_subst("test ${target.filebase}", loc, {}) assert newcom == "test bar" - newcom = scons_varrepl("test ${target.suffix}", targets, sources) + newcom = scons_subst("test ${target.suffix}", loc, {}) assert newcom == "test .exe" - newcom = scons_varrepl("test ${target.base}", targets, sources) + newcom = scons_subst("test ${target.base}", loc, {}) assert newcom == "test foo/bar" - newcom = scons_varrepl("test ${target.dir}", targets, sources) + newcom = scons_subst("test ${target.dir}", loc, {}) assert newcom == "test foo"