[Python-checkins] distutils2: Fix the backport fixes.

eric.araujo python-checkins at python.org
Mon Sep 19 15:12:39 CEST 2011


http://hg.python.org/distutils2/rev/12f3ba3cbac2
changeset:   1148:12f3ba3cbac2
user:        Éric Araujo <merwok at netwok.org>
date:        Sun Sep 18 20:20:13 2011 +0200
summary:
  Fix the backport fixes.

Backports:
- sysconfig is now always imported from our backports
- when hashlib is not found, our backport is used instead of the md5
  module (debatable; we could just drop hashlib)

Version-dependent features:
- PEP 370 features are only enabled for 2.6+
- the check for sys.dont_write_bytecode was fixed to use getattr
  with a default value instead of hasattr

Idioms/syntax:
- octal literals lost their extra 0
- misused try/except blocks have been changed back to try/finally
  (it’s legal in 2.4 too, it’s only try/except/finally that isn’t)
- exception catching uses the regular 2.x idiom instead of sys.exc_info
- file objects are closed within finally blocks (this causes much
  whitespace changes but actually makes diff with packaging easier)

Renamed modules:
- some missed renamings (_thread, Queue, isAlive, urllib.urlsplit, etc.)
  were fixed

Other:
- a few false positive replacements of “packaging” by “distutils2” in
  comments or docstrings were reverted
- util.is_packaging regained its name
- assorted whitespace/comment/import changes to match packaging

files:
  distutils2/__init__.py                       |    2 +-
  distutils2/_backport/tests/test_sysconfig.py |    3 +-
  distutils2/command/__init__.py               |    5 +-
  distutils2/command/bdist.py                  |   12 +-
  distutils2/command/bdist_dumb.py             |   15 +-
  distutils2/command/bdist_msi.py              |   32 +-
  distutils2/command/bdist_wininst.py          |   83 ++-
  distutils2/command/build_clib.py             |    3 +-
  distutils2/command/build_ext.py              |   30 +-
  distutils2/command/build_py.py               |    4 +-
  distutils2/command/build_scripts.py          |   10 +-
  distutils2/command/cmd.py                    |    7 +-
  distutils2/command/config.py                 |   43 +-
  distutils2/command/install_data.py           |    5 +-
  distutils2/command/install_dist.py           |   12 +-
  distutils2/command/install_distinfo.py       |    4 +-
  distutils2/command/install_lib.py            |    4 +-
  distutils2/command/install_scripts.py        |    2 +-
  distutils2/command/register.py               |   12 +-
  distutils2/command/sdist.py                  |    8 +-
  distutils2/command/upload.py                 |   23 +-
  distutils2/command/upload_docs.py            |   27 +-
  distutils2/compiler/bcppcompiler.py          |   20 +-
  distutils2/compiler/ccompiler.py             |   14 +-
  distutils2/compiler/cygwinccompiler.py       |   23 +-
  distutils2/compiler/msvc9compiler.py         |   26 +-
  distutils2/compiler/msvccompiler.py          |   22 +-
  distutils2/compiler/unixccompiler.py         |   18 +-
  distutils2/config.py                         |   24 +-
  distutils2/create.py                         |  128 +++--
  distutils2/database.py                       |   61 +-
  distutils2/depgraph.py                       |    9 +-
  distutils2/dist.py                           |   57 +-
  distutils2/fancy_getopt.py                   |    6 +-
  distutils2/install.py                        |   37 +-
  distutils2/manifest.py                       |   21 +-
  distutils2/markers.py                        |   10 +-
  distutils2/metadata.py                       |   20 +-
  distutils2/pypi/dist.py                      |   10 +-
  distutils2/pypi/simple.py                    |   45 +-
  distutils2/pypi/wrapper.py                   |    4 +-
  distutils2/pypi/xmlrpc.py                    |    5 +-
  distutils2/run.py                            |   35 +-
  distutils2/tests/__main__.py                 |    8 +-
  distutils2/tests/pypi_server.py              |   22 +-
  distutils2/tests/test_command_build.py       |    2 +-
  distutils2/tests/test_command_build_ext.py   |    9 +-
  distutils2/tests/test_command_upload_docs.py |    5 +-
  distutils2/tests/test_install.py             |    3 +-
  distutils2/tests/test_mixin2to3.py           |   10 +-
  distutils2/tests/test_pypi_simple.py         |    4 +-
  distutils2/util.py                           |  203 +++++----
  distutils2/version.py                        |    1 -
  53 files changed, 646 insertions(+), 562 deletions(-)


diff --git a/distutils2/__init__.py b/distutils2/__init__.py
--- a/distutils2/__init__.py
+++ b/distutils2/__init__.py
@@ -1,4 +1,4 @@
-"""Support for distutils2, distribution and installation of Python projects.
+"""Support for packaging, distribution and installation of Python projects.
 
 Third-party tools can use parts of distutils2 as building blocks
 without causing the other modules to be imported:
diff --git a/distutils2/_backport/tests/test_sysconfig.py b/distutils2/_backport/tests/test_sysconfig.py
--- a/distutils2/_backport/tests/test_sysconfig.py
+++ b/distutils2/_backport/tests/test_sysconfig.py
@@ -254,7 +254,8 @@
         # Issue 7880
         def get(python):
             cmd = [python, '-c',
-                   'import sysconfig; print sysconfig.get_platform()']
+                   'from distutils2._backport import sysconfig; '
+                   'print sysconfig.get_platform()']
             p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=os.environ)
             return p.communicate()
         real = os.path.realpath(sys.executable)
diff --git a/distutils2/command/__init__.py b/distutils2/command/__init__.py
--- a/distutils2/command/__init__.py
+++ b/distutils2/command/__init__.py
@@ -28,8 +28,11 @@
     'bdist_wininst': 'distutils2.command.bdist_wininst.bdist_wininst',
     'register': 'distutils2.command.register.register',
     'upload': 'distutils2.command.upload.upload',
-    'upload_docs': 'distutils2.command.upload_docs.upload_docs'}
+    'upload_docs': 'distutils2.command.upload_docs.upload_docs',
+}
 
+# XXX use OrderedDict to preserve the grouping (build-related, install-related,
+# distribution-related)
 STANDARD_COMMANDS = set(_COMMANDS)
 
 
diff --git a/distutils2/command/bdist.py b/distutils2/command/bdist.py
--- a/distutils2/command/bdist.py
+++ b/distutils2/command/bdist.py
@@ -58,7 +58,7 @@
     # This is of course very simplistic.  The various UNIX family operating
     # systems have their specific formats, but they are out of scope for us;
     # bdist_dumb is, well, dumb; it's more a building block for other
-    # distutils2 tools than a real end-user binary format.
+    # packaging tools than a real end-user binary format.
     default_format = {'posix': 'gztar',
                       'nt': 'zip',
                       'os2': 'zip'}
@@ -75,9 +75,8 @@
                       'wininst': ('bdist_wininst',
                                   "Windows executable installer"),
                       'zip':   ('bdist_dumb', "ZIP file"),
-                      'msi':   ('bdist_msi',  "Microsoft Installer")
-                      }
-
+                      'msi':   ('bdist_msi',  "Microsoft Installer"),
+                     }
 
     def initialize_options(self):
         self.bdist_base = None
@@ -109,8 +108,9 @@
             try:
                 self.formats = [self.default_format[os.name]]
             except KeyError:
-                raise PackagingPlatformError("don't know how to create built distributions " + \
-                      "on platform %s" % os.name)
+                raise PackagingPlatformError(
+                    "don't know how to create built distributions "
+                    "on platform %s" % os.name)
 
         if self.dist_dir is None:
             self.dist_dir = "dist"
diff --git a/distutils2/command/bdist_dumb.py b/distutils2/command/bdist_dumb.py
--- a/distutils2/command/bdist_dumb.py
+++ b/distutils2/command/bdist_dumb.py
@@ -7,11 +7,12 @@
 import os
 
 from shutil import rmtree
-from sysconfig import get_python_version
 from distutils2.util import get_platform
 from distutils2.command.cmd import Command
 from distutils2.errors import PackagingPlatformError
 from distutils2 import logger
+from distutils2._backport.sysconfig import get_python_version
+
 
 class bdist_dumb(Command):
 
@@ -44,10 +45,9 @@
 
     boolean_options = ['keep-temp', 'skip-build', 'relative']
 
-    default_format = { 'posix': 'gztar',
-                       'nt': 'zip',
-                       'os2': 'zip' }
-
+    default_format = {'posix': 'gztar',
+                      'nt': 'zip',
+                      'os2': 'zip'}
 
     def initialize_options(self):
         self.bdist_dir = None
@@ -69,8 +69,9 @@
             try:
                 self.format = self.default_format[os.name]
             except KeyError:
-                raise PackagingPlatformError(("don't know how to create dumb built distributions " +
-                       "on platform %s") % os.name)
+                raise PackagingPlatformError(
+                    "don't know how to create dumb built distributions "
+                    "on platform %s" % os.name)
 
         self.set_undefined_options('bdist', 'dist_dir', 'plat_name')
 
diff --git a/distutils2/command/bdist_msi.py b/distutils2/command/bdist_msi.py
--- a/distutils2/command/bdist_msi.py
+++ b/distutils2/command/bdist_msi.py
@@ -8,7 +8,7 @@
 import msilib
 
 
-from sysconfig import get_python_version
+from distutils2._backport.sysconfig import get_python_version
 from shutil import rmtree
 from distutils2.command.cmd import Command
 from distutils2.version import NormalizedVersion
@@ -391,19 +391,23 @@
         if self.pre_install_script:
             scriptfn = os.path.join(self.bdist_dir, "preinstall.bat")
             f = open(scriptfn, "w")
-            # The batch file will be executed with [PYTHON], so that %1
-            # is the path to the Python interpreter; %0 will be the path
-            # of the batch file.
-            # rem ="""
-            # %1 %0
-            # exit
-            # """
-            # <actual script>
-            f.write('rem ="""\n%1 %0\nexit\n"""\n')
-            fp = open(self.pre_install_script)
-            f.write(fp.read())
-            fp.close()
-            f.close()
+            try:
+                # The batch file will be executed with [PYTHON], so that %1
+                # is the path to the Python interpreter; %0 will be the path
+                # of the batch file.
+                # rem ="""
+                # %1 %0
+                # exit
+                # """
+                # <actual script>
+                f.write('rem ="""\n%1 %0\nexit\n"""\n')
+                fp = open(self.pre_install_script)
+                try:
+                    f.write(fp.read())
+                finally:
+                    fp.close()
+            finally:
+                f.close()
             add_data(self.db, "Binary",
                      [("PreInstall", msilib.Binary(scriptfn)),
                      ])
diff --git a/distutils2/command/bdist_wininst.py b/distutils2/command/bdist_wininst.py
--- a/distutils2/command/bdist_wininst.py
+++ b/distutils2/command/bdist_wininst.py
@@ -6,11 +6,11 @@
 import os
 
 from shutil import rmtree
-from sysconfig import get_python_version
 from distutils2.command.cmd import Command
 from distutils2.errors import PackagingOptionError, PackagingPlatformError
 from distutils2 import logger
 from distutils2.util import get_platform
+from distutils2._backport.sysconfig import get_python_version
 
 
 class bdist_wininst(Command):
@@ -246,49 +246,56 @@
 
         if bitmap:
             fp = open(bitmap, "rb")
-            bitmapdata = fp.read()
-            fp.close()
+            try:
+                bitmapdata = fp.read()
+            finally:
+                fp.close()
             bitmaplen = len(bitmapdata)
         else:
             bitmaplen = 0
 
         file = open(installer_name, "wb")
-        file.write(self.get_exe_bytes())
-        if bitmap:
-            file.write(bitmapdata)
+        try:
+            file.write(self.get_exe_bytes())
+            if bitmap:
+                file.write(bitmapdata)
 
-        # Convert cfgdata from unicode to ascii, mbcs encoded
-        if isinstance(cfgdata, unicode):
-            cfgdata = cfgdata.encode("mbcs")
+            # Convert cfgdata from unicode to ascii, mbcs encoded
+            if isinstance(cfgdata, unicode):
+                cfgdata = cfgdata.encode("mbcs")
 
-        # Append the pre-install script
-        cfgdata = cfgdata + "\0"
-        if self.pre_install_script:
-            fp = open(self.pre_install_script)
-            script_data = fp.read()
-            fp.close()
-            cfgdata = cfgdata + script_data + "\n\0"
-        else:
-            # empty pre-install script
+            # Append the pre-install script
             cfgdata = cfgdata + "\0"
-        file.write(cfgdata)
+            if self.pre_install_script:
+                fp = open(self.pre_install_script)
+                try:
+                    script_data = fp.read()
+                finally:
+                    fp.close()
+                cfgdata = cfgdata + script_data + "\n\0"
+            else:
+                # empty pre-install script
+                cfgdata = cfgdata + "\0"
+            file.write(cfgdata)
 
-        # The 'magic number' 0x1234567B is used to make sure that the
-        # binary layout of 'cfgdata' is what the wininst.exe binary
-        # expects.  If the layout changes, increment that number, make
-        # the corresponding changes to the wininst.exe sources, and
-        # recompile them.
-        header = struct.pack("<iii",
-                             0x1234567B,       # tag
-                             len(cfgdata),     # length
-                             bitmaplen,        # number of bytes in bitmap
-                             )
-        file.write(header)
-        file.close()
-
-        fp = open(arcname, "rb")
-        file.write(fp.read())
-        fp.close()
+            # The 'magic number' 0x1234567B is used to make sure that the
+            # binary layout of 'cfgdata' is what the wininst.exe binary
+            # expects.  If the layout changes, increment that number, make
+            # the corresponding changes to the wininst.exe sources, and
+            # recompile them.
+            header = struct.pack("<iii",
+                                 0x1234567B,       # tag
+                                 len(cfgdata),     # length
+                                 bitmaplen,        # number of bytes in bitmap
+                                 )
+            file.write(header)
+            fp = open(arcname, "rb")
+            try:
+                file.write(fp.read())
+            finally:
+                fp.close()
+        finally:
+            file.close()
 
     def get_installer_filename(self, fullname):
         # Factored out to allow overriding in subclasses
@@ -344,6 +351,8 @@
 
         filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
         fp = open(filename, "rb")
-        content = fp.read()
-        fp.close()
+        try:
+            content = fp.read()
+        finally:
+            fp.close()
         return content
diff --git a/distutils2/command/build_clib.py b/distutils2/command/build_clib.py
--- a/distutils2/command/build_clib.py
+++ b/distutils2/command/build_clib.py
@@ -16,7 +16,7 @@
 import os
 from distutils2.command.cmd import Command
 from distutils2.errors import PackagingSetupError
-from distutils2.compiler import customize_compiler
+from distutils2.compiler import customize_compiler, new_compiler
 from distutils2 import logger
 
 
@@ -93,7 +93,6 @@
             return
 
         # Yech -- this is cut 'n pasted from build_ext.py!
-        from distutils2.compiler import new_compiler
         self.compiler = new_compiler(compiler=self.compiler,
                                      dry_run=self.dry_run,
                                      force=self.force)
diff --git a/distutils2/command/build_ext.py b/distutils2/command/build_ext.py
--- a/distutils2/command/build_ext.py
+++ b/distutils2/command/build_ext.py
@@ -1,9 +1,5 @@
 """Build extension modules."""
 
-# FIXME Is this module limited to C extensions or do C++ extensions work too?
-# The docstring of this module said that C++ was not supported, but other
-# comments contradict that.
-
 import os
 import re
 import sys
@@ -20,7 +16,10 @@
 from distutils2 import logger
 
 import site
-HAS_USER_SITE = True
+if sys.version_info[:2] >= (2, 6):
+    HAS_USER_SITE = True
+else:
+    HAS_USER_SITE = False
 
 if os.name == 'nt':
     from distutils2.compiler.msvccompiler import get_build_version
@@ -363,12 +362,11 @@
         for ext in self.extensions:
             try:
                 self.build_extension(ext)
-            except (CCompilerError, PackagingError, CompileError):
+            except (CCompilerError, PackagingError, CompileError), e:
                 if not ext.optional:
                     raise
                 logger.warning('%s: building extension %r failed: %s',
-                               self.get_command_name(), ext.name,
-                               sys.exc_info()[1])
+                               self.get_command_name(), ext.name, e)
 
     def build_extension(self, ext):
         sources = ext.sources
@@ -608,8 +606,7 @@
                 template = "python%d%d"
                 if self.debug:
                     template = template + '_d'
-                pythonlib = (template %
-                       (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+                pythonlib = template % sys.version_info[:2]
                 # don't extend ext.libraries, it may be shared with other
                 # extensions, it is a reference to the original list
                 return ext.libraries + [pythonlib]
@@ -623,22 +620,19 @@
             # not at this time - AIM Apr01
             #if self.debug:
             #    template = template + '_d'
-            pythonlib = (template %
-                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            pythonlib = template % sys.version_info[:2]
             # don't extend ext.libraries, it may be shared with other
             # extensions, it is a reference to the original list
             return ext.libraries + [pythonlib]
         elif sys.platform[:6] == "cygwin":
             template = "python%d.%d"
-            pythonlib = (template %
-                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            pythonlib = template % sys.version_info[:2]
             # don't extend ext.libraries, it may be shared with other
             # extensions, it is a reference to the original list
             return ext.libraries + [pythonlib]
         elif sys.platform[:6] == "atheos":
             template = "python%d.%d"
-            pythonlib = (template %
-                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            pythonlib = template % sys.version_info[:2]
             # Get SHLIBS from Makefile
             extra = []
             for lib in sysconfig.get_config_var('SHLIBS').split():
@@ -656,8 +650,8 @@
 
         else:
             if sysconfig.get_config_var('Py_ENABLE_SHARED'):
-                pythonlib = 'python%s.%s' % (
-                    sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)
+                template = 'python%d.%d' + sys.abiflags
+                pythonlib = template % sys.version_info[:2]
                 return ext.libraries + [pythonlib]
             else:
                 return ext.libraries
diff --git a/distutils2/command/build_py.py b/distutils2/command/build_py.py
--- a/distutils2/command/build_py.py
+++ b/distutils2/command/build_py.py
@@ -388,12 +388,12 @@
                 self.build_module(module, module_file, package)
 
     def byte_compile(self, files):
-        if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode:
+        if getattr(sys, 'dont_write_bytecode', False):
             logger.warning('%s: byte-compiling is disabled, skipping.',
                            self.get_command_name())
             return
 
-        from distutils2.util import byte_compile
+        from distutils2.util import byte_compile  # FIXME use compileall
         prefix = self.build_lib
         if prefix[-1] != os.sep:
             prefix = prefix + os.sep
diff --git a/distutils2/command/build_scripts.py b/distutils2/command/build_scripts.py
--- a/distutils2/command/build_scripts.py
+++ b/distutils2/command/build_scripts.py
@@ -130,9 +130,11 @@
                             "from the script encoding (%s)" % (
                                 shebang, encoding))
                     outf = open(outfile, "wb")
-                    outf.write(shebang)
-                    outf.writelines(f.readlines())
-                    outf.close()
+                    try:
+                        outf.write(shebang)
+                        outf.writelines(f.readlines())
+                    finally:
+                        outf.close()
                 if f:
                     f.close()
             else:
@@ -146,7 +148,7 @@
                     logger.info("changing mode of %s", file)
                 else:
                     oldmode = os.stat(file).st_mode & 07777
-                    newmode = (oldmode | 00555) & 07777
+                    newmode = (oldmode | 0555) & 07777
                     if newmode != oldmode:
                         logger.info("changing mode of %s from %o to %o",
                                  file, oldmode, newmode)
diff --git a/distutils2/command/cmd.py b/distutils2/command/cmd.py
--- a/distutils2/command/cmd.py
+++ b/distutils2/command/cmd.py
@@ -5,6 +5,7 @@
 from shutil import copyfile, move
 from distutils2 import util
 from distutils2 import logger
+from distutils2.util import make_archive
 from distutils2.errors import PackagingOptionError
 
 
@@ -403,9 +404,9 @@
 
     def make_archive(self, base_name, format, root_dir=None, base_dir=None,
                      owner=None, group=None):
-        return util.make_archive(base_name, format, root_dir,
-                                 base_dir, dry_run=self.dry_run,
-                                 owner=owner, group=group)
+        return make_archive(base_name, format, root_dir,
+                            base_dir, dry_run=self.dry_run,
+                            owner=owner, group=group)
 
     def make_file(self, infiles, outfile, func, args,
                   exec_msg=None, skip_msg=None, level=1):
diff --git a/distutils2/command/config.py b/distutils2/command/config.py
--- a/distutils2/command/config.py
+++ b/distutils2/command/config.py
@@ -111,14 +111,16 @@
     def _gen_temp_sourcefile(self, body, headers, lang):
         filename = "_configtest" + LANG_EXT[lang]
         file = open(filename, "w")
-        if headers:
-            for header in headers:
-                file.write("#include <%s>\n" % header)
-            file.write("\n")
-        file.write(body)
-        if body[-1] != "\n":
-            file.write("\n")
-        file.close()
+        try:
+            if headers:
+                for header in headers:
+                    file.write("#include <%s>\n" % header)
+                file.write("\n")
+            file.write(body)
+            if body[-1] != "\n":
+                file.write("\n")
+        finally:
+            file.close()
         return filename
 
     def _preprocess(self, body, headers, include_dirs, lang):
@@ -208,14 +210,17 @@
             pattern = re.compile(pattern)
 
         file = open(out)
-        match = False
-        while True:
-            line = file.readline()
-            if line == '':
-                break
-            if pattern.search(line):
-                match = True
-                break
+        try:
+            match = False
+            while True:
+                line = file.readline()
+                if line == '':
+                    break
+                if pattern.search(line):
+                    match = True
+                    break
+        finally:
+            file.close()
 
         self._clean()
         return match
@@ -347,5 +352,7 @@
     else:
         logger.info(head)
     file = open(filename)
-    logger.info(file.read())
-    file.close()
+    try:
+        logger.info(file.read())
+    finally:
+        file.close()
diff --git a/distutils2/command/install_data.py b/distutils2/command/install_data.py
--- a/distutils2/command/install_data.py
+++ b/distutils2/command/install_data.py
@@ -2,7 +2,7 @@
 
 # Contributed by Bastian Kleineidam
 
-import os, sys
+import os
 from shutil import Error
 from distutils2 import logger
 from distutils2.util import convert_path
@@ -48,8 +48,7 @@
             self.mkpath(dir_dest)
             try:
                 out = self.copy_file(_file[0], dir_dest)[0]
-            except Error:
-                e = sys.exc_info()[1]
+            except Error, e:
                 logger.warning('%s: %s', self.get_command_name(), e)
                 out = destination
 
diff --git a/distutils2/command/install_dist.py b/distutils2/command/install_dist.py
--- a/distutils2/command/install_dist.py
+++ b/distutils2/command/install_dist.py
@@ -295,9 +295,9 @@
 
         self.dump_dirs("post-expand_dirs()")
 
-        # Create directories in the home dir:
+        # Create directories under USERBASE
         if HAS_USER_SITE and self.user:
-            self.create_home_path()
+            self.create_user_dirs()
 
         # Pick the actual directory to install all modules to: either
         # install_purelib or install_platlib, depending on whether this
@@ -494,14 +494,12 @@
             attr = "install_" + name
             setattr(self, attr, change_root(self.root, getattr(self, attr)))
 
-    def create_home_path(self):
-        """Create directories under ~."""
-        if HAS_USER_SITE and not self.user:
-            return
+    def create_user_dirs(self):
+        """Create directories under USERBASE as needed."""
         home = convert_path(os.path.expanduser("~"))
         for name, path in self.config_vars.items():
             if path.startswith(home) and not os.path.isdir(path):
-                os.makedirs(path, 00700)
+                os.makedirs(path, 0700)
 
     # -- Command execution methods -------------------------------------
 
diff --git a/distutils2/command/install_distinfo.py b/distutils2/command/install_distinfo.py
--- a/distutils2/command/install_distinfo.py
+++ b/distutils2/command/install_distinfo.py
@@ -8,7 +8,7 @@
 import re
 try:
     import hashlib
-except ImportError: #<2.5
+except ImportError:
     from distutils2._backport import hashlib
 
 from distutils2.command.cmd import Command
@@ -32,7 +32,7 @@
         ('no-record', None,
          "do not generate a RECORD file"),
         ('no-resources', None,
-         "do not generate a RESSOURCES list installed file")
+         "do not generate a RESSOURCES list installed file"),
     ]
 
     boolean_options = ['requested', 'no-record', 'no-resources']
diff --git a/distutils2/command/install_lib.py b/distutils2/command/install_lib.py
--- a/distutils2/command/install_lib.py
+++ b/distutils2/command/install_lib.py
@@ -114,7 +114,7 @@
         return outfiles
 
     def byte_compile(self, files):
-        if hasattr(sys, 'dont_write_bytecode'):
+        if getattr(sys, 'dont_write_bytecode', False):
             # XXX do we want this?  because a Python runs without bytecode
             # doesn't mean that the *dists should not contain bytecode
             #--or does it?
@@ -122,7 +122,7 @@
                            self.get_command_name())
             return
 
-        from distutils2.util import byte_compile
+        from distutils2.util import byte_compile  # FIXME use compileall
 
         # Get the "--root" directory supplied to the "install_dist" command,
         # and use it as a prefix to strip off the purported filename
diff --git a/distutils2/command/install_scripts.py b/distutils2/command/install_scripts.py
--- a/distutils2/command/install_scripts.py
+++ b/distutils2/command/install_scripts.py
@@ -48,7 +48,7 @@
                 if self.dry_run:
                     logger.info("changing mode of %s", file)
                 else:
-                    mode = (os.stat(file).st_mode | 00555) & 07777
+                    mode = (os.stat(file).st_mode | 0555) & 07777
                     logger.info("changing mode of %s to %o", file, mode)
                     os.chmod(file, mode)
 
diff --git a/distutils2/command/register.py b/distutils2/command/register.py
--- a/distutils2/command/register.py
+++ b/distutils2/command/register.py
@@ -2,14 +2,13 @@
 
 # Contributed by Richard Jones
 
-import sys
 import getpass
+import urllib2
 import urlparse
-import urllib2
 
 from distutils2 import logger
 from distutils2.util import (read_pypirc, generate_pypirc, DEFAULT_REPOSITORY,
-                            DEFAULT_REALM, get_pypirc_path, encode_multipart)
+                             DEFAULT_REALM, get_pypirc_path, encode_multipart)
 from distutils2.command.cmd import Command
 
 class register(Command):
@@ -246,13 +245,12 @@
         data = ''
         try:
             result = opener.open(req)
-        except urllib2.HTTPError:
-            e = sys.exc_info()[1]
+        except urllib2.HTTPError, e:
             if self.show_response:
                 data = e.fp.read()
             result = e.code, e.msg
-        except urllib2.URLError:
-            result = 500, str(sys.exc_info()[1])
+        except urllib2.URLError, e:
+            result = 500, str(e)
         else:
             if self.show_response:
                 data = result.read()
diff --git a/distutils2/command/sdist.py b/distutils2/command/sdist.py
--- a/distutils2/command/sdist.py
+++ b/distutils2/command/sdist.py
@@ -9,7 +9,7 @@
 from distutils2 import logger
 from distutils2.util import resolve_name, get_archive_formats
 from distutils2.errors import (PackagingPlatformError, PackagingOptionError,
-                              PackagingModuleError, PackagingFileError)
+                               PackagingModuleError, PackagingFileError)
 from distutils2.command import get_command_names
 from distutils2.command.cmd import Command
 from distutils2.manifest import Manifest
@@ -143,8 +143,8 @@
                     continue
                 try:
                     builder = resolve_name(builder)
-                except ImportError:
-                    raise PackagingModuleError(sys.exc_info()[1])
+                except ImportError, e:
+                    raise PackagingModuleError(e)
 
                 builders.append(builder)
 
@@ -337,7 +337,7 @@
         """
         return self.archive_files
 
-    def create_tree(self, base_dir, files, mode=00777, verbose=1,
+    def create_tree(self, base_dir, files, mode=0777, verbose=1,
                     dry_run=False):
         need_dir = set()
         for file in files:
diff --git a/distutils2/command/upload.py b/distutils2/command/upload.py
--- a/distutils2/command/upload.py
+++ b/distutils2/command/upload.py
@@ -1,6 +1,6 @@
 """Upload a distribution to a project index."""
 
-import os, sys
+import os
 import socket
 import logging
 import platform
@@ -16,7 +16,7 @@
 from distutils2 import logger
 from distutils2.errors import PackagingOptionError
 from distutils2.util import (spawn, read_pypirc, DEFAULT_REPOSITORY,
-                            DEFAULT_REALM, encode_multipart)
+                             DEFAULT_REALM, encode_multipart)
 from distutils2.command.cmd import Command
 
 
@@ -105,8 +105,10 @@
         # Fill in the data - send all the metadata in case we need to
         # register a new release
         f = open(filename, 'rb')
-        content = f.read()
-        f.close()
+        try:
+            content = f.read()
+        finally:
+            f.close()
 
         data = self.distribution.metadata.todict()
 
@@ -123,8 +125,10 @@
 
         if self.sign:
             fp = open(filename + '.asc')
-            sig = fp.read()
-            fp.close()
+            try:
+                sig = fp.read()
+            finally:
+                fp.close()
             data['gpg_signature'] = [
                 (os.path.basename(filename) + ".asc", sig)]
 
@@ -156,11 +160,10 @@
             result = urlopen(request)
             status = result.code
             reason = result.msg
-        except socket.error:
-            logger.error(sys.exc_info()[1])
+        except socket.error, e:
+            logger.error(e)
             return
-        except HTTPError:
-            e = sys.exc_info()[1]
+        except HTTPError, e:
             status = e.code
             reason = e.msg
 
diff --git a/distutils2/command/upload_docs.py b/distutils2/command/upload_docs.py
--- a/distutils2/command/upload_docs.py
+++ b/distutils2/command/upload_docs.py
@@ -1,6 +1,6 @@
 """Upload HTML documentation to a project index."""
 
-import os, sys
+import os
 import base64
 import socket
 import zipfile
@@ -11,7 +11,7 @@
 
 from distutils2 import logger
 from distutils2.util import (read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM,
-                            encode_multipart)
+                             encode_multipart)
 from distutils2.errors import PackagingFileError
 from distutils2.command.cmd import Command
 
@@ -20,13 +20,15 @@
     """Compresses recursively contents of directory into a BytesIO object"""
     destination = StringIO()
     zip_file = zipfile.ZipFile(destination, "w")
-    for root, dirs, files in os.walk(directory):
-        for name in files:
-            full = os.path.join(root, name)
-            relative = root[len(directory):].lstrip(os.path.sep)
-            dest = os.path.join(relative, name)
-            zip_file.write(full, dest)
-    zip_file.close()
+    try:
+        for root, dirs, files in os.walk(directory):
+            for name in files:
+                full = os.path.join(root, name)
+                relative = root[len(directory):].lstrip(os.path.sep)
+                dest = os.path.join(relative, name)
+                zip_file.write(full, dest)
+    finally:
+        zip_file.close()
     return destination
 
 
@@ -88,7 +90,8 @@
         content_type, body = encode_multipart(fields, files)
 
         credentials = self.username + ':' + self.password
-        auth = "Basic " + base64.encodebytes(credentials.encode()).strip()
+        # FIXME should use explicit encoding
+        auth = "Basic " + base64.encodestring(credentials.encode()).strip()
 
         logger.info("Submitting documentation to %s", self.repository)
 
@@ -110,8 +113,8 @@
             conn.endheaders()
             conn.send(body)
 
-        except socket.error:
-            logger.error(sys.exc_info()[1])
+        except socket.error, e:
+            logger.error(e)
             return
 
         r = conn.getresponse()
diff --git a/distutils2/compiler/bcppcompiler.py b/distutils2/compiler/bcppcompiler.py
--- a/distutils2/compiler/bcppcompiler.py
+++ b/distutils2/compiler/bcppcompiler.py
@@ -7,10 +7,10 @@
 # someone should sit down and factor out the common code as
 # WindowsCCompiler!  --GPW
 
-import os, sys
+import os
 
 from distutils2.errors import (PackagingExecError, CompileError, LibError,
-                              LinkError, UnknownFileError)
+                               LinkError, UnknownFileError)
 from distutils2.compiler.ccompiler import CCompiler
 from distutils2.compiler import gen_preprocess_options
 from distutils2.file_util import write_file
@@ -104,8 +104,8 @@
                 # This needs to be compiled to a .res file -- do it now.
                 try:
                     self.spawn(["brcc32", "-fo", obj, src])
-                except PackagingExecError:
-                    raise CompileError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise CompileError(msg)
                 continue # the 'for' loop
 
             # The next two are both for the real compiler.
@@ -128,8 +128,8 @@
                 self.spawn([self.cc] + compile_opts + pp_opts +
                            [input_opt, output_opt] +
                            extra_postargs + [src])
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
 
         return objects
 
@@ -146,8 +146,8 @@
                 pass                    # XXX what goes here?
             try:
                 self.spawn([self.lib] + lib_args)
-            except PackagingExecError:
-                raise LibError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LibError(msg)
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
 
@@ -268,8 +268,8 @@
             self.mkpath(os.path.dirname(output_filename))
             try:
                 self.spawn([self.linker] + ld_args)
-            except PackagingExecError:
-                raise LinkError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LinkError(msg)
 
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
diff --git a/distutils2/compiler/ccompiler.py b/distutils2/compiler/ccompiler.py
--- a/distutils2/compiler/ccompiler.py
+++ b/distutils2/compiler/ccompiler.py
@@ -8,7 +8,7 @@
 from shutil import move
 from distutils2 import logger
 from distutils2.util import split_quoted, execute, newer_group, spawn
-from distutils2.errors import (CompileError, LinkError, UnknownFileError)
+from distutils2.errors import CompileError, LinkError, UnknownFileError
 from distutils2.compiler import gen_preprocess_options
 
 
@@ -728,14 +728,16 @@
             library_dirs = []
         fd, fname = tempfile.mkstemp(".c", funcname, text=True)
         f = os.fdopen(fd, "w")
-        for incl in includes:
-            f.write("""#include "%s"\n""" % incl)
-        f.write("""\
+        try:
+            for incl in includes:
+                f.write("""#include "%s"\n""" % incl)
+            f.write("""\
 main (int argc, char **argv) {
     %s();
 }
 """ % funcname)
-        f.close()
+        finally:
+            f.close()
         try:
             objects = self.compile([fname], include_dirs=include_dirs)
         except CompileError:
@@ -852,7 +854,7 @@
             return
         return move(src, dst)
 
-    def mkpath(self, name, mode=00777):
+    def mkpath(self, name, mode=0777):
         name = os.path.normpath(name)
         if os.path.isdir(name) or name == '':
             return
diff --git a/distutils2/compiler/cygwinccompiler.py b/distutils2/compiler/cygwinccompiler.py
--- a/distutils2/compiler/cygwinccompiler.py
+++ b/distutils2/compiler/cygwinccompiler.py
@@ -156,14 +156,14 @@
             # gcc needs '.res' and '.rc' compiled to object files !!!
             try:
                 self.spawn(["windres", "-i", src, "-o", obj])
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
         else: # for other files use the C-compiler
             try:
                 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
                            extra_postargs)
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
 
     def link(self, target_desc, objects, output_filename, output_dir=None,
              libraries=None, library_dirs=None, runtime_library_dirs=None,
@@ -345,12 +345,13 @@
     fn = sysconfig.get_config_h_filename()
     try:
         config_h = open(fn)
-        if "__GNUC__" in config_h.read():
-            return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
-        else:
-            return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
-        config_h.close()
-    except IOError:
-        exc = sys.exc_info()[1]
+        try:
+            if "__GNUC__" in config_h.read():
+                return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
+            else:
+                return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
+        finally:
+            config_h.close()
+    except IOError, exc:
         return (CONFIG_H_UNCERTAIN,
                 "couldn't read '%s': %s" % (fn, exc.strerror))
diff --git a/distutils2/compiler/msvc9compiler.py b/distutils2/compiler/msvc9compiler.py
--- a/distutils2/compiler/msvc9compiler.py
+++ b/distutils2/compiler/msvc9compiler.py
@@ -14,7 +14,7 @@
 import re
 
 from distutils2.errors import (PackagingExecError, PackagingPlatformError,
-                              CompileError, LibError, LinkError)
+                               CompileError, LibError, LinkError)
 from distutils2.compiler.ccompiler import CCompiler
 from distutils2.compiler import gen_lib_options
 from distutils2 import logger
@@ -477,8 +477,8 @@
                 try:
                     self.spawn([self.rc] + pp_opts +
                                [output_opt] + [input_opt])
-                except PackagingExecError:
-                    raise CompileError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise CompileError(msg)
                 continue
             elif ext in self._mc_extensions:
                 # Compile .MC to .RC file to .RES file.
@@ -504,8 +504,8 @@
                     self.spawn([self.rc] +
                                ["/fo" + obj] + [rc_file])
 
-                except PackagingExecError:
-                    raise CompileError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise CompileError(msg)
                 continue
             else:
                 # how to handle this file?
@@ -517,8 +517,8 @@
                 self.spawn([self.cc] + compile_opts + pp_opts +
                            [input_opt, output_opt] +
                            extra_postargs)
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
 
         return objects
 
@@ -542,8 +542,8 @@
                 pass # XXX what goes here?
             try:
                 self.spawn([self.lib] + lib_args)
-            except PackagingExecError:
-                raise LibError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LibError(msg)
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
 
@@ -620,8 +620,8 @@
             self.mkpath(os.path.dirname(output_filename))
             try:
                 self.spawn([self.linker] + ld_args)
-            except PackagingExecError:
-                raise LinkError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LinkError(msg)
 
             # embed the manifest
             # XXX - this is somewhat fragile - if mt.exe fails, distutils
@@ -637,8 +637,8 @@
             try:
                 self.spawn(['mt.exe', '-nologo', '-manifest',
                             temp_manifest, out_arg])
-            except PackagingExecError:
-                raise LinkError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LinkError(msg)
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
 
diff --git a/distutils2/compiler/msvccompiler.py b/distutils2/compiler/msvccompiler.py
--- a/distutils2/compiler/msvccompiler.py
+++ b/distutils2/compiler/msvccompiler.py
@@ -12,7 +12,7 @@
 import os
 
 from distutils2.errors import (PackagingExecError, PackagingPlatformError,
-                              CompileError, LibError, LinkError)
+                               CompileError, LibError, LinkError)
 from distutils2.compiler.ccompiler import CCompiler
 from distutils2.compiler import gen_lib_options
 from distutils2 import logger
@@ -386,8 +386,8 @@
                 try:
                     self.spawn([self.rc] + pp_opts +
                                [output_opt] + [input_opt])
-                except PackagingExecError:
-                    raise CompileError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise CompileError(msg)
                 continue
             elif ext in self._mc_extensions:
 
@@ -415,8 +415,8 @@
                     self.spawn([self.rc] +
                                 ["/fo" + obj] + [rc_file])
 
-                except PackagingExecError:
-                    raise CompileError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise CompileError(msg)
                 continue
             else:
                 # how to handle this file?
@@ -429,8 +429,8 @@
                 self.spawn([self.cc] + compile_opts + pp_opts +
                            [input_opt, output_opt] +
                            extra_postargs)
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
 
         return objects
 
@@ -448,8 +448,8 @@
                 pass                    # XXX what goes here?
             try:
                 self.spawn([self.lib] + lib_args)
-            except PackagingExecError:
-                raise LibError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LibError(msg)
 
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
@@ -515,8 +515,8 @@
             self.mkpath(os.path.dirname(output_filename))
             try:
                 self.spawn([self.linker] + ld_args)
-            except PackagingExecError:
-                raise LinkError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LinkError(msg)
 
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
diff --git a/distutils2/compiler/unixccompiler.py b/distutils2/compiler/unixccompiler.py
--- a/distutils2/compiler/unixccompiler.py
+++ b/distutils2/compiler/unixccompiler.py
@@ -127,7 +127,7 @@
         executables['ranlib'] = ["ranlib"]
 
     # Needed for the filename generation methods provided by the base
-    # class, CCompiler.  NB. whoever instantiates/uses a particular
+    # class, CCompiler.  XXX whoever instantiates/uses a particular
     # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
     # reasonable common default here, but it's not necessarily used on all
     # Unices!
@@ -165,8 +165,8 @@
                 self.mkpath(os.path.dirname(output_file))
             try:
                 self.spawn(pp_args)
-            except PackagingExecError:
-                raise CompileError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise CompileError(msg)
 
     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
         compiler_so = self.compiler_so
@@ -175,8 +175,8 @@
         try:
             self.spawn(compiler_so + cc_args + [src, '-o', obj] +
                        extra_postargs)
-        except PackagingExecError:
-            raise CompileError(sys.exc_info()[1])
+        except PackagingExecError, msg:
+            raise CompileError(msg)
 
     def create_static_lib(self, objects, output_libname,
                           output_dir=None, debug=False, target_lang=None):
@@ -199,8 +199,8 @@
             if self.ranlib:
                 try:
                     self.spawn(self.ranlib + [output_filename])
-                except PackagingExecError:
-                    raise LibError(sys.exc_info()[1])
+                except PackagingExecError, msg:
+                    raise LibError(msg)
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
 
@@ -253,8 +253,8 @@
                     linker = _darwin_compiler_fixup(linker, ld_args)
 
                 self.spawn(linker + ld_args)
-            except PackagingExecError:
-                raise LinkError(sys.exc_info()[1])
+            except PackagingExecError, msg:
+                raise LinkError(msg)
         else:
             logger.debug("skipping %s (up-to-date)", output_filename)
 
diff --git a/distutils2/config.py b/distutils2/config.py
--- a/distutils2/config.py
+++ b/distutils2/config.py
@@ -1,8 +1,8 @@
 """Utilities to find and read config files used by distutils2."""
 
-import codecs
 import os
 import sys
+import codecs
 import logging
 
 from shlex import split
@@ -11,7 +11,7 @@
 from distutils2.errors import PackagingOptionError
 from distutils2.compiler.extension import Extension
 from distutils2.util import (check_environ, iglob, resolve_name, strtobool,
-                            split_multiline)
+                             split_multiline)
 from distutils2.compiler import set_compiler
 from distutils2.command import set_command
 from distutils2.markers import interpret
@@ -142,9 +142,9 @@
                     for line in setup_hooks:
                         try:
                             hook = resolve_name(line)
-                        except ImportError:
+                        except ImportError, e:
                             logger.warning('cannot find setup hook: %s',
-                                           sys.exc_info()[1].args[0])
+                                           e.args[0])
                         else:
                             self.setup_hooks.append(hook)
                     self.run_hooks(content)
@@ -178,8 +178,10 @@
                     for filename in filenames:
                         # will raise if file not found
                         description_file = open(filename)
-                        value.append(description_file.read().strip())
-                        description_file.close()
+                        try:
+                            value.append(description_file.read().strip())
+                        finally:
+                            description_file.close()
                         # add filename as a required file
                         if filename not in metadata.requires_files:
                             metadata.requires_files.append(filename)
@@ -290,8 +292,10 @@
         for filename in filenames:
             logger.debug("  reading %s", filename)
             f = codecs.open(filename, 'r', encoding='utf-8')
-            parser.readfp(f)
-            f.close()
+            try:
+                parser.readfp(f)
+            finally:
+                f.close()
 
             if os.path.split(filename)[-1] == 'setup.cfg':
                 self._read_setup_cfg(parser, filename)
@@ -348,8 +352,8 @@
                         setattr(self.dist, opt, strtobool(val))
                     else:
                         setattr(self.dist, opt, val)
-                except ValueError:
-                    raise PackagingOptionError(sys.exc_info()[1])
+                except ValueError, msg:
+                    raise PackagingOptionError(msg)
 
     def _load_compilers(self, compilers):
         compilers = split_multiline(compilers)
diff --git a/distutils2/create.py b/distutils2/create.py
--- a/distutils2/create.py
+++ b/distutils2/create.py
@@ -18,30 +18,33 @@
 #  Ask for a description
 #  Detect scripts (not sure how.  #! outside of package?)
 
-import codecs
 import os
 import re
 import imp
 import sys
 import glob
+import codecs
 import shutil
-from distutils2._backport import sysconfig
-if 'any' not in dir(__builtins__):
-    from distutils2._backport import any
-try:
-    from hashlib import md5
-except ImportError: #<2.5
-    from md5 import md5
 from textwrap import dedent
+from ConfigParser import RawConfigParser
 from distutils2.util import cmp_to_key, detect_encoding
-from ConfigParser import RawConfigParser
 # importing this with an underscore as it should be replaced by the
 # dict form or another structures for all purposes
 from distutils2._trove import all_classifiers as _CLASSIFIERS_LIST
 from distutils2.version import is_valid_version
+from distutils2._backport import sysconfig
+try:
+    any
+except NameError:
+    from distutils2._backport import any
+try:
+    from hashlib import md5
+except ImportError:
+    from distutils2._backport.hashlib import md5
+
 
 _FILENAME = 'setup.cfg'
-_DEFAULT_CFG = '.pypkgcreate'
+_DEFAULT_CFG = '.pypkgcreate'  # FIXME use a section in user .pydistutils.cfg
 
 _helptext = {
     'name': '''
@@ -117,11 +120,16 @@
     been loaded before, because we are monkey patching its setup function with
     a particular one"""
     f = open("setup.py", "rb")
-    encoding, lines = detect_encoding(f.readline)
-    f.close()
+    try:
+        encoding, lines = detect_encoding(f.readline)
+    finally:
+        f.close()
     f = open("setup.py")
-    imp.load_module("setup", f, "setup.py", (".py", "r", imp.PY_SOURCE))
-    f.close()
+    try:
+        imp.load_module("setup", f, "setup.py", (".py", "r", imp.PY_SOURCE))
+    finally:
+        f.close()
+
 
 def ask_yn(question, default=None, helptext=None):
     question += ' (y/n)'
@@ -133,6 +141,10 @@
         print '\nERROR: You must select "Y" or "N".\n'
 
 
+# XXX use util.ask
+# FIXME: if prompt ends with '?', don't add ':'
+
+
 def ask(question, default=None, helptext=None, required=True,
         lengthy=False, multiline=False):
     prompt = u'%s: ' % (question,)
@@ -280,50 +292,52 @@
             shutil.move(_FILENAME, '%s.old' % _FILENAME)
 
         fp = codecs.open(_FILENAME, 'w', encoding='utf-8')
-        fp.write(u'[metadata]\n')
-        # TODO use metadata module instead of hard-coding field-specific
-        # behavior here
+        try:
+            fp.write(u'[metadata]\n')
+            # TODO use metadata module instead of hard-coding field-specific
+            # behavior here
 
-        # simple string entries
-        for name in ('name', 'version', 'summary', 'download_url'):
-            fp.write(u'%s = %s\n' % (name, self.data.get(name, 'UNKNOWN')))
+            # simple string entries
+            for name in ('name', 'version', 'summary', 'download_url'):
+                fp.write(u'%s = %s\n' % (name, self.data.get(name, 'UNKNOWN')))
 
-        # optional string entries
-        if 'keywords' in self.data and self.data['keywords']:
-            fp.write(u'keywords = %s\n' % ' '.join(self.data['keywords']))
-        for name in ('home_page', 'author', 'author_email',
-                     'maintainer', 'maintainer_email', 'description-file'):
-            if name in self.data and self.data[name]:
-                fp.write(u'%s = %s\n' % (name.decode('utf-8'),
-                    self.data[name].decode('utf-8')))
-        if 'description' in self.data:
-            fp.write(
-                u'description = %s\n'
-                % u'\n       |'.join(self.data['description'].split('\n')))
+            # optional string entries
+            if 'keywords' in self.data and self.data['keywords']:
+                fp.write(u'keywords = %s\n' % ' '.join(self.data['keywords']))
+            for name in ('home_page', 'author', 'author_email',
+                         'maintainer', 'maintainer_email', 'description-file'):
+                if name in self.data and self.data[name]:
+                    fp.write(u'%s = %s\n' % (name.decode('utf-8'),
+                                             self.data[name].decode('utf-8')))
+            if 'description' in self.data:
+                fp.write(
+                    u'description = %s\n'
+                    % u'\n       |'.join(self.data['description'].split('\n')))
 
-        # multiple use string entries
-        for name in ('platform', 'supported-platform', 'classifier',
-                     'requires-dist', 'provides-dist', 'obsoletes-dist',
-                     'requires-external'):
-            if not(name in self.data and self.data[name]):
-                continue
-            fp.write(u'%s = ' % name)
-            fp.write(u''.join('    %s\n' % val
-                             for val in self.data[name]).lstrip())
-        fp.write(u'\n[files]\n')
-        for name in ('packages', 'modules', 'scripts',
-                     'package_data', 'extra_files'):
-            if not(name in self.data and self.data[name]):
-                continue
-            fp.write(u'%s = %s\n'
-                     % (name, u'\n    '.join(self.data[name]).strip()))
-        fp.write(u'\nresources =\n')
-        for src, dest in self.data['resources']:
-            fp.write(u'    %s = %s\n' % (src, dest))
-        fp.write(u'\n')
-        fp.close()
+            # multiple use string entries
+            for name in ('platform', 'supported-platform', 'classifier',
+                         'requires-dist', 'provides-dist', 'obsoletes-dist',
+                         'requires-external'):
+                if not(name in self.data and self.data[name]):
+                    continue
+                fp.write(u'%s = ' % name)
+                fp.write(u''.join('    %s\n' % val
+                                 for val in self.data[name]).lstrip())
+            fp.write(u'\n[files]\n')
+            for name in ('packages', 'modules', 'scripts',
+                         'package_data', 'extra_files'):
+                if not(name in self.data and self.data[name]):
+                    continue
+                fp.write(u'%s = %s\n'
+                         % (name, u'\n    '.join(self.data[name]).strip()))
+            fp.write(u'\nresources =\n')
+            for src, dest in self.data['resources']:
+                fp.write(u'    %s = %s\n' % (src, dest))
+            fp.write(u'\n')
+        finally:
+            fp.close()
 
-        os.chmod(_FILENAME, 00644)
+        os.chmod(_FILENAME, 0644)
         print 'Wrote %r.' % _FILENAME
 
     def convert_py_to_cfg(self):
@@ -418,8 +432,10 @@
                 ref = ref.digest()
                 for readme in glob.glob('README*'):
                     fp = codecs.open(readme, encoding='utf-8')
-                    contents = fp.read()
-                    fp.close()
+                    try:
+                        contents = fp.read()
+                    finally:
+                        fp.close()
                     contents = re.sub('\s', '', contents.lower()).encode()
                     val = md5(contents).digest()
                     if val == ref:
diff --git a/distutils2/database.py b/distutils2/database.py
--- a/distutils2/database.py
+++ b/distutils2/database.py
@@ -1,15 +1,16 @@
 """PEP 376 implementation."""
 
-from StringIO import StringIO
 import os
 import re
 import csv
 import sys
 import zipimport
+from StringIO import StringIO
 try:
     from hashlib import md5
-except ImportError: #<2.5
-    from md5 import md5
+except ImportError:
+    from distutils2._backport.hashlib import md5
+
 from distutils2 import logger
 from distutils2.errors import PackagingError
 from distutils2.version import suggest_normalized_version, VersionPredicate
@@ -162,26 +163,30 @@
     def _get_records(self, local=False):
         results = []
         record = self.get_distinfo_file('RECORD')
-        record_reader = csv.reader(record, delimiter=',',
-                                   lineterminator='\n')
-        for row in record_reader:
-            missing = [None for i in range(len(row), 3)]
-            path, checksum, size = row + missing
-            if local:
-                path = path.replace('/', os.sep)
-                path = os.path.join(sys.prefix, path)
-            results.append((path, checksum, size))
-        record.close()
+        try:
+            record_reader = csv.reader(record, delimiter=',',
+                                       lineterminator='\n')
+            for row in record_reader:
+                missing = [None for i in range(len(row), 3)]
+                path, checksum, size = row + missing
+                if local:
+                    path = path.replace('/', os.sep)
+                    path = os.path.join(sys.prefix, path)
+                results.append((path, checksum, size))
+        finally:
+            record.close()
         return results
 
     def get_resource_path(self, relative_path):
         resources_file = self.get_distinfo_file('RESOURCES')
-        resources_reader = csv.reader(resources_file, delimiter=',',
-                                       lineterminator='\n')
-        for relative, destination in resources_reader:
-            if relative == relative_path:
-                return destination
-        resources_file.close()
+        try:
+            resources_reader = csv.reader(resources_file, delimiter=',',
+                                          lineterminator='\n')
+            for relative, destination in resources_reader:
+                if relative == relative_path:
+                    return destination
+        finally:
+            resources_file.close()
         raise KeyError(
             'no resource file with relative path %r is installed' %
             relative_path)
@@ -331,8 +336,10 @@
                 try:
                     req_path = os.path.join(path, 'EGG-INFO', 'requires.txt')
                     fp = open(req_path, 'r')
-                    requires = fp.read()
-                    fp.close()
+                    try:
+                        requires = fp.read()
+                    finally:
+                        fp.close()
                 except IOError:
                     requires = None
             else:
@@ -353,8 +360,10 @@
                 path = os.path.join(path, 'PKG-INFO')
                 try:
                     fp = open(os.path.join(path, 'requires.txt'), 'r')
-                    requires = fp.read()
-                    fp.close()
+                    try:
+                        requires = fp.read()
+                    finally:
+                        fp.close()
                 except IOError:
                     requires = None
             self.metadata = Metadata(path=path)
@@ -417,8 +426,10 @@
 
         def _md5(path):
             f = open(path, 'rb')
-            content = f.read()
-            f.close()
+            try:
+                content = f.read()
+            finally:
+                f.close()
             return md5(content).hexdigest()
 
         def _size(path):
diff --git a/distutils2/depgraph.py b/distutils2/depgraph.py
--- a/distutils2/depgraph.py
+++ b/distutils2/depgraph.py
@@ -234,8 +234,7 @@
             graph = generate_graph(dists)
         finally:
             sys.stderr = old
-    except Exception:
-        e = sys.exc_info()[1]
+    except Exception, e:
         tempout.seek(0)
         tempout = tempout.read()
         print 'Could not generate the graph'
@@ -259,8 +258,10 @@
             filename = 'depgraph.dot'
 
         f = open(filename, 'w')
-        graph_to_dot(graph, f, True)
-        f.close()
+        try:
+            graph_to_dot(graph, f, True)
+        finally:
+            f.close()
         tempout.seek(0)
         tempout = tempout.read()
         print tempout
diff --git a/distutils2/dist.py b/distutils2/dist.py
--- a/distutils2/dist.py
+++ b/distutils2/dist.py
@@ -1,21 +1,21 @@
-"""Class representing the distribution being built/installed/etc."""
+"""Class representing the project being built/installed/etc."""
 
 import os
 import re
-import sys
 
+from distutils2 import logger
+from distutils2.util import strtobool, resolve_name
 from distutils2.errors import (PackagingOptionError, PackagingArgError,
-                              PackagingModuleError, PackagingClassError)
-from distutils2.fancy_getopt import FancyGetopt
-from distutils2.util import strtobool, resolve_name
-from distutils2 import logger
-from distutils2.metadata import Metadata
+                               PackagingModuleError, PackagingClassError)
 from distutils2.config import Config
 from distutils2.command import get_command_class, STANDARD_COMMANDS
+from distutils2.command.cmd import Command
+from distutils2.metadata import Metadata
+from distutils2.fancy_getopt import FancyGetopt
 
 # Regex to define acceptable Packaging command names.  This is not *quite*
-# the same as a Python NAME -- I don't allow leading underscores.  The fact
-# that they're very similar is no coincidence; the default naming scheme is
+# the same as a Python name -- leading underscores are not allowed.  The fact
+# that they're very similar is no coincidence: the default naming scheme is
 # to look for a Python module named after the command.
 command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
 
@@ -33,17 +33,11 @@
 
 
 class Distribution(object):
-    """The core of the Packaging.  Most of the work hiding behind 'setup'
-    is really done within a Distribution instance, which farms the work out
-    to the Packaging commands specified on the command line.
+    """Class used to represent a project and work with it.
 
-    Setup scripts will almost never instantiate Distribution directly,
-    unless the 'setup()' function is totally inadequate to their needs.
-    However, it is conceivable that a setup script might wish to subclass
-    Distribution for some specialized purpose, and then pass the subclass
-    to 'setup()' as the 'distclass' keyword argument.  If so, it is
-    necessary to respect the expectations that 'setup' has of Distribution.
-    See the code for 'setup()', in run.py, for details.
+    Most of the work hiding behind 'pysetup run' is really done within a
+    Distribution instance, which farms the work out to the commands
+    specified on the command line.
     """
 
     # 'global_options' describes the command-line options that may be
@@ -64,8 +58,8 @@
     common_usage = """\
 Common commands: (see '--help-commands' for more)
 
-  pysetup run build      will build the package underneath 'build/'
-  pysetup run install    will install the package
+  pysetup run build      will build the project underneath 'build/'
+  pysetup run install    will install the project
 """
 
     # options that are not propagated to the commands
@@ -373,7 +367,7 @@
                             commands=self.commands)
             return
 
-        return 1
+        return True
 
     def _get_toplevel_options(self):
         """Return the non-display options recognized at the top level.
@@ -403,8 +397,8 @@
         # it takes.
         try:
             cmd_class = get_command_class(command)
-        except PackagingModuleError:
-            raise PackagingArgError(sys.exc_info()[1])
+        except PackagingModuleError, msg:
+            raise PackagingArgError(msg)
 
         # XXX We want to push this in distutils2.command
         #
@@ -501,9 +495,6 @@
         lists per-command help for every command name or command class
         in 'commands'.
         """
-        # late import because of mutual dependence between these modules
-        from distutils2.command.cmd import Command
-
         if global_options:
             if display_options:
                 options = self._get_toplevel_options()
@@ -629,7 +620,7 @@
         """
         cmd_obj = self.command_obj.get(command)
         if not cmd_obj and create:
-            logger.debug("Distribution.get_command_obj(): " \
+            logger.debug("Distribution.get_command_obj(): "
                          "creating %r command object", command)
 
             cls = get_command_class(command)
@@ -685,8 +676,8 @@
                     raise PackagingOptionError(
                         "error in %s: command %r has no such option %r" %
                         (source, command_name, option))
-            except ValueError:
-                raise PackagingOptionError(sys.exc_info()[1])
+            except ValueError, msg:
+                raise PackagingOptionError(msg)
 
     def get_reinitialized_command(self, command, reinit_subcommands=False):
         """Reinitializes a command to the state it was in when first
@@ -707,7 +698,6 @@
 
         Returns the reinitialized command object.
         """
-        from distutils2.command.cmd import Command
         if not isinstance(command, Command):
             command_name = command
             command = self.get_command_obj(command_name)
@@ -716,6 +706,7 @@
 
         if not command.finalized:
             return command
+
         command.initialize_options()
         self.have_run[command_name] = 0
         command.finalized = False
@@ -780,8 +771,8 @@
             if isinstance(hook, basestring):
                 try:
                     hook_obj = resolve_name(hook)
-                except ImportError:
-                    raise PackagingModuleError(sys.exc_info()[1])
+                except ImportError, e:
+                    raise PackagingModuleError(e)
             else:
                 hook_obj = hook
 
diff --git a/distutils2/fancy_getopt.py b/distutils2/fancy_getopt.py
--- a/distutils2/fancy_getopt.py
+++ b/distutils2/fancy_getopt.py
@@ -237,8 +237,8 @@
 
         try:
             opts, args = getopt.getopt(args, short_opts, self.long_opts)
-        except getopt.error:
-            raise PackagingArgError(sys.exc_info()[1])
+        except getopt.error, msg:
+            raise PackagingArgError(msg)
 
         for opt, val in opts:
             if len(opt) == 2 and opt[0] == '-':   # it's a short option
@@ -368,7 +368,7 @@
         if file is None:
             file = sys.stdout
         for line in self.generate_help(header):
-            file.write(line + u"\n")
+            file.write(line + "\n")
 
 
 def fancy_getopt(options, negative_opt, object, args):
diff --git a/distutils2/install.py b/distutils2/install.py
--- a/distutils2/install.py
+++ b/distutils2/install.py
@@ -13,21 +13,22 @@
 import shutil
 import logging
 import tempfile
-from sysconfig import get_config_var, get_path, is_python_build
 
 from distutils2 import logger
 from distutils2.dist import Distribution
 from distutils2.util import (_is_archive_file, ask, get_install_method,
-                            egginfo_to_distinfo, unpack_archive)
+                             egginfo_to_distinfo, unpack_archive)
 from distutils2.pypi import wrapper
 from distutils2.version import get_version_predicate
 from distutils2.database import get_distributions, get_distribution
 from distutils2.depgraph import generate_graph
 
 from distutils2.errors import (PackagingError, InstallationException,
-                              InstallationConflict, CCompilerError)
+                               InstallationConflict, CCompilerError)
 from distutils2.pypi.errors import ProjectNotFound, ReleaseNotFound
 from distutils2 import database
+from distutils2._backport.sysconfig import (get_config_var, get_path,
+                                            is_python_build)
 
 
 __all__ = ['install_dists', 'install_from_infos', 'get_infos', 'remove',
@@ -50,8 +51,7 @@
         # try to make the paths.
         try:
             os.makedirs(os.path.dirname(new))
-        except OSError:
-            e = sys.exc_info()[1]
+        except OSError, e:
             if e.errno != errno.EEXIST:
                 raise
         os.rename(old, new)
@@ -88,8 +88,8 @@
         dist.run_command('install_dist')
         name = dist.metadata['Name']
         return database.get_distribution(name) is not None
-    except (IOError, os.error, PackagingError, CCompilerError):
-        raise ValueError("Failed to install, " + str(sys.exc_info()[1]))
+    except (IOError, os.error, PackagingError, CCompilerError), msg:
+        raise ValueError("Failed to install, " + str(msg))
 
 
 def _install_dist(dist, path):
@@ -160,9 +160,9 @@
         try:
             func(source_dir)
             return True
-        except ValueError:
+        except ValueError, err:
             # failed to install
-            logger.info(str(sys.exc_info()[1]))
+            logger.info(str(err))
             return False
     finally:
         os.chdir(old_dir)
@@ -187,8 +187,8 @@
         try:
             _install_dist(dist, path)
             installed_dists.append(dist)
-        except Exception:
-            logger.info('Failed: %s', sys.exc_info()[1])
+        except Exception, e:
+            logger.info('Failed: %s', e)
 
             # reverting
             for installed_dist in installed_dists:
@@ -396,8 +396,8 @@
     def _move_file(source, target):
         try:
             os.rename(source, target)
-        except OSError:
-            return sys.exc_info()[1]
+        except OSError, err:
+            return err
         return None
 
     success = True
@@ -496,9 +496,11 @@
     # trying to write a file there
     try:
         testfile = tempfile.NamedTemporaryFile(suffix=project,
-                dir=purelib_path)
-        testfile.write('test')
-        testfile.close()
+                                               dir=purelib_path)
+        try:
+            testfile.write('test')
+        finally:
+            testfile.close()
     except OSError:
         # FIXME this should check the errno, or be removed altogether (race
         # condition: the directory permissions could be changed between here
@@ -523,8 +525,7 @@
         install_from_infos(install_path,
                            info['install'], info['remove'], info['conflict'])
 
-    except InstallationConflict:
-        e = sys.exc_info()[1]
+    except InstallationConflict, e:
         if logger.isEnabledFor(logging.INFO):
             projects = ('%r %s' % (p.name, p.version) for p in e.args[0])
             logger.info('%r conflicts with %s', project, ','.join(projects))
diff --git a/distutils2/manifest.py b/distutils2/manifest.py
--- a/distutils2/manifest.py
+++ b/distutils2/manifest.py
@@ -8,13 +8,12 @@
 # XXX todo: document + add tests
 import re
 import os
-import sys
 import fnmatch
 
 from distutils2 import logger
 from distutils2.util import write_file, convert_path
 from distutils2.errors import (PackagingTemplateError,
-                              PackagingInternalError)
+                               PackagingInternalError)
 
 __all__ = ['Manifest']
 
@@ -90,8 +89,8 @@
                 continue
             try:
                 self._process_template_line(line)
-            except PackagingTemplateError:
-                logger.warning("%s, %s", path_or_file, sys.exc_info()[1])
+            except PackagingTemplateError, msg:
+                logger.warning("%s, %s", path_or_file, msg)
 
     def write(self, path):
         """Write the file list in 'self.filelist' (presumably as filled in
@@ -100,8 +99,10 @@
         """
         if os.path.isfile(path):
             fp = open(path)
-            first_line = fp.readline()
-            fp.close()
+            try:
+                first_line = fp.readline()
+            finally:
+                fp.close()
 
             if first_line != '# file GENERATED by distutils2, do NOT edit\n':
                 logger.info("not writing to manually maintained "
@@ -122,9 +123,11 @@
         """
         logger.info("reading manifest file %r", path)
         manifest = open(path)
-        for line in manifest.readlines():
-            self.append(line)
-        manifest.close()
+        try:
+            for line in manifest.readlines():
+                self.append(line)
+        finally:
+            manifest.close()
 
     def exclude_pattern(self, pattern, anchor=True, prefix=None,
                         is_regex=False):
diff --git a/distutils2/markers.py b/distutils2/markers.py
--- a/distutils2/markers.py
+++ b/distutils2/markers.py
@@ -6,6 +6,11 @@
 
 from tokenize import generate_tokens, NAME, OP, STRING, ENDMARKER
 from StringIO import StringIO as BytesIO
+try:
+    python_implementation = platform.python_implementation()
+except AttributeError:
+    # FIXME import from compat
+    python_implementation = 'CPython'
 
 __all__ = ['interpret']
 
@@ -24,10 +29,7 @@
 def _operate(operation, x, y):
     return _OPERATORS[operation](x, y)
 
-try:
-    python_implementation = platform.python_implementation()
-except AttributeError: #<2.6 - assume CPython?
-    python_implementation = 'CPython'
+
 # restricted set of variables
 _VARS = {'sys.platform': sys.platform,
          'python_version': sys.version[:3],
diff --git a/distutils2/metadata.py b/distutils2/metadata.py
--- a/distutils2/metadata.py
+++ b/distutils2/metadata.py
@@ -3,8 +3,8 @@
 Supports all metadata formats (1.0, 1.1, 1.2).
 """
 
+import re
 import codecs
-import re
 import logging
 
 from StringIO import StringIO
@@ -12,10 +12,10 @@
 from distutils2 import logger
 from distutils2.markers import interpret
 from distutils2.version import (is_valid_predicate, is_valid_version,
-                               is_valid_versions)
+                                is_valid_versions)
 from distutils2.errors import (MetadataMissingError,
-                              MetadataConflictError,
-                              MetadataUnrecognizedVersionError)
+                               MetadataConflictError,
+                               MetadataUnrecognizedVersionError)
 
 try:
     # docutils is installed
@@ -311,8 +311,10 @@
     def read(self, filepath):
         """Read the metadata values from a file path."""
         fp = codecs.open(filepath, 'r', encoding='utf-8')
-        self.read_file(fp)
-        fp.close()
+        try:
+            self.read_file(fp)
+        finally:
+            fp.close()
 
     def read_file(self, fileob):
         """Read the metadata values from a file object."""
@@ -335,8 +337,10 @@
     def write(self, filepath):
         """Write the metadata fields to filepath."""
         fp = codecs.open(filepath, 'w', encoding='utf-8')
-        self.write_file(fp)
-        fp.close()
+        try:
+            self.write_file(fp)
+        finally:
+            fp.close()
 
     def write_file(self, fileobject):
         """Write the PKG-INFO format data to a file object."""
diff --git a/distutils2/pypi/dist.py b/distutils2/pypi/dist.py
--- a/distutils2/pypi/dist.py
+++ b/distutils2/pypi/dist.py
@@ -10,7 +10,7 @@
 import re
 try:
     import hashlib
-except ImportError: #<2.5
+except ImportError:
     from distutils2._backport import hashlib
 import tempfile
 import urllib
@@ -328,9 +328,11 @@
         expected_hashval = self.url['hashval']
         if None not in (expected_hashval, hashname):
             f = open(filename, 'rb')
-            hashval = hashlib.new(hashname)
-            hashval.update(f.read())
-            f.close()
+            try:
+                hashval = hashlib.new(hashname)
+                hashval.update(f.read())
+            finally:
+                f.close()
 
             if hashval.hexdigest() != expected_hashval:
                 raise HashDoesNotMatch("got %s instead of %s"
diff --git a/distutils2/pypi/simple.py b/distutils2/pypi/simple.py
--- a/distutils2/pypi/simple.py
+++ b/distutils2/pypi/simple.py
@@ -161,16 +161,18 @@
         Return a list of names.
         """
         index = self._open_url(self.index_url)
-        if '*' in name:
-            name.replace('*', '.*')
-        else:
-            name = "%s%s%s" % ('*.?', name, '*.?')
-        name = name.replace('*', '[^<]*')  # avoid matching end tag
-        projectname = re.compile('<a[^>]*>(%s)</a>' % name, re.I)
-        matching_projects = []
+        try:
+            if '*' in name:
+                name.replace('*', '.*')
+            else:
+                name = "%s%s%s" % ('*.?', name, '*.?')
+            name = name.replace('*', '[^<]*')  # avoid matching end tag
+            projectname = re.compile('<a[^>]*>(%s)</a>' % name, re.I)
+            matching_projects = []
 
-        index_content = index.read()
-        index.close()
+            index_content = index.read()
+        finally:
+            index.close()
 
         # FIXME should use bytes I/O and regexes instead of decoding
         index_content = index_content.decode()
@@ -236,7 +238,9 @@
         self._mirrors_used.add(self.index_url)
         index_url = self._mirrors.pop()
         # XXX use urlparse for a real check of missing scheme part
-        if not index_url.startswith(("http://", "https://", "file://")):
+        if not (index_url.startswith("http://") or
+                index_url.startswith("https://") or
+                index_url.startswith("file://")):
             index_url = "http://%s" % index_url
 
         if not index_url.endswith("/simple"):
@@ -327,8 +331,7 @@
                             try:
                                 infos = get_infos_from_url(link, project_name,
                                             is_external=self.index_url not in url)
-                            except CantParseArchiveName:
-                                e = sys.exc_info()[1]
+                            except CantParseArchiveName, e:
                                 if self.verbose:
                                     logger.warning(
                                         "version has not been parsed: %s", e)
@@ -410,7 +413,7 @@
 
         # authentication stuff
         if scheme in ('http', 'https'):
-            auth, host = urlparse.splituser(netloc)
+            auth, host = urllib2.splituser(netloc)
         else:
             auth = None
 
@@ -432,21 +435,17 @@
         request.add_header('User-Agent', USER_AGENT)
         try:
             fp = urllib2.urlopen(request)
-        except (ValueError, httplib.InvalidURL):
-            v = sys.exc_info()[1]
+        except (ValueError, httplib.InvalidURL), v:
             msg = ' '.join([str(arg) for arg in v.args])
             raise PackagingPyPIError('%s %s' % (url, msg))
-        except urllib2.HTTPError:
-            return sys.exc_info()[1]
-        except urllib2.URLError:
-            v = sys.exc_info()[1]
+        except urllib2.HTTPError, v:
+            return v
+        except urllib2.URLError, v:
             raise DownloadError("Download error for %s: %s" % (url, v.reason))
-        except httplib.BadStatusLine:
-            v = sys.exc_info()[1]
+        except httplib.BadStatusLine, v:
             raise DownloadError('%s returned a bad status line. '
                 'The server might be down, %s' % (url, v.line))
-        except httplib.HTTPException:
-            v = sys.exc_info()[1]
+        except httplib.HTTPException, v:
             raise DownloadError("Download error for %s: %s" % (url, v))
         except socket.timeout:
             raise DownloadError("The server timeouted")
diff --git a/distutils2/pypi/wrapper.py b/distutils2/pypi/wrapper.py
--- a/distutils2/pypi/wrapper.py
+++ b/distutils2/pypi/wrapper.py
@@ -31,8 +31,8 @@
             try:
                 response = method(*args, **kwargs)
                 retry = False
-            except Exception:
-                exception = sys.exc_info()[1]
+            except Exception, e:
+                exception = e
             if not retry:
                 break
         if retry and exception:
diff --git a/distutils2/pypi/xmlrpc.py b/distutils2/pypi/xmlrpc.py
--- a/distutils2/pypi/xmlrpc.py
+++ b/distutils2/pypi/xmlrpc.py
@@ -13,7 +13,7 @@
 from distutils2.version import get_version_predicate
 from distutils2.pypi.base import BaseClient
 from distutils2.pypi.errors import (ProjectNotFound, InvalidSearchField,
-                                   ReleaseNotFound)
+                                    ReleaseNotFound)
 from distutils2.pypi.dist import ReleaseInfo
 
 __all__ = ['Client', 'DEFAULT_XMLRPC_INDEX_URL']
@@ -171,8 +171,7 @@
                 project.add_release(release=ReleaseInfo(p['name'],
                     p['version'], metadata={'summary': p['summary']},
                     index=self._index))
-            except IrrationalVersionError:
-                e = sys.exc_info()[1]
+            except IrrationalVersionError, e:
                 logger.warning("Irrational version error found: %s", e)
         return [self._projects[p['name'].lower()] for p in projects]
 
diff --git a/distutils2/run.py b/distutils2/run.py
--- a/distutils2/run.py
+++ b/distutils2/run.py
@@ -15,8 +15,8 @@
 from distutils2.depgraph import generate_graph
 from distutils2.fancy_getopt import FancyGetopt
 from distutils2.errors import (PackagingArgError, PackagingError,
-                              PackagingModuleError, PackagingClassError,
-                              CCompilerError)
+                               PackagingModuleError, PackagingClassError,
+                               CCompilerError)
 
 
 command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
@@ -473,8 +473,8 @@
         # it takes.
         try:
             cmd_class = get_command_class(command)
-        except PackagingModuleError:
-            raise PackagingArgError(sys.exc_info()[1])
+        except PackagingModuleError, msg:
+            raise PackagingArgError(msg)
 
         # XXX We want to push this in distutils2.command
         #
@@ -674,22 +674,21 @@
     old_level = logger.level
     old_handlers = list(logger.handlers)
     try:
-        dispatcher = Dispatcher(args)
-        if dispatcher.action is None:
-            return
-        return dispatcher()
-    except KeyboardInterrupt:
-        logger.info('interrupted')
-        return 1
-    except (IOError, os.error, PackagingError, CCompilerError):
-        logger.exception(sys.exc_info()[1])
-        return 1
-    except:
+        try:
+            dispatcher = Dispatcher(args)
+            if dispatcher.action is None:
+                return
+            return dispatcher()
+        except KeyboardInterrupt:
+            logger.info('interrupted')
+            return 1
+        except (IOError, os.error, PackagingError, CCompilerError), exc:
+            logger.exception(exc)
+            return 1
+    finally:
         logger.setLevel(old_level)
         logger.handlers[:] = old_handlers
-        raise
-    logger.setLevel(old_level)
-    logger.handlers[:] = old_handlers
+
 
 if __name__ == '__main__':
     sys.exit(main())
diff --git a/distutils2/tests/__main__.py b/distutils2/tests/__main__.py
--- a/distutils2/tests/__main__.py
+++ b/distutils2/tests/__main__.py
@@ -4,8 +4,8 @@
 
 import os
 import sys
-import unittest2
-from .support import run_unittest, reap_children, reap_threads
+from distutils2.tests import unittest
+from distutils2.tests.support import reap_children, reap_threads, run_unittest
 
 
 @reap_threads
@@ -13,7 +13,9 @@
     try:
         start_dir = os.path.dirname(__file__)
         top_dir = os.path.dirname(os.path.dirname(start_dir))
-        test_loader = unittest2.TestLoader()
+        test_loader = unittest.TestLoader()
+        # XXX find out how to use unittest.main, to get command-line options
+        # (failfast, catch, etc.)
         run_unittest(test_loader.discover(start_dir, top_level_dir=top_dir))
     finally:
         reap_children()
diff --git a/distutils2/tests/pypi_server.py b/distutils2/tests/pypi_server.py
--- a/distutils2/tests/pypi_server.py
+++ b/distutils2/tests/pypi_server.py
@@ -30,19 +30,21 @@
 """
 
 import os
-import queue
+import Queue
 import select
 import threading
-import socketserver
+import SocketServer
+from BaseHTTPServer import HTTPServer
+from SimpleHTTPServer import SimpleHTTPRequestHandler
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+
+from distutils2.tests import unittest
+
 try:
     from functools import wraps
 except ImportError:
     from distutils2._backport.functools import wraps
 
-from http.server import HTTPServer, SimpleHTTPRequestHandler
-from xmlrpc.server import SimpleXMLRPCServer
-
-from distutils2.tests import unittest
 
 PYPI_DEFAULT_STATIC_PATH = os.path.join(
     os.path.dirname(os.path.abspath(__file__)), 'pypiserver')
@@ -117,7 +119,7 @@
             self.server = HTTPServer(('127.0.0.1', 0), PyPIRequestHandler)
             self.server.RequestHandlerClass.pypi_server = self
 
-            self.request_queue = queue.Queue()
+            self.request_queue = Queue.Queue()
             self._requests = []
             self.default_response_status = 404
             self.default_response_headers = [('Content-type', 'text/plain')]
@@ -154,7 +156,7 @@
     def stop(self):
         """self shutdown is not supported for python < 2.6"""
         self._run = False
-        if self.is_alive():
+        if self.isAlive():
             self.join()
         self.server.server_close()
 
@@ -171,7 +173,7 @@
         while True:
             try:
                 self._requests.append(self.request_queue.get_nowait())
-            except queue.Empty:
+            except Queue.Empty:
                 break
         return self._requests
 
@@ -275,7 +277,7 @@
 class PyPIXMLRPCServer(SimpleXMLRPCServer):
     def server_bind(self):
         """Override server_bind to store the server name."""
-        socketserver.TCPServer.server_bind(self)
+        SocketServer.TCPServer.server_bind(self)
         host, port = self.socket.getsockname()[:2]
         self.server_port = port
 
diff --git a/distutils2/tests/test_command_build.py b/distutils2/tests/test_command_build.py
--- a/distutils2/tests/test_command_build.py
+++ b/distutils2/tests/test_command_build.py
@@ -3,7 +3,7 @@
 import sys
 
 from distutils2.command.build import build
-from sysconfig import get_platform
+from distutils2._backport.sysconfig import get_platform
 from distutils2.tests import unittest, support
 
 
diff --git a/distutils2/tests/test_command_build_ext.py b/distutils2/tests/test_command_build_ext.py
--- a/distutils2/tests/test_command_build_ext.py
+++ b/distutils2/tests/test_command_build_ext.py
@@ -5,6 +5,7 @@
 import textwrap
 from StringIO import StringIO
 from distutils2._backport import sysconfig
+from distutils2._backport.sysconfig import _CONFIG_VARS
 from distutils2.dist import Distribution
 from distutils2.errors import (UnknownFileError, CompileError,
                               PackagingPlatformError)
@@ -36,9 +37,10 @@
         filename = _get_source_filename()
         if os.path.exists(filename):
             shutil.copy(filename, self.tmp_dir)
-        self.old_user_base = site.USER_BASE
-        site.USER_BASE = self.mkdtemp()
-        build_ext.USER_BASE = site.USER_BASE
+        if sys.version > "2.6":
+            self.old_user_base = site.USER_BASE
+            site.USER_BASE = self.mkdtemp()
+            build_ext.USER_BASE = site.USER_BASE
 
     def tearDown(self):
         # Get everything back to normal
@@ -122,7 +124,6 @@
         old = sys.platform
 
         sys.platform = 'sunos'  # fooling finalize_options
-        from sysconfig import _CONFIG_VARS
 
         old_var = _CONFIG_VARS.get('Py_ENABLE_SHARED')
         _CONFIG_VARS['Py_ENABLE_SHARED'] = 1
diff --git a/distutils2/tests/test_command_upload_docs.py b/distutils2/tests/test_command_upload_docs.py
--- a/distutils2/tests/test_command_upload_docs.py
+++ b/distutils2/tests/test_command_upload_docs.py
@@ -18,7 +18,7 @@
     from distutils2.tests.pypi_server import PyPIServerTestCase
 except ImportError:
     threading = None
-    PyPIServerTestCase = object
+    PyPIServerTestCase = unittest.TestCase
 
 
 PYPIRC = """\
@@ -32,8 +32,7 @@
 """
 
 
-class UploadDocsTestCase(unittest.TestCase,
-                         support.TempdirManager,
+class UploadDocsTestCase(support.TempdirManager,
                          support.EnvironRestorer,
                          support.LoggingCatcher,
                          PyPIServerTestCase):
diff --git a/distutils2/tests/test_install.py b/distutils2/tests/test_install.py
--- a/distutils2/tests/test_install.py
+++ b/distutils2/tests/test_install.py
@@ -1,7 +1,6 @@
 """Tests for the distutils2.install module."""
 import os
 import logging
-from sysconfig import is_python_build
 from tempfile import mkstemp
 
 from distutils2 import install
@@ -9,6 +8,8 @@
 from distutils2.metadata import Metadata
 from distutils2.tests.support import (LoggingCatcher, TempdirManager, unittest,
                                      fake_dec)
+from distutils2._backport.sysconfig import is_python_build
+
 try:
     import threading
     from distutils2.tests.pypi_server import use_xmlrpc_server
diff --git a/distutils2/tests/test_mixin2to3.py b/distutils2/tests/test_mixin2to3.py
--- a/distutils2/tests/test_mixin2to3.py
+++ b/distutils2/tests/test_mixin2to3.py
@@ -1,3 +1,4 @@
+import sys
 import textwrap
 
 from distutils2.tests import unittest, support
@@ -8,8 +9,7 @@
                         support.LoggingCatcher,
                         unittest.TestCase):
 
-    #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
-    @unittest.skipIf(True, 'Not needed for backport')
+    @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
     def test_convert_code_only(self):
         # used to check if code gets converted properly.
         code = "print 'test'"
@@ -28,8 +28,7 @@
 
         self.assertEqual(expected, converted)
 
-    #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
-    @unittest.skipIf(True, 'Not needed for backport')
+    @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
     def test_doctests_only(self):
         # used to check if doctests gets converted properly.
         doctest = textwrap.dedent('''\
@@ -62,8 +61,7 @@
 
         self.assertEqual(expected, converted)
 
-    #@unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
-    @unittest.skipIf(True, 'Not needed for backport')
+    @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
     def test_additional_fixers(self):
         # used to check if use_2to3_fixers works
         code = 'type(x) is not T'
diff --git a/distutils2/tests/test_pypi_simple.py b/distutils2/tests/test_pypi_simple.py
--- a/distutils2/tests/test_pypi_simple.py
+++ b/distutils2/tests/test_pypi_simple.py
@@ -12,9 +12,9 @@
                                      fake_dec)
 
 try:
-    import _thread
+    import thread as _thread
     from distutils2.tests.pypi_server import (use_pypi_server, PyPIServer,
-                                             PYPI_DEFAULT_STATIC_PATH)
+                                              PYPI_DEFAULT_STATIC_PATH)
 except ImportError:
     _thread = None
     use_pypi_server = fake_dec
diff --git a/distutils2/util.py b/distutils2/util.py
--- a/distutils2/util.py
+++ b/distutils2/util.py
@@ -180,8 +180,8 @@
 
     try:
         return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
-    except KeyError:
-        raise ValueError("invalid variable '$%s'" % sys.exc_info()[1])
+    except KeyError, e:
+        raise ValueError("invalid variable '$%s'" % e)
 
 
 # Needed by 'split_quoted()'
@@ -334,7 +334,7 @@
     """
     # nothing is done if sys.dont_write_bytecode is True
     # FIXME this should not raise an error
-    if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode:
+    if getattr(sys, 'dont_write_bytecode', False):
         raise PackagingByteCompileError('byte-compiling is disabled.')
 
     # First, if the caller didn't force us into direct or indirect mode,
@@ -354,7 +354,7 @@
     # run it with the appropriate flags.
     if not direct:
         from tempfile import mkstemp
-        # XXX script_fd may leak, use something better than mkstemp
+        # XXX use something better than mkstemp
         script_fd, script_name = mkstemp(".py")
         os.close(script_fd)
         script_fd = None
@@ -365,33 +365,36 @@
             else:
                 script = codecs.open(script_name, "w", encoding='utf-8')
 
-            script.write("""\
+            try:
+                script.write("""\
 from distutils2.util import byte_compile
 files = [
 """)
 
-            # XXX would be nice to write absolute filenames, just for
-            # safety's sake (script should be more robust in the face of
-            # chdir'ing before running it).  But this requires abspath'ing
-            # 'prefix' as well, and that breaks the hack in build_lib's
-            # 'byte_compile()' method that carefully tacks on a trailing
-            # slash (os.sep really) to make sure the prefix here is "just
-            # right".  This whole prefix business is rather delicate -- the
-            # problem is that it's really a directory, but I'm treating it
-            # as a dumb string, so trailing slashes and so forth matter.
+                # XXX would be nice to write absolute filenames, just for
+                # safety's sake (script should be more robust in the face of
+                # chdir'ing before running it).  But this requires abspath'ing
+                # 'prefix' as well, and that breaks the hack in build_lib's
+                # 'byte_compile()' method that carefully tacks on a trailing
+                # slash (os.sep really) to make sure the prefix here is "just
+                # right".  This whole prefix business is rather delicate -- the
+                # problem is that it's really a directory, but I'm treating it
+                # as a dumb string, so trailing slashes and so forth matter.
 
-            #py_files = map(os.path.abspath, py_files)
-            #if prefix:
-            #    prefix = os.path.abspath(prefix)
+                #py_files = map(os.path.abspath, py_files)
+                #if prefix:
+                #    prefix = os.path.abspath(prefix)
 
-            script.write(",\n".join(map(repr, py_files)) + "]\n")
-            script.write("""
+                script.write(",\n".join(map(repr, py_files)) + "]\n")
+                script.write("""
 byte_compile(files, optimize=%r, force=%r,
              prefix=%r, base_dir=%r,
              verbose=%r, dry_run=False,
              direct=True)
 """ % (optimize, force, prefix, base_dir, verbose))
-        script.close()
+            finally:
+                script.close()
+
         cmd = [sys.executable, script_name]
         if optimize == 1:
             cmd.insert(1, "-O")
@@ -553,9 +556,11 @@
     *contents* is a sequence of strings without line terminators.
     """
     f = open(filename, "w")
-    for line in contents:
-        f.write(line + "\n")
-    f.close()
+    try:
+        for line in contents:
+            f.write(line + "\n")
+    finally:
+        f.close()
 
 def _is_package(path):
     return os.path.isdir(path) and os.path.isfile(
@@ -657,8 +662,8 @@
     for part in parts[1:]:
         try:
             ret = getattr(ret, part)
-        except AttributeError:
-            raise ImportError(sys.exc_info()[1])
+        except AttributeError, exc:
+            raise ImportError(exc)
 
     return ret
 
@@ -775,6 +780,7 @@
     _cfg_target = None
     _cfg_target_split = None
 
+
 def spawn(cmd, search_path=True, verbose=0, dry_run=False, env=None):
     """Run another program specified as a command list 'cmd' in a new process.
 
@@ -872,11 +878,12 @@
     """Create a default .pypirc file."""
     rc = get_pypirc_path()
     f = open(rc, 'w')
-    f.write(DEFAULT_PYPIRC % (username, password))
-    f.close()
-
     try:
-        os.chmod(rc, 00600)
+        f.write(DEFAULT_PYPIRC % (username, password))
+    finally:
+        f.close()
+    try:
+        os.chmod(rc, 0600)
     except OSError:
         # should do something better here
         pass
@@ -1084,8 +1091,10 @@
         raise PackagingFileError("file '%s' does not exist" %
                                  os.path.abspath(path))
     f = codecs.open(path, encoding='utf-8')
-    config.readfp(f)
-    f.close()
+    try:
+        config.readfp(f)
+    finally:
+        f.close()
 
     kwargs = {}
     for arg in D1_D2_SETUP_ARGS:
@@ -1108,8 +1117,10 @@
                     in_cfg_value = []
                     for filename in filenames:
                         fp = open(filename)
-                        in_cfg_value.append(fp.read())
-                        fp.close()
+                        try:
+                            in_cfg_value.append(fp.read())
+                        finally:
+                            fp.close()
                     in_cfg_value = '\n\n'.join(in_cfg_value)
             else:
                 continue
@@ -1147,8 +1158,10 @@
         raise PackagingFileError("a setup.py file already exists")
 
     fp = codecs.open("setup.py", "w", encoding='utf-8')
-    fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)})
-    fp.close()
+    try:
+        fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)})
+    finally:
+        fp.close()
 
 
 # Taken from the pip project
@@ -1168,26 +1181,29 @@
 def _parse_record_file(record_file):
     distinfo, extra_metadata, installed = ({}, [], [])
     rfile = open(record_file, 'r')
-    for path in rfile:
-        path = path.strip()
-        if path.endswith('egg-info') and os.path.isfile(path):
-            distinfo_dir = path.replace('egg-info', 'dist-info')
-            metadata = path
-            egginfo = path
-        elif path.endswith('egg-info') and os.path.isdir(path):
-            distinfo_dir = path.replace('egg-info', 'dist-info')
-            egginfo = path
-            for metadata_file in os.listdir(path):
-                metadata_fpath = os.path.join(path, metadata_file)
-                if metadata_file == 'PKG-INFO':
-                    metadata = metadata_fpath
-                else:
-                    extra_metadata.append(metadata_fpath)
-        elif 'egg-info' in path and os.path.isfile(path):
-            # skip extra metadata files
-            continue
-        else:
-            installed.append(path)
+    try:
+        for path in rfile:
+            path = path.strip()
+            if path.endswith('egg-info') and os.path.isfile(path):
+                distinfo_dir = path.replace('egg-info', 'dist-info')
+                metadata = path
+                egginfo = path
+            elif path.endswith('egg-info') and os.path.isdir(path):
+                distinfo_dir = path.replace('egg-info', 'dist-info')
+                egginfo = path
+                for metadata_file in os.listdir(path):
+                    metadata_fpath = os.path.join(path, metadata_file)
+                    if metadata_file == 'PKG-INFO':
+                        metadata = metadata_fpath
+                    else:
+                        extra_metadata.append(metadata_fpath)
+            elif 'egg-info' in path and os.path.isfile(path):
+                # skip extra metadata files
+                continue
+            else:
+                installed.append(path)
+    finally:
+        rfile.close()
 
     distinfo['egginfo'] = egginfo
     distinfo['metadata'] = metadata
@@ -1204,25 +1220,29 @@
 
 def _write_record_file(record_path, installed_files):
     f = codecs.open(record_path, 'w', encoding='utf-8')
-    writer = csv.writer(f, delimiter=',', lineterminator=os.linesep,
-                        quotechar='"')
+    try:
+        writer = csv.writer(f, delimiter=',', lineterminator=os.linesep,
+                            quotechar='"')
 
-    for fpath in installed_files:
-        if fpath.endswith('.pyc') or fpath.endswith('.pyo'):
-            # do not put size and md5 hash, as in PEP-376
-            writer.writerow((fpath, '', ''))
-        else:
-            hash = hashlib.md5()
-            fp = open(fpath, 'rb')
-            hash.update(fp.read())
-            fp.close()
-            md5sum = hash.hexdigest()
-            size = os.path.getsize(fpath)
-            writer.writerow((fpath, md5sum, size))
+        for fpath in installed_files:
+            if fpath.endswith('.pyc') or fpath.endswith('.pyo'):
+                # do not put size and md5 hash, as in PEP-376
+                writer.writerow((fpath, '', ''))
+            else:
+                hash = hashlib.md5()
+                fp = open(fpath, 'rb')
+                try:
+                    hash.update(fp.read())
+                finally:
+                    fp.close()
+                md5sum = hash.hexdigest()
+                size = os.path.getsize(fpath)
+                writer.writerow((fpath, md5sum, size))
 
-    # add the RECORD file itself
-    writer.writerow((record_path, '', ''))
-    f.close()
+        # add the RECORD file itself
+        writer.writerow((record_path, '', ''))
+    finally:
+        f.close()
     return record_path
 
 
@@ -1258,8 +1278,10 @@
     installer_path = distinfo['installer_path']
     logger.info('creating %s', installer_path)
     f = open(installer_path, 'w')
-    f.write(installer)
-    f.close()
+    try:
+        f.write(installer)
+    finally:
+        f.close()
 
     if requested:
         requested_path = distinfo['requested_path']
@@ -1301,13 +1323,15 @@
 
 def _has_text(setup_py, installer):
     installer_pattern = re.compile('import %s|from %s' % (
-        installer[0], installer[1]))
+        installer[0], installer[0]))
     setup = codecs.open(setup_py, 'r', encoding='utf-8')
-    for line in setup:
-        if re.search(installer_pattern, line):
-            logger.debug("Found %s text in setup.py.", installer)
-            return True
-    setup.close()
+    try:
+        for line in setup:
+            if re.search(installer_pattern, line):
+                logger.debug("Found %s text in setup.py.", installer)
+                return True
+    finally:
+        setup.close()
     logger.debug("No %s text found in setup.py.", installer)
     return False
 
@@ -1315,8 +1339,10 @@
 def _has_required_metadata(setup_cfg):
     config = RawConfigParser()
     f = codecs.open(setup_cfg, 'r', encoding='utf8')
-    config.readfp(f)
-    f.close()
+    try:
+        config.readfp(f)
+    finally:
+        f.close()
     return (config.has_section('metadata') and
             'name' in config.options('metadata') and
             'version' in config.options('metadata'))
@@ -1377,7 +1403,7 @@
                                       _has_distutils_text(setup_py))
 
 
-def is_distutils2(path):
+def is_packaging(path):
     """Check if the project is based on distutils2
 
     :param path: path to source directory containing a setup.cfg file.
@@ -1398,7 +1424,7 @@
 
     Returns a string representing the best install method to use.
     """
-    if is_distutils2(path):
+    if is_packaging(path):
         return "distutils2"
     elif is_setuptools(path):
         return "setuptools"
@@ -1419,8 +1445,8 @@
               "cannot copy tree '%s': not a directory" % src)
     try:
         names = os.listdir(src)
-    except os.error:
-        errstr = sys.exc_info()[1][1]
+    except os.error, e:
+        errstr = e[1]
         if dry_run:
             names = []
         else:
@@ -1465,7 +1491,7 @@
 # I don't use os.makedirs because a) it's new to Python 1.5.2, and
 # b) it blows up if the directory already exists (I want to silently
 # succeed in that case).
-def _mkpath(name, mode=00777, verbose=True, dry_run=False):
+def _mkpath(name, mode=0777, verbose=True, dry_run=False):
     # Detect a common bug -- name is None
     if not isinstance(name, basestring):
         raise PackagingInternalError(
@@ -1506,8 +1532,7 @@
         if not dry_run:
             try:
                 os.mkdir(head, mode)
-            except OSError:
-                exc = sys.exc_info()[1]
+            except OSError, exc:
                 if not (exc.errno == errno.EEXIST and os.path.isdir(head)):
                     raise PackagingFileError(
                           "could not create '%s': %s" % (head, exc.args[-1]))
diff --git a/distutils2/version.py b/distutils2/version.py
--- a/distutils2/version.py
+++ b/distutils2/version.py
@@ -182,7 +182,6 @@
         return "%s('%s')" % (self.__class__.__name__, self)
 
     def _cannot_compare(self, other):
-        import pdb; pdb.set_trace()
         raise TypeError("cannot compare %s and %s"
                 % (type(self).__name__, type(other).__name__))
 

-- 
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list