diff options
author | Steven Knight <knight@baldmt.com> | 2003-03-12 17:48:40 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2003-03-12 17:48:40 (GMT) |
commit | 739a3fa86075710448e66e6488135b65a9e3f9c4 (patch) | |
tree | 6f028265e8d8527aa546aead25b9b1340e2a58d1 /src/engine | |
parent | f77b9a0cb3c8503269ed69c715ea1b7d2588f2e1 (diff) | |
download | SCons-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.py | 25 | ||||
-rw-r--r-- | src/engine/SCons/Util.py | 70 | ||||
-rw-r--r-- | src/engine/SCons/UtilTests.py | 73 |
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') |