summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine/SCons/Action.py11
-rw-r--r--src/engine/SCons/ActionTests.py18
-rw-r--r--src/engine/SCons/BuilderTests.py2
-rw-r--r--src/engine/SCons/EnvironmentTests.py2
-rw-r--r--src/engine/SCons/Node/FS.py148
-rw-r--r--src/engine/SCons/Node/FSTests.py6
-rw-r--r--src/engine/SCons/Node/NodeTests.py6
-rw-r--r--src/engine/SCons/Node/__init__.py17
-rw-r--r--src/engine/SCons/Util.py69
-rw-r--r--src/engine/SCons/UtilTests.py16
10 files changed, 175 insertions, 120 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index befac1e..49b0cb1 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -262,8 +262,10 @@ class CommandAction(ActionBase):
if not SCons.Util.is_List(cmd):
cmd = [ cmd ]
return SCons.Util.scons_subst(string.join(map(str, cmd)),
- env, SCons.Util.SUBST_RAW,
- target, source)
+ env,
+ SCons.Util.SUBST_RAW,
+ SCons.Util.target_prep(target),
+ SCons.Util.source_prep(source))
def get_contents(self, target, source, env):
"""Return the signature contents of this action's command line.
@@ -277,7 +279,8 @@ class CommandAction(ActionBase):
return SCons.Util.scons_subst(string.join(map(str, cmd)),
env,
SCons.Util.SUBST_SIG,
- target, source)
+ SCons.Util.target_prep(target),
+ SCons.Util.source_prep(source))
class CommandGeneratorAction(ActionBase):
"""Class for command-generator actions."""
@@ -403,6 +406,8 @@ class ListAction(ActionBase):
Simple concatenation of the signatures of the elements.
"""
+ target = SCons.Util.target_prep(target)
+ source = SCons.Util.source_prep(source)
return string.join(map(lambda x, t=target, s=source, e=env:
x.get_contents(t, s, e),
self.list),
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index 33bf57e..3e32594 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -134,6 +134,8 @@ class DummyNode:
return self.name
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
if os.name == 'java':
python = os.path.join(sys.prefix, 'jython')
@@ -392,7 +394,7 @@ class CommandActionTestCase(unittest.TestCase):
cmd2 = r'%s %s %s $TARGET' % (python, act_py, outfile)
act = SCons.Action.CommandAction(cmd2)
- r = act('foo', [], env.Copy())
+ r = act(DummyNode('foo'), [], env.Copy())
assert r == 0
c = test.read(outfile, 'r')
assert c == "act.py: 'foo'\n", c
@@ -400,7 +402,7 @@ class CommandActionTestCase(unittest.TestCase):
cmd3 = r'%s %s %s ${TARGETS}' % (python, act_py, outfile)
act = SCons.Action.CommandAction(cmd3)
- r = act(['aaa', 'bbb'], [], env.Copy())
+ r = act(map(DummyNode, ['aaa', 'bbb']), [], env.Copy())
assert r == 0
c = test.read(outfile, 'r')
assert c == "act.py: 'aaa' 'bbb'\n", c
@@ -437,13 +439,13 @@ class CommandActionTestCase(unittest.TestCase):
PATH = ''
env5['ENV']['XYZZY'] = 'xyzzy'
- r = act(target = 'out5', source = [], env = env5)
+ r = act(target = DummyNode('out5'), source = [], env = env5)
act = SCons.Action.CommandAction(cmd5)
r = act(target = DummyNode('out5'),
- source = [],
- env = env.Copy(ENV = {'XYZZY' : 'xyzzy',
- 'PATH' : PATH}))
+ source = [],
+ env = env.Copy(ENV = {'XYZZY' : 'xyzzy',
+ 'PATH' : PATH}))
assert r == 0
c = test.read(outfile, 'r')
assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy'\n", c
@@ -455,6 +457,8 @@ class CommandActionTestCase(unittest.TestCase):
return self._str
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (python, act_py, outfile)
@@ -749,6 +753,8 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
def rfile(self):
self.t.rfile_called = 1
return self
+ def get_subst_proxy(self):
+ return self
def f3(target, source, env, for_signature):
return ''
c = SCons.Action.CommandGeneratorAction(f3)
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index 5f9a18c..6def6d5 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -255,6 +255,8 @@ class BuilderTestCase(unittest.TestCase):
return self.name
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
target = map(DummyNode, map(lambda x: "__t%d__" % x, range(1, 7)))
source = map(DummyNode, map(lambda x: "__s%d__" % x, range(1, 7)))
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 28ea0e5..6473bdd 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -574,6 +574,8 @@ class EnvironmentTestCase(unittest.TestCase):
return self.name
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
# Test callables in the Environment
def foo(target, source, env, for_signature):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index e64aacc..884736e 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -190,7 +190,7 @@ class ParentOfRoot:
This class is an instance of the Null object pattern.
"""
def __init__(self):
- self.abspath_str = ''
+ self.abspath = ''
self.path = ''
self.abspath_ = ''
self.path_ = ''
@@ -224,6 +224,61 @@ else:
def _my_normcase(x):
return string.upper(x)
+class EntryProxy(SCons.Util.Proxy):
+ def __init__(self, entry):
+ SCons.Util.Proxy.__init__(self, entry)
+ self.abspath = SCons.Util.SpecialAttrWrapper(entry.abspath,
+ entry.name + "_abspath")
+ filebase, suffix = os.path.splitext(entry.name)
+ self.filebase = SCons.Util.SpecialAttrWrapper(filebase,
+ entry.name + "_filebase")
+ self.suffix = SCons.Util.SpecialAttrWrapper(suffix,
+ entry.name + "_suffix")
+ self.file = SCons.Util.SpecialAttrWrapper(entry.name,
+ entry.name + "_file")
+
+ def __get_base_path(self):
+ """Return the file's directory and file name, with the
+ suffix stripped."""
+ return SCons.Util.SpecialAttrWrapper(os.path.splitext(self.get().get_path())[0],
+ self.get().name + "_base")
+
+ def __get_posix_path(self):
+ """Return the path with / as the path separator, regardless
+ of platform."""
+ if os.sep == '/':
+ return self
+ else:
+ return SCons.Util.SpecialAttrWrapper(string.replace(self.get().get_path(),
+ os.sep, '/'),
+ self.get().name + "_posix")
+
+ def __get_srcnode(self):
+ return EntryProxy(self.get().srcnode())
+
+ def __get_srcdir(self):
+ """Returns the directory containing the source node linked to this
+ node via BuildDir(), or the directory of this node if not linked."""
+ return EntryProxy(self.get().srcnode().dir)
+
+ def __get_dir(self):
+ return EntryProxy(self.get().dir)
+
+ dictSpecialAttrs = { "base" : __get_base_path,
+ "posix" : __get_posix_path,
+ "srcpath" : __get_srcnode,
+ "srcdir" : __get_srcdir,
+ "dir" : __get_dir }
+
+ def __getattr__(self, name):
+ # This is how we implement the "special" attributes
+ # such as base, posix, srcdir, etc.
+ try:
+ return self.dictSpecialAttrs[name](self)
+ except KeyError:
+ return SCons.Util.Proxy.__getattr__(self, name)
+
+
class Entry(SCons.Node.Node):
"""A generic class for file system entries. This class is for
when we don't know yet whether the entry being looked up is a file
@@ -251,14 +306,14 @@ class Entry(SCons.Node.Node):
assert directory, "A directory must be provided"
- self.abspath_str = directory.abspath_ + name
+ self.abspath = directory.abspath_ + name
if directory.path == '.':
self.path = name
else:
self.path = directory.path_ + name
self.path_ = self.path
- self.abspath_ = self.abspath_str
+ self.abspath_ = self.abspath
self.dir = directory
self.cwd = None # will hold the SConscript directory for target nodes
self.duplicate = directory.duplicate
@@ -293,11 +348,11 @@ class Entry(SCons.Node.Node):
Since this should return the real contents from the file
system, we check to see into what sort of subclass we should
morph this Entry."""
- if os.path.isfile(self.abspath_str):
+ if os.path.isfile(self.abspath):
self.__class__ = File
self._morph()
return File.get_contents(self)
- if os.path.isdir(self.abspath_str):
+ if os.path.isdir(self.abspath):
self.__class__ = Dir
self._morph()
return Dir.get_contents(self)
@@ -307,7 +362,7 @@ class Entry(SCons.Node.Node):
try:
return self._exists
except AttributeError:
- self._exists = _existsp(self.abspath_str)
+ self._exists = _existsp(self.abspath)
return self._exists
def rexists(self):
@@ -403,64 +458,9 @@ class Entry(SCons.Node.Node):
self.sbuilder = scb
return scb
- def get_base_path(self):
- """Return the file's directory and file name, with the
- suffix stripped."""
- return os.path.splitext(self.get_path())[0]
-
- def get_suffix(self):
- """Return the file's suffix."""
- return os.path.splitext(self.get_path())[1]
-
- def get_file_name(self):
- """Return the file's name without the path."""
- return self.name
-
- def get_file_base(self):
- """Return the file name with path and suffix stripped."""
- return os.path.splitext(self.name)[0]
-
- def get_posix_path(self):
- """Return the path with / as the path separator, regardless
- of platform."""
- if os.sep == '/':
- return str(self)
- else:
- return string.replace(self.get_path(), os.sep, '/')
-
def get_abspath(self):
"""Get the absolute path of the file."""
- return self.abspath_str
-
- def get_srcdir(self):
- """Returns the directory containing the source node linked to this
- node via BuildDir(), or the directory of this node if not linked."""
- return self.srcnode().dir
-
- dictSpecialAttrs = { "file" : get_file_name,
- "base" : get_base_path,
- "filebase" : get_file_base,
- "suffix" : get_suffix,
- "posix" : get_posix_path,
- "abspath" : get_abspath,
- "srcpath" : srcnode,
- "srcdir" : get_srcdir }
-
- def __getattr__(self, name):
- # This is how we implement the "special" attributes
- # such as base, suffix, basepath, etc.
- #
- # Note that we enclose values in a SCons.Util.Literal instance,
- # so they will retain special characters during Environment variable
- # substitution.
- try:
- attr = self.dictSpecialAttrs[name](self)
- except KeyError:
- raise AttributeError, '%s has no attribute: %s' % (self.__class__, name)
- if SCons.Util.is_String(attr):
- return SCons.Util.SpecialAttrWrapper(attr, self.name +
- "_%s" % name)
- return attr
+ return self.abspath
def for_signature(self):
# Return just our name. Even an absolute path would not work,
@@ -468,6 +468,14 @@ class Entry(SCons.Node.Node):
# paths.
return self.name
+ def get_subst_proxy(self):
+ try:
+ return self._proxy
+ except AttributeError:
+ ret = EntryProxy(self)
+ self._proxy = ret
+ return ret
+
# This is for later so we can differentiate between Entry the class and Entry
# the method of the FS class.
_classEntry = Entry
@@ -556,7 +564,7 @@ class FS:
raise SCons.Errors.UserError
dir = Dir(drive, ParentOfRoot(), self)
dir.path = dir.path + os.sep
- dir.abspath_str = dir.abspath_str + os.sep
+ dir.abspath = dir.abspath + os.sep
self.Root[drive] = dir
directory = dir
path_comp = path_comp[1:]
@@ -642,7 +650,7 @@ class FS:
if not dir is None:
self._cwd = dir
if change_os_dir:
- os.chdir(dir.abspath_str)
+ os.chdir(dir.abspath)
except:
self._cwd = curr
raise
@@ -850,7 +858,7 @@ class Dir(Entry):
node) don't use signatures for currency calculation."""
self.path_ = self.path + os.sep
- self.abspath_ = self.abspath_str + os.sep
+ self.abspath_ = self.abspath + os.sep
self.repositories = []
self.srcdir = None
@@ -951,9 +959,9 @@ class Dir(Entry):
keys = filter(lambda k: k != '.' and k != '..', self.entries.keys())
kids = map(lambda x, s=self: s.entries[x], keys)
def c(one, two):
- if one.abspath_str < two.abspath_str:
+ if one.abspath < two.abspath:
return -1
- if one.abspath_str > two.abspath_str:
+ if one.abspath > two.abspath:
return 1
return 0
kids.sort(c)
@@ -1085,11 +1093,11 @@ class File(Entry):
def get_contents(self):
if not self.rexists():
return ''
- return open(self.rfile().abspath_str, "rb").read()
+ return open(self.rfile().abspath, "rb").read()
def get_timestamp(self):
if self.rexists():
- return os.path.getmtime(self.rfile().abspath_str)
+ return os.path.getmtime(self.rfile().abspath)
else:
return 0
@@ -1328,7 +1336,7 @@ class File(Entry):
# Duplicate from source path if we are set up to do this.
if self.duplicate and not self.has_builder() and not self.linked:
src=self.srcnode().rfile()
- if src.exists() and src.abspath_str != self.abspath_str:
+ if src.exists() and src.abspath != self.abspath:
self._createDir()
try:
Unlink(self, None, None)
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 209e80d..1f58264 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1524,7 +1524,7 @@ class SpecialAttrTestCase(unittest.TestCase):
test=TestCmd(workdir='')
fs = SCons.Node.FS.FS(test.workpath(''))
- f=fs.Entry('foo/bar/baz.blat')
+ f=fs.Entry('foo/bar/baz.blat').get_subst_proxy()
assert str(f.dir) == os.path.normpath('foo/bar'), str(f.dir)
assert f.dir.is_literal()
assert f.dir.for_signature() == 'bar', f.dir.for_signature()
@@ -1564,11 +1564,11 @@ class SpecialAttrTestCase(unittest.TestCase):
assert str(f.srcpath) == os.path.normpath('baz/bar/baz.blat'), str(f.srcpath)
assert f.srcpath.is_literal()
- assert isinstance(f.srcpath, SCons.Node.FS.Entry)
+ assert isinstance(f.srcpath.get(), SCons.Node.FS.Entry)
assert str(f.srcdir) == os.path.normpath('baz/bar'), str(f.srcdir)
assert f.srcdir.is_literal()
- assert isinstance(f.srcdir, SCons.Node.FS.Dir)
+ assert isinstance(f.srcdir.get(), SCons.Node.FS.Dir)
# And now, combinations!!!
assert str(f.srcpath.base) == os.path.normpath('baz/bar/baz'), str(f.srcpath.base)
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index b188f81..2cf6d4b 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -949,6 +949,12 @@ class NodeTestCase(unittest.TestCase):
assert n.found_includes == {}, n.found_includes
assert n.implicit is None, n.implicit
+ def test_get_subst_proxy(self):
+ """Test the get_subst_proxy method."""
+ n = MyNode("test")
+
+ assert n.get_subst_proxy() == n, n.get_subst_proxy()
+
if __name__ == "__main__":
suite = unittest.makeSuite(NodeTestCase, 'test_')
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 883d757..5231f90 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -628,7 +628,7 @@ class Node:
generator is being called to generate a signature for the
command line, which determines if we should rebuild or not.
- Such command generators should use this method in preference
+ Such command generators shoud use this method in preference
to str(Node) when converting a Node to a string, passing
in the for_signature parameter, such that we will call
Node.for_signature() or str(Node) properly, depending on whether
@@ -638,6 +638,21 @@ class Node:
return self.for_signature()
return str(self)
+ def get_subst_proxy(self):
+ """
+ This method is expected to return an object that will function
+ exactly like this Node, except that it implements any additional
+ special features that we would like to be in effect for
+ Environment variable substitution. The principle use is that
+ some Nodes would like to implement a __getattr__() method,
+ but putting that in the Node type itself has a tendency to kill
+ performance. We instead put it in a proxy and return it from
+ this method. It is legal for this method to return self
+ if no new functionality is needed for Environment substitution.
+ """
+ return self
+
+
def get_children(node, parent): return node.children()
def ignore_cycle(node, stack): pass
def do_nothing(node, parent): pass
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index b7aac31..8d81437 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -341,17 +341,26 @@ class DisplayEngine:
else:
self.__call__ = self.dont_print
+def target_prep(target):
+ if target and not isinstance(target, NodeList):
+ if not is_List(target):
+ target = [target]
+ target = NodeList(map(lambda x: x.get_subst_proxy(), target))
+ return target
+
+def source_prep(source):
+ if source and not isinstance(source, NodeList):
+ if not is_List(source):
+ source = [source]
+ source = NodeList(map(lambda x: x.rfile().get_subst_proxy(), source))
+ return source
def subst_dict(target, source, env):
- """Create a dictionary for substitution of construction
- variables.
+ """Create a dictionary for substitution of special
+ construction variables.
This translates the following special arguments:
- env - the construction environment itself,
- the values of which (CC, CCFLAGS, etc.)
- are copied straight into the dictionary
-
target - the target (object or array of objects),
used to generate the TARGET and TARGETS
construction variables
@@ -359,20 +368,20 @@ def subst_dict(target, source, env):
source - the source (object or array of objects),
used to generate the SOURCES and SOURCE
construction variables
- """
-
- dict = env.Dictionary().copy()
- if not is_List(target):
- target = [target]
+ env - the construction Environment used for this
+ build, which is made available as the __env__
+ construction variable
+ """
+ dict = { '__env__' : env }
- dict['TARGETS'] = NodeList(target)
+ target = target_prep(target)
+ dict['TARGETS'] = target
if dict['TARGETS']:
dict['TARGET'] = dict['TARGETS'][0]
- if not is_List(source):
- source = [source]
- dict['SOURCES'] = NodeList(map(lambda x: x.rfile(), source))
+ source = source_prep(source)
+ dict['SOURCES'] = source
if dict['SOURCES']:
dict['SOURCE'] = dict['SOURCES'][0]
@@ -406,8 +415,7 @@ def _canonicalize(obj):
_regex_remove = [ None, _rm, _remove ]
_strconv = [ to_String, to_String, _canonicalize ]
-def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None,
- source=None):
+def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None):
"""
This function serves the same purpose as scons_subst(), except
this function returns the interpolated list as a list of lines, where
@@ -434,18 +442,13 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None,
remove = _regex_remove[mode]
strconv = _strconv[mode]
-
- if target != None:
- dict = subst_dict(target, source, env)
- else:
- dict = env.Dictionary()
def repl(m,
target=target,
source=source,
env=env,
- local_vars = dict,
- global_vars = { "__env__" : env },
+ local_vars = subst_dict(target, source, env),
+ global_vars = env.Dictionary(),
strconv=strconv,
sig=(mode != SUBST_CMD)):
key = m.group(1)
@@ -492,8 +495,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None,
return map(lambda x: map(CmdStringHolder, filter(lambda y:y, string.split(x, '\0\1'))),
listLines)
-def scons_subst(strSubst, env, mode=SUBST_RAW, target=None,
- source=None):
+def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None):
"""Recursively interpolates dictionary variables into
the specified string, returning the expanded result.
Variables are specified by a $ prefix in the string and
@@ -506,11 +508,6 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None,
# This function needs to be fast, so don't call scons_subst_list
- if target != None:
- dict = subst_dict(target, source, env)
- else:
- dict = env.Dictionary()
-
remove = _regex_remove[mode]
strconv = _strconv[mode]
@@ -518,8 +515,8 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None,
target=target,
source=source,
env=env,
- local_vars = dict,
- global_vars = { '__env__' : env },
+ local_vars = subst_dict(target, source, env),
+ global_vars = env.Dictionary(),
strconv=strconv,
sig=(mode != SUBST_CMD)):
key = m.group(1)
@@ -530,7 +527,8 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None,
except NameError:
return '\0\5'
if callable(e):
- e = e(target=target, source=source, env=env, for_signature=sig)
+ e = e(target=target, source=source, env=env,
+ for_signature = sig)
def conv(arg, strconv=strconv):
literal = 0
@@ -691,6 +689,9 @@ class Proxy:
def __getattr__(self, name):
return getattr(self.__subject, name)
+ def get(self):
+ return self.__subject
+
# attempt to load the windows registry module:
can_read_reg = 0
try:
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index e0543d9..a48b302 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -95,6 +95,9 @@ class UtilTestCase(unittest.TestCase):
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
+
foo = 1
target = [ N("./foo/bar.exe"),
@@ -241,6 +244,8 @@ class UtilTestCase(unittest.TestCase):
return 1
def rfile(self):
return self
+ def get_subst_proxy(self):
+ return self
loc = {}
target = [ Node("./foo/bar.exe"),
@@ -589,6 +594,7 @@ class UtilTestCase(unittest.TestCase):
s.baz = 6
assert p.baz == 5, p.baz
+ assert p.get() == s, p.get()
def test_Literal(self):
"""Test the Literal() function."""
@@ -710,9 +716,9 @@ class UtilTestCase(unittest.TestCase):
def test_subst_dict(self):
"""Test substituting dictionary values in an Action
"""
- d = subst_dict([], [], DummyEnv({'a' : 'A', 'b' : 'B'}))
- assert d['a'] == 'A', d
- assert d['b'] == 'B', d
+ env = DummyEnv({'a' : 'A', 'b' : 'B'})
+ d = subst_dict([], [], env)
+ assert d['__env__'] is env, d['__env__']
class SimpleNode:
def __init__(self, data):
@@ -723,6 +729,8 @@ class UtilTestCase(unittest.TestCase):
return self
def is_literal(self):
return 1
+ def get_subst_proxy(self):
+ return self
d = subst_dict(target = SimpleNode('t'), source = SimpleNode('s'), env=DummyEnv())
assert str(d['TARGETS'][0]) == 't', d['TARGETS']
@@ -749,6 +757,8 @@ class UtilTestCase(unittest.TestCase):
return self.name
def rfile(self):
return self.__class__('rstr-' + self.name)
+ def get_subst_proxy(self):
+ return self
d = subst_dict(target = [N('t3'), SimpleNode('t4')],
source = [SimpleNode('s3'), N('s4')],