summaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-03-12 17:48:40 (GMT)
committerSteven Knight <knight@baldmt.com>2003-03-12 17:48:40 (GMT)
commit739a3fa86075710448e66e6488135b65a9e3f9c4 (patch)
tree6f028265e8d8527aa546aead25b9b1340e2a58d1 /src/engine
parentf77b9a0cb3c8503269ed69c715ea1b7d2588f2e1 (diff)
downloadSCons-739a3fa86075710448e66e6488135b65a9e3f9c4.zip
SCons-739a3fa86075710448e66e6488135b65a9e3f9c4.tar.gz
SCons-739a3fa86075710448e66e6488135b65a9e3f9c4.tar.bz2
Fix the new signature dictionary so it handles slices and attributes such as abspath.
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/SCons/Environment.py25
-rw-r--r--src/engine/SCons/Util.py70
-rw-r--r--src/engine/SCons/UtilTests.py73
3 files changed, 134 insertions, 34 deletions
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index fdfa8b2..8336f74 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -549,31 +549,10 @@ class Environment:
This fills in static TARGET, TARGETS, SOURCE and SOURCES
variables so that signatures stay the same every time.
"""
- class lister:
- def __init__(self, fmt):
- self.fmt = fmt
- def _format(self, index):
- # For some reason, I originally made the fake names of
- # the targets and sources 1-based (['__t1__, '__t2__']),
- # not 0-based. We preserve this behavior by adding one
- # to the returned item names, so everyone's targets
- # won't get recompiled if they were using an old
- # version.
- return self.fmt % (index + 1)
- def __str__(self):
- return self._format(0) + " " + self._format(1)
- def __getitem__(self, index):
- return SCons.Util.PathList([self._format(index)])[0]
- def __getslice__(self, i, j):
- slice = []
- for x in range(i, j):
- slice.append(self._format(x))
- return SCons.Util.PathList(slice)
-
dict = {}
for k,v in self.items(): dict[k] = v
- dict['TARGETS'] = lister('__t%d__')
+ dict['TARGETS'] = SCons.Util.Lister('__t%d__')
dict['TARGET'] = dict['TARGETS'][0]
- dict['SOURCES'] = lister('__s%d__')
+ dict['SOURCES'] = SCons.Util.Lister('__s%d__')
dict['SOURCE'] = dict['SOURCES'][0]
return dict
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index fcadf48..b03ff0f 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -133,8 +133,10 @@ class PathList(UserList.UserList):
first_part, second_part = split_func(strPath)
list1.append(first_part)
list2.append(second_part)
- return (self.__class__(list1),
- self.__class__(list2))
+ # Note that we return explicit PathList() instances, not
+ # self.__class__(). This makes sure the right attributes are
+ # available even if this object is a Lister, not a PathList.
+ return (PathList(list1), PathList(list2))
def __getBasePath(self):
"""Return the file's directory and file name, with the
@@ -159,7 +161,10 @@ class PathList(UserList.UserList):
def __getAbsPath(self):
"""Return the absolute path"""
- return map(lambda x: updrive(os.path.abspath(x)), self.data)
+ # Note that we return an explicit PathList() instance, not
+ # self.__class__(). This makes sure the right attributes are
+ # available even if this object is a Lister, not a PathList.
+ return PathList(map(lambda x: updrive(os.path.abspath(x)), self.data))
dictSpecialAttrs = { "file" : __getFileName,
"base" : __getBasePath,
@@ -174,6 +179,12 @@ class PathList(UserList.UserList):
def __str__(self):
return string.join(self.data)
+ def to_String(self):
+ # Used by our variable-interpolation to interpolate a string.
+ # The interpolation doesn't use __str__() for this because then
+ # it interpolates other lists as "['x', 'y']".
+ return string.join(self.data)
+
def __repr__(self):
return repr(string.join(self.data))
@@ -183,6 +194,49 @@ class PathList(UserList.UserList):
# suffix and basepath.
return self.__class__([ UserList.UserList.__getitem__(self, item), ])
+class Lister(PathList):
+ """A special breed of fake list that not only supports the inherited
+ "path dissection" attributes of PathList, but also uses a supplied
+ format string to generate arbitrary (slices of) individually-named
+ elements on the fly.
+ """
+ def __init__(self, fmt):
+ self.fmt = fmt
+ PathList.__init__(self, [ self._element(0), self._element(1) ])
+ def __getitem__(self, index):
+ return PathList([self._element(index)])
+ def _element(self, index):
+ """Generate the index'th element in this list."""
+ # For some reason, I originally made the fake names of
+ # the targets and sources 1-based (['__t1__, '__t2__']),
+ # not 0-based. We preserve this behavior by adding one
+ # to the returned item names, so everyone's targets
+ # won't get recompiled if they were using an old version.
+ return self.fmt % (index + 1)
+ def __iter__(self):
+ """Return an iterator object for Python 2.2."""
+ class Lister_iter:
+ def __init__(self, data):
+ self.data = data
+ self.index = 0
+ def __iter__(self):
+ return self
+ def next(self):
+ try:
+ element = self.data[self.index]
+ except IndexError:
+ raise StopIteration
+ self.index = self.index + 1
+ return element
+ return Lister_iter(self.data)
+ def __getslice__(self, i, j):
+ slice = []
+ if j == sys.maxint:
+ j = i + 2
+ for x in range(i, j):
+ slice.append(self._element(x))
+ return PathList(slice)
+
_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[^}]*})$')
def get_environment_var(varstr):
@@ -378,7 +432,10 @@ def scons_subst_list(strSubst, globals, locals, remove=None):
elif is_String(x):
return _space_sep.sub('\0', x)
elif is_List(x):
- return string.join(map(to_String, x), '\0')
+ try:
+ return x.to_String()
+ except AttributeError:
+ return string.join(map(to_String, x), '\0')
else:
return to_String(x)
@@ -439,7 +496,10 @@ def scons_subst(strSubst, globals, locals, remove=None):
if e is None:
s = ''
elif is_List(e):
- s = string.join(map(to_String, e), ' ')
+ try:
+ s = e.to_String()
+ except AttributeError:
+ s = string.join(map(to_String, e), ' ')
else:
s = to_String(e)
except NameError:
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index 0e81a1d..f77265a 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -45,9 +45,9 @@ class OutBuffer:
class UtilTestCase(unittest.TestCase):
- def test_subst(self):
- """Test the subst function."""
- loc = {}
+ def test_subst_PathList(self):
+ """Test the subst function with PathLists"""
+ loc = {}
loc['TARGETS'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
"/bar/baz.obj",
"../foo/baz.obj" ]))
@@ -97,16 +97,18 @@ class UtilTestCase(unittest.TestCase):
newcom = scons_subst("test ${TARGET.dir}", loc, {})
assert newcom == cvt("test foo")
+ cwd = SCons.Util.updrive(os.getcwd())
+
newcom = scons_subst("test ${TARGET.abspath}", loc, {})
- assert newcom == cvt("test %s/foo/bar.exe"%SCons.Util.updrive(os.getcwd())), newcom
+ assert newcom == cvt("test %s/foo/bar.exe" % (cwd)), newcom
newcom = scons_subst("test ${SOURCES.abspath}", loc, {})
- assert newcom == cvt("test %s/foo/blah.cpp %s %s/foo/ack.c"%(SCons.Util.updrive(os.getcwd()),
+ assert newcom == cvt("test %s/foo/blah.cpp %s %s/foo/ack.c"%(cwd,
SCons.Util.updrive(os.path.abspath(os.path.normpath("/bar/ack.cpp"))),
SCons.Util.updrive(os.path.normpath(os.getcwd()+"/..")))), newcom
newcom = scons_subst("test ${SOURCE.abspath}", loc, {})
- assert newcom == cvt("test %s/foo/blah.cpp"%SCons.Util.updrive(os.getcwd())), newcom
+ assert newcom == cvt("test %s/foo/blah.cpp" % (cwd)), newcom
newcom = scons_subst("test $xxx", loc, {})
assert newcom == cvt("test"), newcom
@@ -151,6 +153,65 @@ class UtilTestCase(unittest.TestCase):
newcom = scons_subst("$$FOO$BAZ", glob, {})
assert newcom == "$FOOBLAT", newcom
+ def test_subst_Lister(self):
+ """Test the subst function with Listers"""
+ loc = {}
+ loc['TARGETS'] = Lister('t%d')
+ loc['TARGET'] = loc['TARGETS'][0]
+ loc['SOURCES'] = Lister('s%d')
+ loc['SOURCE'] = loc['SOURCES'][0]
+ loc['xxx'] = None
+ loc['zero'] = 0
+ loc['one'] = 1
+
+ if os.sep == '/':
+ def cvt(str):
+ return str
+ else:
+ def cvt(str):
+ return string.replace(str, '/', os.sep)
+
+ newcom = scons_subst("test $TARGETS $SOURCES", loc, {})
+ assert newcom == cvt("test t1 t2 s1 s2"), newcom
+
+ newcom = scons_subst("test ${TARGETS[:]} ${SOURCES[0]}", loc, {})
+ assert newcom == cvt("test t1 t2 s1"), newcom
+
+ newcom = scons_subst("test ${TARGETS[1:]}v", loc, {})
+ assert newcom == cvt("test t2 t3v"), newcom
+
+ newcom = scons_subst("test $TARGET", loc, {})
+ assert newcom == cvt("test t1"), newcom
+
+ newcom = scons_subst("test $TARGET$FOO[0]", loc, {})
+ assert newcom == cvt("test t1[0]"), newcom
+
+ newcom = scons_subst("test ${TARGET.file}", loc, {})
+ assert newcom == cvt("test t1"), newcom
+
+ newcom = scons_subst("test ${TARGET.filebase}", loc, {})
+ assert newcom == cvt("test t1"), newcom
+
+ newcom = scons_subst("test ${TARGET.suffix}", loc, {})
+ assert newcom == cvt("test"), newcom
+
+ newcom = scons_subst("test ${TARGET.base}", loc, {})
+ assert newcom == cvt("test t1"), newcom
+
+ newcom = scons_subst("test ${TARGET.dir}", loc, {})
+ assert newcom == cvt("test"), newcom
+
+ cwd = SCons.Util.updrive(os.getcwd())
+
+ newcom = scons_subst("test ${TARGET.abspath}", loc, {})
+ assert newcom == cvt("test %s/t1" % (cwd)), newcom
+
+ newcom = scons_subst("test ${SOURCES.abspath}", loc, {})
+ assert newcom == cvt("test %s/s1 %s/s2" % (cwd, cwd)), newcom
+
+ newcom = scons_subst("test ${SOURCE.abspath}", loc, {})
+ assert newcom == cvt("test %s/s1" % cwd), newcom
+
def test_splitext(self):
assert splitext('foo') == ('foo','')
assert splitext('foo.bar') == ('foo','.bar')