Anonymous avatar Anonymous committed 57bd742

http://scons.tigris.org/issues/show_bug.cgi?id=2345

Comb out all code that supported earlier versions of Python. Most such
code is in snippets of only a few lines and can be identified by having
a Python version string in it. Such snippets add up; this combing pass
probably got rid of over 500 lines of code.

Comments (0)

Files changed (115)

QMTest/TestCmd.py

 # PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __author__ = "Steven Knight <knight at baldmt dot com>"
 __revision__ = "TestCmd.py 0.37.D001 2010/01/11 16:55:50 knight"
 
 _Cleanup = []
 
-_chain_to_exitfunc = None
-
 def _clean():
     global _Cleanup
     cleanlist = [_f for _f in _Cleanup if _f]
     cleanlist.reverse()
     for test in cleanlist:
         test.cleanup()
-    if _chain_to_exitfunc:
-        _chain_to_exitfunc()
-
-try:
-    import atexit
-except ImportError:
-    # TODO(1.5): atexit requires python 2.0, so chain sys.exitfunc
-    try:
-        _chain_to_exitfunc = sys.exitfunc
-    except AttributeError:
-        pass
-    sys.exitfunc = _clean
-else:
-    atexit.register(_clean)
+import atexit
+atexit.register(_clean)
 
 def _caller(tblist, skip):
     string = ""

QMTest/TestCommon.py

 # PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __author__ = "Steven Knight <knight at baldmt dot com>"
 __revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight"

QMTest/TestSCons.py

 """
 
 # __COPYRIGHT__
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
                 kw['arguments'] = option + arguments
             else:
                 kw['arguments'] = option + ' ' + arguments
-        # TODO(1.5)
-        #return self.run(**kw)
         return self.run(**kw)
 
     def diff_substr(self, expect, actual, prelen=20, postlen=40):
         if 'verbose' not in kw and not self.calibrate:
             kw['verbose'] = True
 
-        # TODO(1.5)
-        #TestSCons.__init__(self, *args, **kw)
         TestSCons.__init__(self, *args, **kw)
 
         # TODO(sgk):    better way to get the script dir than sys.argv[0]
                 options.append('%s=%s' % (variable, value))
             kw['options'] = ' '.join(options)
         if self.calibrate:
-            # TODO(1.5)
-            #self.calibration(*args, **kw)
             self.calibration(*args, **kw)
         else:
             self.uptime()
-            # TODO(1.5)
-            #self.startup(*args, **kw)
-            #self.full(*args, **kw)
-            #self.null(*args, **kw)
             self.startup(*args, **kw)
             self.full(*args, **kw)
             self.null(*args, **kw)
                    "seconds",
                    sort=0)
         for name, args in stats.items():
-            # TODO(1.5)
-            #self.trace(name, trace, *args)
             self.trace(name, trace, **args)
 
     def uptime(self):
         # won't report any statistics for it, but we can still execute
         # the full and null builds.
         kw['status'] = None
-        # TODO(1.5)
-        #self.run(*args, **kw)
         self.run(*args, **kw)
         sys.stdout.write(self.stdout())
         stats = self.collect_stats(self.stdout())
         """
         Runs a full build of SCons.
         """
-        # TODO(1.5)
-        #self.run(*args, **kw)
         self.run(*args, **kw)
         sys.stdout.write(self.stdout())
         stats = self.collect_stats(self.stdout())
         self.report_traces('full', stats)
-        # TODO(1.5)
-        #self.trace('full-memory', 'initial', **stats['memory-initial'])
-        #self.trace('full-memory', 'prebuild', **stats['memory-prebuild'])
-        #self.trace('full-memory', 'final', **stats['memory-final'])
         self.trace('full-memory', 'initial', **stats['memory-initial'])
         self.trace('full-memory', 'prebuild', **stats['memory-prebuild'])
         self.trace('full-memory', 'final', **stats['memory-final'])
         information (the variable(s) that were set for this configuration,
         and the elapsed time to run.
         """
-        # TODO(1.5)
-        #self.run(*args, **kw)
         self.run(*args, **kw)
         if self.variables:
             for variable, value in self.variables.items():
         """
         # TODO(sgk):  allow the caller to specify the target (argument)
         # that must be up-to-date.
-        # TODO(1.5)
-        #self.up_to_date(arguments='.', **kw)
-        kw = kw.copy()
-        kw['arguments'] = '.'
-        self.up_to_date(**kw)
+        self.up_to_date(arguments='.', **kw)
         sys.stdout.write(self.stdout())
         stats = self.collect_stats(self.stdout())
         # time-commands should always be 0.0 on a null build, because
         if float(stats['time-commands']['value']) == 0.0:
             del stats['time-commands']
         self.report_traces('null', stats)
-        # TODO(1.5)
-        #self.trace('null-memory', 'initial', **stats['memory-initial'])
-        #self.trace('null-memory', 'prebuild', **stats['memory-prebuild'])
-        #self.trace('null-memory', 'final', **stats['memory-final'])
         self.trace('null-memory', 'initial', **stats['memory-initial'])
         self.trace('null-memory', 'prebuild', **stats['memory-prebuild'])
         self.trace('null-memory', 'final', **stats['memory-final'])
         kw['options'] = kw.get('options', '') + ' --debug=memory --debug=time'
         self.startTime = time.time()
         try:
-            # TODO(1.5)
-            #result = TestSCons.run(self, *args, **kw)
             result = TestSCons.run(self, *args, **kw)
         finally:
             self.endTime = time.time()

QMTest/scons_tdb.py

 
 Thanks to Stefan Seefeld for the initial code.
 """
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

QMTest/unittest.py

 AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 """
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __author__ = "Steve Purcell (stephen_purcell@yahoo.com)"
 __version__ = "$ Revision: 1.23 $"[11:-2]
 EXECUTION REQUIREMENTS
 ======================
 
-Running SCons requires Python version 1.5.2 or later.  There should be
+Running SCons requires Python version 2.4 or later.  There should be
 no other dependencies or requirements to run SCons.
 
 The default SCons configuration assumes use of the Microsoft Visual C++
 INSTALLATION REQUIREMENTS
 =========================
 
-Building and installing SCons from this package requires the Python
-distutils package.  The distutils package was not shipped as a standard
-part of Python until Python version 1.6, so if your system is running
-Python 1.5.2, you may not have distutils installed.  If you are running
-Python version 1.6 or later, you should be fine.
-
-NOTE TO RED HAT USERS:  Red Hat shipped Python 1.5.2 as the default all
-the way up to Red Hat Linux 7.3, so you probably do *not* have distutils
-installed, unless you have already done so manually or are running Red
-Hat 8.0 or later.
-
-In this case, your options are:
-
-    --  (Optional.)  Install from a pre-packaged SCons package that
-        does not require distutils:
-
-            Red Hat Linux       scons-1.3.0.noarch.rpm
-
-            Debian GNU/Linux    use apt-get to get the official package
-
-            Windows             scons-1.3.0.win32.exe
-
-    --  (Recommended.)  Download the latest distutils package from the
-        following URL:
-
-            http://www.python.org/sigs/distutils-sig/download.html
-
-        Install the distutils according to the instructions on the page.
-        You can then proceed to the next section to install SCons from
-        this package.
+Nothing special.
 
 
 INSTALLATION
 EXECUTION REQUIREMENTS
 ======================
 
-Running SCons requires Python version 1.5.2 or later.  There should be
+Running SCons requires Python version 2.4 or later.  There should be
 no other dependencies or requirements to run SCons.
 
 The default SCons configuration assumes use of the Microsoft Visual C++
 # SConstruct file to build scons packages during development.
 #
 # See the README file for an overview of how SCons is built and tested.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 # When this gets changed, you must also change the copyright_years string
 # in QMTest/TestSCons.py so the test scripts look for the right string.
 #
 # This will allow (as much as possible) us to time just the code itself,
 # not Python function call overhead.
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 import getopt
 import sys

bench/is_types.py

 import types
 from UserDict import UserDict
 from UserList import UserList
-
-try:
-    from UserString import UserString
-except ImportError:
-    # "Borrowed" from the Python 2.2 UserString module
-    # and modified slightly for use with SCons.
-    class UserString:
-        def __init__(self, seq):
-            if isinstance(seq, str):
-                self.data = seq
-            elif isinstance(seq, UserString):
-                self.data = seq.data[:]
-            else:
-                self.data = str(seq)
-        def __str__(self): return str(self.data)
-        def __repr__(self): return repr(self.data)
-        def __int__(self): return int(self.data)
-        def __long__(self): return long(self.data)
-        def __float__(self): return float(self.data)
-        def __complex__(self): return complex(self.data)
-        def __hash__(self): return hash(self.data)
-
-        def __cmp__(self, s):
-            if isinstance(s, UserString):
-                return cmp(self.data, s.data)
-            else:
-                return cmp(self.data, s)
-        def __contains__(self, char):
-            return char in self.data
-
-        def __len__(self): return len(self.data)
-        def __getitem__(self, index): return self.__class__(self.data[index])
-        def __getslice__(self, start, end):
-            start = max(start, 0); end = max(end, 0)
-            return self.__class__(self.data[start:end])
-
-        def __add__(self, other):
-            if isinstance(other, UserString):
-                return self.__class__(self.data + other.data)
-            elif is_String(other):
-                return self.__class__(self.data + other)
-            else:
-                return self.__class__(self.data + str(other))
-        def __radd__(self, other):
-            if is_String(other):
-                return self.__class__(other + self.data)
-            else:
-                return self.__class__(str(other) + self.data)
-        def __mul__(self, n):
-            return self.__class__(self.data*n)
-        __rmul__ = __mul__
+from UserString import UserString
 
 InstanceType = types.InstanceType
 DictType = dict
 Note: there is a certain baseline overhead associated with executing a
 pass statement.  The code here doesn't try to hide it, but you should
 be aware of it.  The baseline overhead can be measured by invoking the
-program without arguments.
-
-The baseline overhead differs between Python versions!  Also, to
-fairly compare older Python versions to Python 2.3, you may want to
-use python -O for the older versions to avoid timing SET_LINENO
-instructions.
+program without arguments.  The baseline overhead differs between
+Python versions!
 """
 
 try:
 #
 # Module for handling SCons documentation processing.
 #
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __doc__ = """
 This module parses home-brew XML files that document various things

bin/install_python.py

 from Command import CommandRunner, Usage
 
 all_versions = [
-    #'1.5.2',   # no longer available at python.org
-    '2.0.1',
-    '2.1.3',
-    '2.2',
     '2.3.7',
     '2.4.5',
     #'2.5.2',
         tar_gz = os.path.join(downloads_dir, python + '.tgz')
         tar_gz_url = os.path.join(downloads_url, version, python + '.tgz')
 
-        if (version.startswith('1.5') or
-            version.startswith('1.6') or
-            version.startswith('2.0')):
-
-            configureflags = '--with-threads'
-
-        else:
-
-            configureflags = ''
-
         cmd.subst_dictionary(locals())
 
         if not os.path.exists(tar_gz):
 
         cmd.run('cd %(python)s')
 
-        if (version.startswith('1.6') or
-            version.startswith('2.0')):
-
-            def edit_modules_setup_in():
-                content = open('Modules/Setup.in', 'r').read()
-                content = content.replace('\n#zlib', '\nzlib')
-                open('Modules/Setup.in', 'w').write(content)
-
-            display = 'ed Modules/Setup.in <<EOF\ns/^#zlib/zlib/\nw\nq\nEOF\n'
-            cmd.run((edit_modules_setup_in,), display)
-
         cmd.run('./configure --prefix=%(prefix)s %(configureflags)s 2>&1 | tee configure.out')
         cmd.run('make 2>&1 | tee make.out')
         cmd.run('%(sudo)s make install')
 # in each category, the number of non-blank lines, and the number of
 # non-comment lines.  The last figure (non-comment) lines is the most
 # interesting one for most purposes.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 # Error output gets passed through to your error output so you
 # can see if there are any problems executing the command.
 #
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 import optparse
 import os
     return func(args[1:], c, t, dict)
 
 class MySGML(sgmllib.SGMLParser):
-    """A subclass of the standard Python 2.2 sgmllib SGML parser.
+    """A subclass of the standard Python sgmllib SGML parser.
 
     This extends the standard sgmllib parser to recognize, and do cool
     stuff with, the added tags that describe our SCons examples,
     commands, and other stuff.
-
-    Note that this doesn't work with the 1.5.2 sgmllib module, because
-    that didn't have the ability to work with ENTITY declarations.
     """
     def __init__(self, outfp):
         sgmllib.SGMLParser.__init__(self)

bin/sconsexamples.py

 # output from SCons, and insert it into the text as appropriate.
 # Error output gets passed through to your error output so you
 # can see if there are any problems executing the command.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 import os
 import os.path
 """
 
 class MySGML(sgmllib.SGMLParser):
-    """A subclass of the standard Python 2.2 sgmllib SGML parser.
-
-    Note that this doesn't work with the 1.5.2 sgmllib module, because
-    that didn't have the ability to work with ENTITY declarations.
+    """A subclass of the standard Python sgmllib SGML parser.
     """
     def __init__(self):
         sgmllib.SGMLParser.__init__(self)
 local SConstruct file.
 """
 
-try:
-    script_dir = os.path.abspath(os.path.dirname(__file__))
-except NameError:
-    # Pre-2.3 versions of Python don't have __file__.
-    script_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+script_dir = os.path.abspath(os.path.dirname(__file__))
 
 bootstrap_dir = os.path.join(script_dir, 'bootstrap')
 
 Section: devel
 Priority: optional
 Maintainer: Moshe Zadka <moshez@debian.org>
-Build-Depends-Indep: debhelper (>> 2.0.0), python-dev (>> 2.2)
+Build-Depends-Indep: debhelper (>> 2.0.0), python-dev (>> 2.4)
 Standards-Version: 3.5.6
 
 Package: scons
 Architecture: all
-Depends: python (>> 2.2)
+Depends: python (>> 2.4)
 Description: A replacement for Make
  SCons is an Open Source software construction tool--that is, a build
  tool; an improved substitute for the classic Make utility; a better
 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 import os.path
 import re
 does not exist.
 
 .B scons
-requires Python version 1.5.2 or later.
+requires Python version 2.4 or later.
 There should be no other dependencies or requirements to run
 .B scons.
 
 of the various classes used internally by SCons
 before and after reading the SConscript files
 and before and after building targets.
-This is not supported when run under Python versions earlier than 2.1,
-when SCons is executed with the Python
+This is not supported when SCons is executed with the Python
 .B -O
-(optimized) option,
+(optimized) option
 or when the SCons modules
 have been compiled with optimization
 (that is, when executing from
 an internal subsystem that counts
 how often SCons uses cached values in memory
 instead of recomputing them each time they're needed.
-Only available when using Python 2.2 or later.
 
 .TP
 --debug=memory
 --debug=objects
 Prints a list of the various objects
 of the various classes used internally by SCons.
-This only works when run under Python 2.1 or later.
 
 .TP
 --debug=pdb
 see the documentation for
 .B optparse
 for a thorough discussion of its option-processing capabities.
-(Note that although the
-.B optparse
-module was not a standard module until Python 2.3,
-.B scons
-contains a compatible version of the module
-that is used to provide identical functionality
-when run by earlier Python versions.)
 
 In addition to the arguments and values supported by the
 .B optparse.add_option ()
 .B SCons.dblite
 module that uses pickled
 Python data structures,
-and which works on all Python versions from 1.5.2 on.
+and which works on all Python versions.
 
 Examples:
 

doc/python10/process.xml

   <listitem>
     <para>
 
-      &SCons; will be written to Python version 1.5.2 (to ensure
+      &SCons; will be written to Python version 2.4 (to ensure
       usability by a wide install base).
 
     </para>

doc/user/build-install.in

 
     <para>
 
-    (Note that the <option>-V</option> option
-    was added to Python version 2.0,
-    so if your system only has an earlier version available
-    you may see an
-    <literal>"Unknown option: -V"</literal>
-    error message.)
-
-    </para>
-
-    <para>
-
     The standard location for information
     about downloading and installing Python is
     <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>.
 
     <para>
 
-    &SCons; will work with any version of Python from 1.5.2 or later.
+    &SCons; will work with any version of Python from 2.4 or later.
     If you need to install Python and have a choice,
-    we recommend using the most recent Python 2.5 version available.
-    Python 2.5 has significant improvements
+    we recommend using the most recent Python version available.
+    Newer Pythons have significant improvements
     that help speed up the performance of &SCons;.
 
     </para>

doc/user/build-install.xml

 
     <para>
 
-    (Note that the <option>-V</option> option
-    was added to Python version 2.0,
-    so if your system only has an earlier version available
-    you may see an
-    <literal>"Unknown option: -V"</literal>
-    error message.)
-
-    </para>
-
-    <para>
-
     The standard location for information
     about downloading and installing Python is
     <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>.
 
     <para>
 
-    &SCons; will work with any version of Python from 1.5.2 or later.
+    &SCons; will work with any version of Python from 2.4 or later.
     If you need to install Python and have a choice,
-    we recommend using the most recent Python 2.5 version available.
-    Python 2.5 has significant improvements
+    we recommend using the most recent Python version available.
+    Newer Pythons have significant improvements
     that help speed up the performance of &SCons;.
 
     </para>

doc/user/builders-built-in.in

         <scons_output_command>scons -Q .</scons_output_command>
       </scons_output>
 
-      <para>
-
-      If you're using Python version 1.5.2 to run &SCons;,
-      then &SCons; will try to use an external
-      &zip; program as follows:
-
-      </para>
-
-      <screen>
-        % <userinput>scons -Q .</userinput>
-        zip /home/my/project/zip.out file1 file2
-      </screen>
-
     </section>
 
   </section>

doc/user/builders-built-in.xml

         zip(["out.zip"], ["file1", "file2"])
       </screen>
 
-      <para>
-
-      If you're using Python version 1.5.2 to run &SCons;,
-      then &SCons; will try to use an external
-      &zip; program as follows:
-
-      </para>
-
-      <screen>
-        % <userinput>scons -Q .</userinput>
-        zip /home/my/project/zip.out file1 file2
-      </screen>
-
     </section>
 
   </section>
     <para>
 
     Although the &SCons; code itself will run 
-    on any Python version 1.5.2 or later,
+    on any Python version 2.4 or later,
     you are perfectly free to make use of
     Python syntax and modules from more modern versions
-    (for example, Python 2.4 or 2.5)
+    (for example, Python 2.5 or 2.6)
     when writing your &SConscript; files
     or your own local modules.
     If you do this, it's usually helpful to

doc/user/misc.xml

     <para>
 
     Although the &SCons; code itself will run 
-    on any Python version 1.5.2 or later,
+    on any Python version 2.4 or later,
     you are perfectly free to make use of
     Python syntax and modules from more modern versions
-    (for example, Python 2.4 or 2.5)
+    (for example, Python 2.5 or 2.6)
     when writing your &SConscript; files
     or your own local modules.
     If you do this, it's usually helpful to

doc/user/tasks.in

 filenames = [os.path.join(prefix, x) for x in filenames]
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-import os.path
-new_filenames = [] 
-for x in filenames:
-    new_filenames.append(os.path.join(prefix, x))
-</programlisting>
-</example>
-
 <example>
 <title>Substituting a path prefix with another one</title>
 <programlisting>
     filename = filename.replace(old_prefix, new_prefix)
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-if filename.find(old_prefix) == 0:
-    filename = filename.replace(old_prefix, new_prefix)      
-</programlisting>
-</example>
-
 <example>
 <title>Filtering a filename list to exclude/retain only a specific set
 of extensions</title>
 filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions]
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-import os.path
-new_filenames = []
-for x in filenames:
-    if os.path.splitext(x)[1] in extensions:
-        new_filenames.append(x)
-</programlisting>
-</example>
-
 <example>
 <title>The "backtick function": run a shell command and capture the
 output</title>

doc/user/tasks.xml

 filenames = [os.path.join(prefix, x) for x in filenames]
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-import os.path
-new_filenames = [] 
-for x in filenames:
-    new_filenames.append(os.path.join(prefix, x))
-</programlisting>
-</example>
-
 <example>
 <title>Substituting a path prefix with another one</title>
 <programlisting>
     filename = filename.replace(old_prefix, new_prefix)
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-if filename.find(old_prefix) == 0:
-    filename = filename.replace(old_prefix, new_prefix)      
-</programlisting>
-</example>
-
 <example>
 <title>Filtering a filename list to exclude/retain only a specific set
 of extensions</title>
 filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions]
 </programlisting>
 
-<simpara>or in Python 1.5.2:</simpara>
-
-<programlisting>
-import os.path
-new_filenames = []
-for x in filenames:
-    if os.path.splitext(x)[1] in extensions:
-        new_filenames.append(x)
-</programlisting>
-</example>
-
 <example>
 <title>The "backtick function": run a shell command and capture the
 output</title>

gentoo/scons.ebuild.in

 LICENSE="as-is"
 KEYWORDS="~x86 ~sparc"
 
-DEPEND=">=dev-lang/python-2.0"
+DEPEND=">=dev-lang/python-2.4"
 
 src_compile() {
         python setup.py build

rpm/scons.spec.in

 BuildArchitectures: noarch
 Vendor: Steven Knight <knight@scons.org>
 Packager: Steven Knight <knight@scons.org>
-Requires: python >= 1.5
+Requires: python >= 2.4
 Url: http://www.scons.org/
 
 %description
 # library directory.  If we ever resurrect that as the default, then
 # you can find the appropriate code in the 0.04 version of this script,
 # rather than reinventing that wheel.)
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 import getopt
 import glob
 EXECUTION REQUIREMENTS
 ======================
 
-Running SCons requires Python version 1.5.2 or later.  There should be
+Running SCons requires Python version 2.4 or later.  There should be
 no other dependencies or requirements to run SCons.  (There is, however,
 an additional requirement to *install* SCons from this particular
 package; see the next section.)
 INSTALLATION REQUIREMENTS
 =========================
 
-Installing SCons from this package requires the Python distutils
-package.  The distutils package was not shipped as a standard part of
-Python until Python version 1.6, so if your system is running Python
-1.5.2, you may not have distutils installed.  If you are running
-Python version 1.6 or later, you should be fine.
-
-NOTE TO RED HAT USERS:  Red Hat shipped Python 1.5.2 as the default all
-the way up to Red Hat Linux 7.3, so you probably do *not* have distutils
-installed, unless you have already done so manually or are running Red
-Hat 8.0 or later.
-
-In this case, your options are:
-
-    --  (Recommended.)  Install from a pre-packaged SCons package that
-        does not require distutils:
-
-            Red Hat Linux       scons-__VERSION__-1.noarch.rpm
-
-            Debian GNU/Linux    scons___VERSION__-1_all.deb
-                                (or use apt-get)
-
-            Windows             scons-__VERSION__.win32.exe
-
-    --  (Optional.)  Download the latest distutils package from the
-        following URL:
-
-            http://www.python.org/sigs/distutils-sig/download.html
-
-        Install the distutils according to the instructions on the page.
-        You can then proceed to the next section to install SCons from
-        this package.
+Nothing special.
 
 
 INSTALLATION

src/engine/SCons/Action.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
         return act
 
     if is_List(act):
-        #TODO(1.5) return CommandAction(act, **kw)
         return CommandAction(act, **kw)
 
     if callable(act):
             return LazyAction(var, kw)
         commands = str(act).split('\n')
         if len(commands) == 1:
-            #TODO(1.5) return CommandAction(commands[0], **kw)
             return CommandAction(commands[0], **kw)
         # The list of string commands may include a LazyAction, so we
         # reprocess them via _do_create_list_action.
         # variables.
         if __debug__: logInstanceCreation(self, 'Action.CommandAction')
 
-        #TODO(1.5) _ActionAction.__init__(self, **kw)
         _ActionAction.__init__(self, **kw)
         if is_List(cmd):
             if list(filter(is_List, cmd)):
                              source=source,
                              env=env,
                              for_signature=for_signature)
-        #TODO(1.5) gen_cmd = Action(ret, **self.gen_kw)
         gen_cmd = Action(ret, **self.gen_kw)
         if not gen_cmd:
             raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret))
             c = env.get(self.var, '')
         else:
             c = ''
-        #TODO(1.5) gen_cmd = Action(c, **self.gen_kw)
         gen_cmd = Action(c, **self.gen_kw)
         if not gen_cmd:
             raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c)))
                 # This is weird, just do the best we can.
                 self.funccontents = _object_contents(execfunction)
 
-        #TODO(1.5) _ActionAction.__init__(self, **kw)
         _ActionAction.__init__(self, **kw)
 
     def function_name(self):
     def __call__(self, target, source, env, executor=None):
         args = self.subst_args(target, source, env)
         kw = self.subst_kw(target, source, env)
-        #TODO(1.5) return self.parent.actfunc(*args, **kw)
         return self.parent.actfunc(*args, **kw)
 
     def strfunction(self, target, source, env):
         args = self.subst_args(target, source, env)
         kw = self.subst_kw(target, source, env)
-        #TODO(1.5) return self.parent.strfunc(*args, **kw)
         return self.parent.strfunc(*args, **kw)
 
     def __str__(self):
-        #TODO(1.5) return self.parent.strfunc(*self.args, **self.kw)
         return self.parent.strfunc(*self.args, **self.kw)
 
 class ActionFactory:

src/engine/SCons/ActionTests.py

         def f_global(target, source, env, for_signature):
             return SCons.Action.Action(GlobalFunc)
 
-        # TODO(1.5):
-        #def f_local(target, source, env, for_signature):
-        def f_local(target, source, env, for_signature, LocalFunc=LocalFunc):
+        def f_local(target, source, env, for_signature):
             return SCons.Action.Action(LocalFunc)
 
         env = Environment(XYZ = 'foo')
         def f_global(target, source, env, for_signature):
             return SCons.Action.Action(GlobalFunc, varlist=['XYZ'])
 
-        # TODO(1.5):
-        #def f_local(target, source, env, for_signature):
-        def f_local(target, source, env, for_signature, LocalFunc=LocalFunc):
+        def f_local(target, source, env, for_signature):
             return SCons.Action.Action(LocalFunc, varlist=['XYZ'])
 
         matches_foo = [x + "foo" for x in func_matches]

src/engine/SCons/Builder.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/BuilderTests.py

         tgt.build()
         assert env['CNT'][0] == 2
         tgts = builder(env, None, infiles[2:4])
-        try:
-            [].extend(collections.UserList())
-        except TypeError:
-            # Old Python version (1.5.2) that can't handle extending
-            # a list with list-like objects.  That means the return
-            # value from the builder call is a real list with Nodes,
-            # and doesn't have a __str__() method that stringifies
-            # the individual elements.  Since we're gong to drop 1.5.2
-            # support anyway, don't bother trying to test for it.
-            pass
-        else:
-            s = list(map(str, tgts))
-            expect = [test.workpath('2.out'), test.workpath('3.out')]
-            expect = list(map(os.path.normcase, expect))
-            assert list(map(os.path.normcase, s)) == expect, s
+        s = list(map(str, tgts))
+        expect = [test.workpath('2.out'), test.workpath('3.out')]
+        expect = list(map(os.path.normcase, expect))
+        assert list(map(os.path.normcase, s)) == expect, s
         for t in tgts: t.prepare()
         tgts[0].build()
         tgts[1].build()

src/engine/SCons/Debug.py

 """SCons.Debug
 
-Code for debugging SCons internal things.  Not everything here is
-guaranteed to work all the way back to Python 1.5.2, and shouldn't be
+Code for debugging SCons internal things.  Shouldn't be
 needed by most users.
 
 """
 import os
 import sys
 import time
-
-# Recipe 14.10 from the Python Cookbook.
-try:
-    import weakref
-except ImportError:
-    def logInstanceCreation(instance, name=None):
-        pass
-else:
-    def logInstanceCreation(instance, name=None):
-        if name is None:
-            name = instance.__class__.__name__
-        if name not in tracked_classes:
-            tracked_classes[name] = []
-        tracked_classes[name].append(weakref.ref(instance))
-
-
+import weakref
 
 tracked_classes = {}
 
+def logInstanceCreation(instance, name=None):
+    if name is None:
+        name = instance.__class__.__name__
+    if name not in tracked_classes:
+        tracked_classes[name] = []
+    tracked_classes[name].append(weakref.ref(instance))
+
 def string_to_classes(s):
     if s == '*':
         return sorted(tracked_classes.keys())
         mstr = open('/proc/self/stat').read()
         mstr = mstr.split()[22]
         return int(mstr)
+elif sys.platform[:6] == 'darwin':
+    #TODO really get memory stats for OS X
+    def memory():
+        return 0
 else:
     try:
         import resource

src/engine/SCons/Environment.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
         # list works a little better in Python 2.5, but that has the
         # disadvantage of maybe getting out of sync if we ever add more
         # variable names.  Using self._special_set.has_key() works a
-        # little better in Python 2.4, but is worse then this test.
+        # little better in Python 2.4, but is worse than this test.
         # So right now it seems like a good trade-off, but feel free to
         # revisit this with bench/env.__setitem__.py as needed (and
         # as newer versions of Python come out).
         # othewise force a shell
         if not SCons.Util.is_List(command): kw['shell'] = True
         # run constructed command
-        #TODO(1.5) p = SCons.Action._subproc(self, command, **kw)
         p = SCons.Action._subproc(self, command, **kw)
         out,err = p.communicate()
         status = p.wait()
             'RPATH'         : [],
         }
 
-        # The use of the "me" parameter to provide our own name for
-        # recursion is an egregious hack to support Python 2.1 and before.
-        def do_parse(arg, me, self = self, dict = dict):
+        def do_parse(arg):
             # if arg is a sequence, recurse with each element
             if not arg:
                 return
 
             if not SCons.Util.is_String(arg):
-                for t in arg: me(t, me)
+                for t in arg: do_parse(t)
                 return
 
             # if arg is a command, execute it
                     dict['CCFLAGS'].append(arg)
     
         for arg in flags:
-            do_parse(arg, do_parse)
+            do_parse(arg)
         return dict
 
     def MergeFlags(self, args, unique=1, dict=None):
 #                 self.AppendENVPath(pathname, pathval)
 
 
-# Used by the FindSourceFiles() method, below.
-# Stuck here for support of pre-2.2 Python versions.
-def build_source(ss, result):
-    for s in ss:
-        if isinstance(s, SCons.Node.FS.Dir):
-            build_source(s.all_children(), result)
-        elif s.has_builder():
-            build_source(s.sources, result)
-        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
-            result.append(s)
-
 def default_decide_source(dependency, target, prev_ni):
     f = SCons.Defaults.DefaultEnvironment().decide_source
     return f(dependency, target, prev_ni)
         for line in lines:
             try:
                 target, depends = line.split(':', 1)
-            except (AttributeError, TypeError, ValueError):
-                # Python 1.5.2 throws TypeError if line isn't a string,
-                # Python 2.x throws AttributeError because it tries
-                # to call line.split().  Either can throw ValueError
-                # if the line doesn't split into two or more elements.
+            except (AttributeError, ValueError):
+                # Throws AttributeError if line isn't a string.  Can throw
+                # ValueError if line doesn't split into two or more elements.
                 pass
             else:
                 tdlist.append((target.split(), depends.split()))
         node = self.arg2nodes(node, self.fs.Entry)[0]
 
         sources = []
-        # Uncomment this and get rid of the global definition when we
-        # drop support for pre-2.2 Python versions.
-        #def build_source(ss, result):
-        #    for s in ss:
-        #        if isinstance(s, SCons.Node.FS.Dir):
-        #            build_source(s.all_children(), result)
-        #        elif s.has_builder():
-        #            build_source(s.sources, result)
-        #        elif isinstance(s.disambiguate(), SCons.Node.FS.File):
-        #            result.append(s)
-        build_source(node.all_children(), sources)
+        def build_source(ss):
+            for s in ss:
+                if isinstance(s, SCons.Node.FS.Dir):
+                    build_source(s.all_children())
+                elif s.has_builder():
+                    build_source(s.sources)
+                elif isinstance(s.disambiguate(), SCons.Node.FS.File):
+                    sources.append(s)
+        build_source(node.all_children())
 
     # THIS CODE APPEARS TO HAVE NO EFFECT
     #    # get the final srcnode for all nodes, this means stripping any

src/engine/SCons/EnvironmentTests.py

     def test_contains(self):
         """Test the SubstitutionEnvironment __contains__() method
         """
-        try:
-            'x' in {'x':1}
-        except TypeError:
-            # TODO(1.5)
-            # An early version of Python that doesn't support "in"
-            # on dictionaries.  Just pass the test.
-            pass
-        else:
-            env = SubstitutionEnvironment(XXX = 'x')
-            assert 'XXX' in env
-            assert not 'YYY' in env
+        env = SubstitutionEnvironment(XXX = 'x')
+        assert 'XXX' in env
+        assert not 'YYY' in env
 
     def test_items(self):
         """Test the SubstitutionEnvironment items() method
         env['CLVar'] = CLVar([])
         env.AppendUnique(CLVar = 'bar')
         result = env['CLVar']
-        if sys.version[0] == '1' or sys.version[:3] == '2.0':
-            # Python 2.0 and before have a quirky behavior where CLVar([])
-            # actually matches '' and [] due to different __coerce__()
-            # semantics in the UserList implementation.  It isn't worth a
-            # lot of effort to get this corner case to work identically
-            # (support for Python 1.5 support will die soon anyway),
-            # so just treat it separately for now.
-            assert result == 'bar', result
-        else:
-            assert isinstance(result, CLVar), repr(result)
-            assert result == ['bar'], result
+        assert isinstance(result, CLVar), repr(result)
+        assert result == ['bar'], result
 
         env['CLVar'] = CLVar(['abc'])
         env.AppendUnique(CLVar = 'bar')
         env['CLVar'] = CLVar([])
         env.PrependUnique(CLVar = 'bar')
         result = env['CLVar']
-        if sys.version[0] == '1' or sys.version[:3] == '2.0':
-            # Python 2.0 and before have a quirky behavior where CLVar([])
-            # actually matches '' and [] due to different __coerce__()
-            # semantics in the UserList implementation.  It isn't worth a
-            # lot of effort to get this corner case to work identically
-            # (support for Python 1.5 support will die soon anyway),
-            # so just treat it separately for now.
-            assert result == 'bar', result
-        else:
-            assert isinstance(result, CLVar), repr(result)
-            assert result == ['bar'], result
+        assert isinstance(result, CLVar), repr(result)
+        assert result == ['bar'], result
 
         env['CLVar'] = CLVar(['abc'])
         env.PrependUnique(CLVar = 'bar')
 
     def test_contains(self):
         """Test the OverrideEnvironment __contains__() method"""
-        try:
-            'x' in {'x':1}
-        except TypeError:
-            # TODO(1.5)
-            # An early version of Python that doesn't support "in"
-            # on dictionaries.  Just pass the test.
-            pass
-        else:
-            env, env2, env3 = self.envs
-            assert 'XXX' in env
-            assert 'XXX' in env2
-            assert 'XXX' in env3
-            assert 'YYY' in env
-            assert 'YYY' in env2
-            assert 'YYY' in env3
-            assert not 'ZZZ' in env
-            assert not 'ZZZ' in env2
-            assert 'ZZZ' in env3
+        env, env2, env3 = self.envs
+        assert 'XXX' in env
+        assert 'XXX' in env2
+        assert 'XXX' in env3
+        assert 'YYY' in env
+        assert 'YYY' in env2
+        assert 'YYY' in env3
+        assert not 'ZZZ' in env
+        assert not 'ZZZ' in env2
+        assert 'ZZZ' in env3
 
     def test_items(self):
         """Test the OverrideEnvironment Dictionary() method"""

src/engine/SCons/Errors.py

             status=status,      # might be 0, OK here
             exitstatus=status,      # might be 0, OK here
             exc_info=exc_info)
-    # TODO(1.5):
-    #elif isinstance(status, (StopError, UserError)):
-    elif isinstance(status, StopError) or isinstance(status, UserError):
+    elif isinstance(status, (StopError, UserError)):
         buildError = BuildError(
             errstr=str(status),
             status=2,

src/engine/SCons/Executor.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
         """Returns all targets for all batches of this Executor."""
         result = []
         for batch in self.batches:
-            # TODO(1.5):  remove the list() cast
-            result.extend(list(batch.targets))
+            result.extend(batch.targets)
         return result
 
     def get_all_sources(self):
         """Returns all sources for all batches of this Executor."""
         result = []
         for batch in self.batches:
-            # TODO(1.5):  remove the list() cast
-            result.extend(list(batch.sources))
+            result.extend(batch.sources)
         return result
 
     def get_all_children(self):
         """
         result = SCons.Util.UniqueList([])
         for target in self.get_all_targets():
-            # TODO(1.5):  remove the list() cast
-            result.extend(list(target.prerequisites))
+            result.extend(target.prerequisites)
         return result
 
     def get_action_side_effects(self):

src/engine/SCons/Job.py

                 worker = Worker(self.requestQueue, self.resultsQueue, interrupted)
                 self.workers.append(worker)
 
-            # Once we drop Python 1.5 we can change the following to:
-            #if 'prev_size' in locals():
-            if 'prev_size' in locals().keys():
+            if 'prev_size' in locals():
                 threading.stack_size(prev_size)
 
         def put(self, task):

src/engine/SCons/JobTests.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/Node/FS.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import stat
 import sys
 import time
-
-try:
-    import codecs
-except ImportError:
-    pass
-else:
-    # TODO(2.2):  Remove when 2.3 becomes the minimal supported version.
-    try:
-        codecs.BOM_UTF8
-    except AttributeError:
-        codecs.BOM_UTF8 = '\xef\xbb\xbf'
-    try:
-        codecs.BOM_UTF16_LE
-        codecs.BOM_UTF16_BE
-    except AttributeError:
-        codecs.BOM_UTF16_LE = '\xff\xfe'
-        codecs.BOM_UTF16_BE = '\xfe\xff'
-
-    # Provide a wrapper function to handle decoding differences in
-    # different versions of Python.  Normally, we'd try to do this in the
-    # compat layer (and maybe it still makes sense to move there?) but
-    # that doesn't provide a way to supply the string class used in
-    # pre-2.3 Python versions with a .decode() method that all strings
-    # naturally have.  Plus, the 2.[01] encodings behave differently
-    # enough that we have to settle for a lowest-common-denominator
-    # wrapper approach.
-    #
-    # Note that the 2.[012] implementations below may be inefficient
-    # because they perform an explicit look up of the encoding for every
-    # decode, but they're old enough (and we want to stop supporting
-    # them soon enough) that it's not worth complicating the interface.
-    # Think of it as additional incentive for people to upgrade...
-    try:
-        ''.decode
-    except AttributeError:
-        # 2.0 through 2.2:  strings have no .decode() method
-        try:
-            codecs.lookup('ascii').decode
-        except AttributeError:
-            # 2.0 and 2.1:  encodings are a tuple of functions, and the
-            # decode() function returns a (result, length) tuple.
-            def my_decode(contents, encoding):
-                return codecs.lookup(encoding)[1](contents)[0]
-        else:
-            # 2.2:  encodings are an object with methods, and the
-            # .decode() method returns just the decoded bytes.
-            def my_decode(contents, encoding):
-                return codecs.lookup(encoding).decode(contents)
-    else:
-        # 2.3 or later:  use the .decode() string method
-        def my_decode(contents, encoding):
-            return contents.decode(encoding)
+import codecs
 
 import SCons.Action
 from SCons.Debug import logInstanceCreation
     def Dirs(self, pathlist):
         """Create a list of directories relative to the SConscript
         directory of this file."""
-        # TODO(1.5)
-        # return [self.Dir(p) for p in pathlist]
         return [self.Dir(p) for p in pathlist]
 
     def File(self, name):
             raise
         return contents
 
-    try:
-        import codecs
-    except ImportError:
-        get_text_contents = get_contents
-    else:
-        # This attempts to figure out what the encoding of the text is
-        # based upon the BOM bytes, and then decodes the contents so that
-        # it's a valid python string.
-        def get_text_contents(self):
-            contents = self.get_contents()
-            # The behavior of various decode() methods and functions
-            # w.r.t. the initial BOM bytes is different for different
-            # encodings and/or Python versions.  ('utf-8' does not strip
-            # them, but has a 'utf-8-sig' which does; 'utf-16' seems to
-            # strip them; etc.)  Just side step all the complication by
-            # explicitly stripping the BOM before we decode().
-            if contents.startswith(codecs.BOM_UTF8):
-                contents = contents[len(codecs.BOM_UTF8):]
-                # TODO(2.2):  Remove when 2.3 becomes floor.
-                #contents = contents.decode('utf-8')
-                contents = my_decode(contents, 'utf-8')
-            elif contents.startswith(codecs.BOM_UTF16_LE):
-                contents = contents[len(codecs.BOM_UTF16_LE):]
-                # TODO(2.2):  Remove when 2.3 becomes floor.
-                #contents = contents.decode('utf-16-le')
-                contents = my_decode(contents, 'utf-16-le')
-            elif contents.startswith(codecs.BOM_UTF16_BE):
-                contents = contents[len(codecs.BOM_UTF16_BE):]
-                # TODO(2.2):  Remove when 2.3 becomes floor.
-                #contents = contents.decode('utf-16-be')
-                contents = my_decode(contents, 'utf-16-be')
-            return contents
+    # This attempts to figure out what the encoding of the text is
+    # based upon the BOM bytes, and then decodes the contents so that
+    # it's a valid python string.
+    def get_text_contents(self):
+        contents = self.get_contents()
+        # The behavior of various decode() methods and functions
+        # w.r.t. the initial BOM bytes is different for different
+        # encodings and/or Python versions.  ('utf-8' does not strip
+        # them, but has a 'utf-8-sig' which does; 'utf-16' seems to
+        # strip them; etc.)  Just sidestep all the complication by
+        # explicitly stripping the BOM before we decode().
+        if contents.startswith(codecs.BOM_UTF8):
+            return contents[len(codecs.BOM_UTF8):].decode('utf-8')
+        if contents.startswith(codecs.BOM_UTF16_LE):
+            return contents[len(codecs.BOM_UTF16_LE):].decode('utf-16-le')
+        if contents.startswith(codecs.BOM_UTF16_BE):
+            return contents[len(codecs.BOM_UTF16_BE):].decode('utf-16-be')
+        return contents
 
     def get_content_hash(self):
         """
             #    if isinstance(node, Dir) or isinstance(node, Entry):
             #        return node
             #    return None
-            #paths = filter(None, map(filedir_lookup, paths))
+            #paths = [_f for _f in map(filedir_lookup, paths) if _f]
 
             self.default_filedir = filedir
             paths = [_f for _f in map(self.filedir_lookup, paths) if _f]

src/engine/SCons/Node/FSTests.py

         f1 = fs.File(test.workpath("binary_file"))
         assert f1.get_contents() == "Foo\x1aBar", f1.get_contents()
 
-        try:
-            # TODO(1.5)
-            eval('test_string = u"Foo\x1aBar"')
-        except SyntaxError:
-            pass
-        else:
-            # This tests to make sure we can decode UTF-8 text files.
-            test.write("utf8_file", test_string.encode('utf-8'))
-            f1 = fs.File(test.workpath("utf8_file"))
-            assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \
-                   f1.get_text_contents()
+        # This tests to make sure we can decode UTF-8 text files.
+        test_string = u"Foo\x1aBar"
+        test.write("utf8_file", test_string.encode('utf-8'))
+        f1 = fs.File(test.workpath("utf8_file"))
+        assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \
+               f1.get_text_contents()
 
         def nonexistent(method, s):
             try:
         e = self.fs.Dir(os.path.join('d', 'empty'))
         s = self.fs.Dir(os.path.join('d', 'sub'))
 
-        #TODO(1.5) files = d.get_contents().split('\n')
         files = d.get_contents().split('\n')
 
         assert e.get_contents() == '', e.get_contents()

src/engine/SCons/Node/NodeTests.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
         l = [1]
         ul = collections.UserList([2])
-        try:
-            l.extend(ul)
-        except TypeError:
-            # An older version of Python (*cough* 1.5.2 *cough*)
-            # that doesn't allow UserList objects to extend lists.
-            pass
-        else:
-            s = str(nl)
-            assert s == "['n3', 'n2', 'n1']", s
+        s = str(nl)
+        assert s == "['n3', 'n2', 'n1']", s
 
         r = repr(nl)
         r = re.sub('at (0[xX])?[0-9a-fA-F]+', 'at 0x', r)

src/engine/SCons/Node/__init__.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
             lines = ["%s:\n" % preamble] + lines
             return ( ' '*11).join(lines)
 
-try:
-    [].extend(collections.UserList([]))
-except TypeError:
-    # Python 1.5.2 doesn't allow a list to be extended by list-like
-    # objects (such as UserList instances), so just punt and use
-    # real lists.
-    def NodeList(l):
-        return l
-else:
-    class NodeList(collections.UserList):
-        def __str__(self):
-            return str(list(map(str, self.data)))
+class NodeList(collections.UserList):
+    def __str__(self):
+        return str(list(map(str, self.data)))
 
 def get_children(node, parent): return node.children()
 def ignore_cycle(node, stack): pass

src/engine/SCons/SConf.py

     return (str(target[0]) + ' <-\n  |' +
             source[0].get_contents().replace( '\n', "\n  |" ) )
 
-# python 2.2 introduces bool
-BooleanTypes = [int, bool]
-
 class SConfBuildInfo(SCons.Node.FS.FileBuildInfo):
     """
     Special build info for targets of configure tests. Additional members
         string. In case of an integer, the written text will be 'yes' or 'no'.
         The result is only displayed when self.did_show_result is not set.
         """
-        if type(res) in BooleanTypes:
+        if isinstance(res, (int, bool)):
             if res:
                 text = "yes"
             else:

src/engine/SCons/Scanner/Dir.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/Scanner/Fortran.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/Scanner/LaTeX.py

     env.PrependENVPath(var, abspath)
     try:
         if SCons.Util.is_List(env[var]):
-            #TODO(1.5)
-            #env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]])
             env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]])
         else:
             # Split at os.pathsep to convert into absolute path
-            #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)])
             env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)])
     except KeyError:
         pass
     # does not work, refuses to append ":" (os.pathsep).
 
     if SCons.Util.is_List(env['ENV'][var]):
-        # TODO(1.5)
-        #env['ENV'][var] = os.pathsep.join(env['ENV'][var])
         env['ENV'][var] = os.pathsep.join(env['ENV'][var])
     # Append the trailing os.pathsep character here to catch the case with no env[var]
     env['ENV'][var] = env['ENV'][var] + os.pathsep
         if include[0] == 'includegraphics':
             base, ext = os.path.splitext( filename )
             if ext == "":
-                #TODO(1.5) return [filename + e for e in self.graphics_extensions]
-                #return map(lambda e: filename+e, self.graphics_extensions + TexGraphics)
-                # use the line above to find dependency for PDF builder when only .eps figure is present
-                # Since it will be found if the user tell scons how to make the pdf figure leave it out for now.
+                #return [filename+e for e in self.graphics_extensions + TexGraphics]
+                # use the line above to find dependencies for the PDF builder
+                # when only an .eps figure is present.  Since it will be found
+                # if the user tells scons how to make the pdf figure, leave
+                # it out for now.
                 return [filename+e for e in self.graphics_extensions]
         return [filename]
 
         while queue:
             
             include = queue.pop()
-            # TODO(1.5):  more compact:
-            #try:
-            #    if seen[include[1]] == 1:
-            #        continue
-            #except KeyError:
-            #    seen[include[1]] = 1
             try:
-                already_seen = seen[include[1]]
+                if seen[include[1]] == 1:
+                    continue
             except KeyError:
                 seen[include[1]] = 1
-                already_seen = False
-            if already_seen:
-                continue
 
             #
             # Handle multiple filenames in include[1]

src/engine/SCons/Scanner/ScannerTests.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
             assert n == 'path/bbb', n
             assert i == 'bbb', i
 
-            # TODO(1.5):  remove when 2.2 is minimal; replace ccc
-            # variable in find_include() call below with in-line u'ccc'.
-            try:
-                ccc = eval("u'ccc'")
-            except SyntaxError:
-                ccc = 'ccc'
-
-            n, i = s.find_include(('<', ccc), 'foo', ('path',))
+            n, i = s.find_include(('<', u'ccc'), 'foo', ('path',))
             assert n == 'path/ccc', n
             assert i == 'ccc', i
 

src/engine/SCons/Script/Interactive.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/Script/Main.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
         sys.stderr.write(errfmt % (nodename, buildError))
 
         if (buildError.exc_info[2] and buildError.exc_info[1] and 
-           # TODO(1.5)
-           #not isinstance(
-           #    buildError.exc_info[1], 
-           #    (EnvironmentError, SCons.Errors.StopError, SCons.Errors.UserError))):
-           not isinstance(buildError.exc_info[1], EnvironmentError) and
-           not isinstance(buildError.exc_info[1], SCons.Errors.StopError) and
-           not isinstance(buildError.exc_info[1], SCons.Errors.UserError)):
+           not isinstance(
+               buildError.exc_info[1], 
+               (EnvironmentError, SCons.Errors.StopError,
+                            SCons.Errors.UserError))):
             type, value, trace = buildError.exc_info
             traceback.print_exception(type, value, trace)
         elif tb and print_stacktrace:

src/engine/SCons/Script/SConsOptions.py

 import sys
 import textwrap
 
-try:
-    no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')
-except re.error:
-    # Pre-2.0 Python versions don't have the (?<= negative
-    # look-behind assertion.
-    no_hyphen_re = re.compile(r'(\s+|-*\w{2,}-(?=\w{2,}))')
+no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')
 
 try:
     from gettext import gettext

src/engine/SCons/Script/SConscript.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 

src/engine/SCons/Script/__init__.py

     try:
         SCons.Memoize.EnableMemoization()
     except SCons.Warnings.Warning:
-        # Some warning was thrown (inability to --debug=memoizer on
-        # Python 1.5.2 because it doesn't have metaclasses).  Arrange
-        # for it to be displayed or not after warnings are configured.
+        # Some warning was thrown.  Arrange for it to be displayed
+        # or not after warnings are configured.
         import Main
         exc_type, exc_value, tb = sys.exc_info()
         Main.delayed_warnings.append((exc_type, exc_value))

src/engine/SCons/Subst.py

 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-from __future__ import generators  ### KEEP FOR COMPATIBILITY FIXERS
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 class NullNodeList(SCons.Util.NullSeq):
   def __call__(self, *args, **kwargs): return ''
   def __str__(self): return ''
-  # TODO(1.5):  unneeded after new-style classes introduce iterators
-  def __getitem__(self, i):
-      raise IndexError
 
 NullNodesList = NullNodeList()
 
             if is_String(args) and not isinstance(args, CmdStringHolder):
                 args = str(args)        # In case it's a UserString.
                 try:
-                    def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars):
-                        return conv(expand(match.group(1), lvars))
+                    def sub_match(match):
+                        return self.conv(self.expand(match.group(1), lvars))
                     result = _dollar_exps.sub(sub_match, args)
                 except TypeError:
                     # If the internal conversion routine doesn't return

src/engine/SCons/SubstTests.py

             scons_subst('$foo.bar.3.0', env)
         except SCons.Errors.UserError, e:
             expect = [
-                # Python 1.5
-                "SyntaxError `invalid syntax' trying to evaluate `$foo.bar.3.0'",
-                # Python 2.2, 2.3, 2.4
+                # Python 2.3, 2.4
                 "SyntaxError `invalid syntax (line 1)' trying to evaluate `$foo.bar.3.0'",
                 # Python 2.5
                 "SyntaxError `invalid syntax (<string>, line 1)' trying to evaluate `$foo.bar.3.0'",
             scons_subst("${NONE[2]}", env, gvars={'NONE':None})
         except SCons.Errors.UserError, e:
             expect = [
-                # Python 1.5, 2.2, 2.3, 2.4
+                # Python 2.3, 2.4
                 "TypeError `unsubscriptable object' trying to evaluate `${NONE[2]}'",
                 # Python 2.5 and later
                 "TypeError `'NoneType' object is unsubscriptable' trying to evaluate `${NONE[2]}'",
             scons_subst("${func(1)}", env, gvars={'func':func})
         except SCons.Errors.UserError, e:
             expect = [
-                # Python 1.5