A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from http://mail.python.org/pipermail/python-checkins/2010-October/098052.html below:

[Python-checkins] distutils2: merged

[Python-checkins] distutils2: mergedtarek.ziade python-checkins at python.org
Sat Oct 2 00:52:20 CEST 2010
tarek.ziade pushed 397f4622333b to distutils2:

http://hg.python.org/distutils2/rev/397f4622333b
changeset:   729:397f4622333b
tag:         tip
parent:      691:c7e47ada3eec
parent:      728:e94847294adf
user:        Tarek Ziade <tarek at ziade.org>
date:        Sat Oct 02 00:50:48 2010 +0200
summary:     merged
files:       distutils2/core.py, distutils2/tests/test_config.py, runtests-cov.py, runtests.py

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -7,6 +7,7 @@
 build/
 dist/
 _static/
+_build/
 *.swp
 .coverage
 .tox
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -9,6 +9,7 @@
 
 Thanks to:
 
+- Rajiv Abraham
 - Ali Afshar
 - Éric Araujo
 - Pior Bastida
@@ -19,12 +20,15 @@
 - Josip Djolonga
 - Yannick Gingras
 - Jeremy Kloth
+- Amos Latteier
 - Martin von Löwis
 - Carl Meyer
 - Alexis Métaireau
 - Zubin Mithra
+- Derek McTavish Mounce
 - Michael Mulich
 - George Peristerakis
+- Mathieu Perreault
 - Sean Reifschneider
 - Antoine Reversat
 - Luis Rojas
diff --git a/DEVNOTES.txt b/DEVNOTES.txt
--- a/DEVNOTES.txt
+++ b/DEVNOTES.txt
@@ -7,8 +7,3 @@
 
 - Always run tests.sh before you push a change. This implies
   that you have all Python versions installed from 2.4 to 2.7.
-
-- With Python 2.4, if you want to run tests with runtests.py, or run
-  just one test directly, be sure to run python2.4 setup.py build_ext
-  first, else tests won't find _hashlib or _md5. When using tests.sh,
-  build_ext is automatically done.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,284 @@
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
+as a successor of a language called ABC.  Guido remains Python's
+principal author, although it includes many contributions from others.
+
+In 1995, Guido continued his work on Python at the Corporation for
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
+in Reston, Virginia where he released several versions of the
+software.
+
+In May 2000, Guido and the Python core development team moved to
+BeOpen.com to form the BeOpen PythonLabs team.  In October of the same
+year, the PythonLabs team moved to Digital Creations (now Zope
+Corporation, see http://www.zope.com).  In 2001, the Python Software
+Foundation (PSF, see http://www.python.org/psf/) was formed, a
+non-profit organization created specifically to own Python-related
+Intellectual Property.  Zope Corporation is a sponsoring member of
+the PSF.
+
+All Python releases are Open Source (see http://www.opensource.org for
+the Open Source Definition).  Historically, most, but not all, Python
+releases have also been GPL-compatible; the table below summarizes
+the various releases.
+
+    Release         Derived     Year        Owner       GPL-
+                    from                                compatible? (1)
+
+    0.9.0 thru 1.2              1991-1995   CWI         yes
+    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes
+    1.6             1.5.2       2000        CNRI        no
+    2.0             1.6         2000        BeOpen.com  no
+    1.6.1           1.6         2001        CNRI        yes (2)
+    2.1             2.0+1.6.1   2001        PSF         no
+    2.0.1           2.0+1.6.1   2001        PSF         yes
+    2.1.1           2.1+2.0.1   2001        PSF         yes
+    2.2             2.1.1       2001        PSF         yes
+    2.1.2           2.1.1       2002        PSF         yes
+    2.1.3           2.1.2       2002        PSF         yes
+    2.2.1           2.2         2002        PSF         yes
+    2.2.2           2.2.1       2002        PSF         yes
+    2.2.3           2.2.2       2003        PSF         yes
+    2.3             2.2.2       2002-2003   PSF         yes
+    2.3.1           2.3         2002-2003   PSF         yes
+    2.3.2           2.3.1       2002-2003   PSF         yes
+    2.3.3           2.3.2       2002-2003   PSF         yes
+    2.3.4           2.3.3       2004        PSF         yes
+    2.3.5           2.3.4       2005        PSF         yes
+    2.4             2.3         2004        PSF         yes
+    2.4.1           2.4         2005        PSF         yes
+    2.4.2           2.4.1       2005        PSF         yes
+    2.4.3           2.4.2       2006        PSF         yes
+    2.4.4           2.4.3       2006        PSF         yes
+    2.5             2.4         2006        PSF         yes
+    2.5.1           2.5         2007        PSF         yes
+    2.5.2           2.5.1       2008        PSF         yes
+    2.5.3           2.5.2       2008        PSF         yes
+    2.6             2.5         2008        PSF         yes
+    2.6.1           2.6         2008        PSF         yes
+    2.6.2           2.6.1       2009        PSF         yes
+    2.6.3           2.6.2       2009        PSF         yes
+    2.6.4           2.6.3       2009        PSF         yes
+    2.6.5           2.6.4       2010        PSF         yes
+    3.0             2.6         2008        PSF         yes
+    3.0.1           3.0         2009        PSF         yes
+    3.1             3.0.1       2009        PSF         yes
+    3.1.1           3.1         2009        PSF         yes
+    3.1.2           3.1         2010        PSF         yes
+    3.2             3.1         2010        PSF         yes
+
+Footnotes:
+
+(1) GPL-compatible doesn't mean that we're distributing Python under
+    the GPL.  All Python licenses, unlike the GPL, let you distribute
+    a modified version without making your changes open source.  The
+    GPL-compatible licenses make it possible to combine Python with
+    other software that is released under the GPL; the others don't.
+
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
+    because its license has a choice of law clause.  According to
+    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
+    is "not incompatible" with the GPL.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+analyze, test, perform and/or display publicly, prepare derivative works,
+distribute, and otherwise use Python alone or in any derivative version,
+provided, however, that PSF's License Agreement and PSF's notice of copyright,
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+Python Software Foundation; All Rights Reserved" are retained in Python alone or
+in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions.  Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee.  This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party.  As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee.  Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement.  This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013.  This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement.  Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee.  This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+        ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands.  All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/distutils2/_backport/tests/__init__.py b/distutils2/_backport/tests/__init__.py
--- a/distutils2/_backport/tests/__init__.py
+++ b/distutils2/_backport/tests/__init__.py
@@ -1,7 +1,7 @@
 import os
 import sys
 
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 
 here = os.path.dirname(__file__) or os.curdir
diff --git a/distutils2/_backport/tests/test_pkgutil.py b/distutils2/_backport/tests/test_pkgutil.py
--- a/distutils2/_backport/tests/test_pkgutil.py
+++ b/distutils2/_backport/tests/test_pkgutil.py
@@ -12,8 +12,8 @@
 except ImportError:
     from distutils2._backport.hashlib import md5
 
-from test.test_support import run_unittest, TESTFN
-from distutils2.tests.support import unittest
+from test.test_support import TESTFN
+from distutils2.tests import unittest, run_unittest
 
 from distutils2._backport import pkgutil
 
@@ -39,10 +39,12 @@
         super(TestPkgUtilData, self).setUp()
         self.dirname = tempfile.mkdtemp()
         sys.path.insert(0, self.dirname)
+        pkgutil.disable_cache()
 
     def tearDown(self):
         super(TestPkgUtilData, self).tearDown()
         del sys.path[0]
+        pkgutil.enable_cache()
         shutil.rmtree(self.dirname)
 
     def test_getdata_filesys(self):
@@ -139,10 +141,12 @@
 
     def setUp(self):
         super(TestPkgUtilPEP302, self).setUp()
+        pkgutil.disable_cache()
         sys.meta_path.insert(0, self.MyTestImporter())
 
     def tearDown(self):
         del sys.meta_path[0]
+        pkgutil.enable_cache()
         super(TestPkgUtilPEP302, self).tearDown()
 
     def test_getdata_pep302(self):
@@ -168,6 +172,7 @@
         super(TestPkgUtilDistribution, self).setUp()
         self.fake_dists_path = os.path.abspath(
             os.path.join(os.path.dirname(__file__), 'fake_dists'))
+        pkgutil.disable_cache()
 
         self.distinfo_dirs = [os.path.join(self.fake_dists_path, dir)
             for dir in os.listdir(self.fake_dists_path)
@@ -214,6 +219,7 @@
         for distinfo_dir in self.distinfo_dirs:
             record_file = os.path.join(distinfo_dir, 'RECORD')
             open(record_file, 'w').close()
+        pkgutil.enable_cache()
         super(TestPkgUtilDistribution, self).tearDown()
 
     def test_instantiation(self):
@@ -322,6 +328,7 @@
 
     def setUp(self):
         super(TestPkgUtilPEP376, self).setUp()
+        pkgutil.disable_cache()
         # Setup the path environment with our fake distributions
         current_path = os.path.abspath(os.path.dirname(__file__))
         self.sys_path = sys.path[:]
@@ -330,6 +337,7 @@
 
     def tearDown(self):
         sys.path[:] = self.sys_path
+        pkgutil.enable_cache()
         super(TestPkgUtilPEP376, self).tearDown()
 
     def test_distinfo_dirname(self):
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
@@ -14,7 +14,8 @@
         get_config_var, get_config_vars, get_path, get_paths, get_platform,
         get_scheme_names, _main, _SCHEMES)
 
-from distutils2.tests.support import unittest, EnvironGuard
+from distutils2.tests import unittest
+from distutils2.tests.support import EnvironGuard
 from test.test_support import TESTFN, unlink
 try:
     from test.test_support import skip_unless_symlink
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
@@ -10,11 +10,11 @@
 from sysconfig import get_python_version
 
 from distutils2.core import Command
-from distutils2.dir_util import remove_tree
 from distutils2.version import StrictVersion
 from distutils2.errors import DistutilsOptionError
 from distutils2 import log
 from distutils2.util import get_platform
+from distutils2._backport.shutil import rmtree
 
 import msilib
 from msilib import schema, sequence, text
@@ -259,7 +259,9 @@
             self.distribution.dist_files.append(tup)
 
         if not self.keep_temp:
-            remove_tree(self.bdist_dir, dry_run=self.dry_run)
+            log.info("removing temporary build directory %s", self.bdist_dir)
+            if not self.dry_run:
+                rmtree(self.bdist_dir)
 
     def add_files(self):
         db = self.db
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
@@ -31,7 +31,7 @@
     HAS_USER_SITE = True
 
 if os.name == 'nt':
-    from distutils2.msvccompiler import get_build_version
+    from distutils2.compiler.msvccompiler import get_build_version
     MSVC_VERSION = int(get_build_version())
 
 # An extension name is just a dot-separated list of Python NAMEs (ie.
diff --git a/distutils2/compiler/msvccompiler.py b/distutils2/compiler/msvccompiler.py
--- a/distutils2/compiler/msvccompiler.py
+++ b/distutils2/compiler/msvccompiler.py
@@ -654,6 +654,6 @@
 if get_build_version() >= 8.0:
     log.debug("Importing new compiler from distutils.msvc9compiler")
     OldMSVCCompiler = MSVCCompiler
-    from distutils2.msvc9compiler import MSVCCompiler
+    from distutils2.compiler.msvc9compiler import MSVCCompiler
     # get_build_architecture not really relevant now we support cross-compile
-    from distutils2.msvc9compiler import MacroExpander
+    from distutils2.compiler.msvc9compiler import MacroExpander
diff --git a/distutils2/core.py b/distutils2/core.py
--- a/distutils2/core.py
+++ b/distutils2/core.py
@@ -199,9 +199,10 @@
     l = {}
     try:
         try:
-            sys.argv[0] = script_name
             if script_args is not None:
-                sys.argv[1:] = script_args
+                sys.argv = [script_name] + script_args
+            else:
+                sys.argv = [script_name]
             exec open(script_name, 'r').read() in g, l
         finally:
             sys.argv = save_argv
diff --git a/distutils2/tests/__init__.py b/distutils2/tests/__init__.py
--- a/distutils2/tests/__init__.py
+++ b/distutils2/tests/__init__.py
@@ -10,15 +10,26 @@
 distutils2.command.tests package, since command identification is done
 by import rather than matching pre-defined names.
 
-Utility code is included in distutils2.tests.support.  Always import
-unittest from that module, it will be the right version (standard
-library unittest for 2.7 and higher, third-party unittest2 release for
-older versions).
+Always import unittest from this module, it will be the right version
+(standard library unittest for 3.2 and higher, third-party unittest2
+release for older versions).
+
+Utility code is included in distutils2.tests.support.  
 """
 
 import os
 import sys
-from distutils2.tests.support import unittest
+
+if sys.version_info >= (3, 2):
+    # improved unittest package from 3.2's standard library
+    import unittest
+else:
+    try:
+        # external release of same package for older versions
+        import unittest2 as unittest
+    except ImportError:
+        sys.exit('Error: You have to install unittest2')
+
 
 from test.test_support import TESTFN    # use TESTFN from stdlib/test_support.
 
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
@@ -40,7 +40,7 @@
 from SimpleHTTPServer import SimpleHTTPRequestHandler
 from SimpleXMLRPCServer import SimpleXMLRPCServer
 
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 PYPI_DEFAULT_STATIC_PATH = os.path.dirname(os.path.abspath(__file__)) + "/pypiserver"
 
diff --git a/distutils2/tests/support.py b/distutils2/tests/support.py
--- a/distutils2/tests/support.py
+++ b/distutils2/tests/support.py
@@ -1,14 +1,10 @@
 """Support code for distutils2 test cases.
 
-Always import unittest from this module, it will be the right version
-(standard library unittest for 3.2 and higher, third-party unittest2
-release for older versions).
-
 Four helper classes are provided: LoggingCatcher, TempdirManager,
 EnvironGuard and WarningsCatcher. They are written to be used as mixins,
 e.g. ::
 
-    from distutils2.tests.support import unittest
+    from distutils2.tests import unittest
     from distutils2.tests.support import LoggingCatcher
 
     class SomeTestCase(LoggingCatcher, unittest.TestCase):
@@ -37,13 +33,7 @@
 from distutils2 import log
 from distutils2.dist import Distribution
 from distutils2.log import DEBUG, INFO, WARN, ERROR, FATAL
-
-if sys.version_info >= (3, 2):
-    # improved unittest package from 3.2's standard library
-    import unittest
-else:
-    # external release of same package for older versions
-    import unittest2 as unittest
+from distutils2.tests import unittest
 
 __all__ = ['LoggingCatcher', 'WarningsCatcher', 'TempdirManager',
            'EnvironGuard', 'DummyCommand', 'unittest']
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
@@ -3,8 +3,7 @@
 import logging
 
 import distutils2
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2.compat import Mixin2to3
 
 
diff --git a/distutils2/tests/test_bdist.py b/distutils2/tests/test_bdist.py
--- a/distutils2/tests/test_bdist.py
+++ b/distutils2/tests/test_bdist.py
@@ -6,8 +6,7 @@
 
 from distutils2.core import Distribution
 from distutils2.command.bdist import bdist
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2.util import find_executable
 from distutils2.errors import DistutilsExecError
 
diff --git a/distutils2/tests/test_bdist_dumb.py b/distutils2/tests/test_bdist_dumb.py
--- a/distutils2/tests/test_bdist_dumb.py
+++ b/distutils2/tests/test_bdist_dumb.py
@@ -10,8 +10,7 @@
 except ImportError:
     zlib = None
 
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
+from distutils2.tests import run_unittest, unittest
 
 from distutils2.core import Distribution
 from distutils2.command.bdist_dumb import bdist_dumb
diff --git a/distutils2/tests/test_bdist_msi.py b/distutils2/tests/test_bdist_msi.py
--- a/distutils2/tests/test_bdist_msi.py
+++ b/distutils2/tests/test_bdist_msi.py
@@ -3,8 +3,7 @@
 
 from distutils2.tests import run_unittest
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class BDistMSITestCase(support.TempdirManager,
                        support.LoggingCatcher,
diff --git a/distutils2/tests/test_bdist_wininst.py b/distutils2/tests/test_bdist_wininst.py
--- a/distutils2/tests/test_bdist_wininst.py
+++ b/distutils2/tests/test_bdist_wininst.py
@@ -1,10 +1,7 @@
 """Tests for distutils.command.bdist_wininst."""
 
-from distutils2.tests import run_unittest
-
+from distutils2.tests import unittest, support, run_unittest
 from distutils2.command.bdist_wininst import bdist_wininst
-from distutils2.tests import support
-from distutils2.tests.support import unittest
 
 class BuildWinInstTestCase(support.TempdirManager,
                            support.LoggingCatcher,
diff --git a/distutils2/tests/test_build.py b/distutils2/tests/test_build.py
--- a/distutils2/tests/test_build.py
+++ b/distutils2/tests/test_build.py
@@ -3,8 +3,7 @@
 import sys
 
 from distutils2.command.build import build
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 try:
     from sysconfig import get_platform
 except ImportError:
diff --git a/distutils2/tests/test_build_clib.py b/distutils2/tests/test_build_clib.py
--- a/distutils2/tests/test_build_clib.py
+++ b/distutils2/tests/test_build_clib.py
@@ -4,9 +4,8 @@
 
 from distutils2.command.build_clib import build_clib
 from distutils2.errors import DistutilsSetupError
-from distutils2.tests import support
+from distutils2.tests import unittest, support
 from distutils2.util import find_executable
-from distutils2.tests.support import unittest
 
 class BuildCLibTestCase(support.TempdirManager,
                         support.LoggingCatcher,
diff --git a/distutils2/tests/test_build_ext.py b/distutils2/tests/test_build_ext.py
--- a/distutils2/tests/test_build_ext.py
+++ b/distutils2/tests/test_build_ext.py
@@ -4,7 +4,7 @@
 from StringIO import StringIO
 
 import distutils2.tests
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 from distutils2.core import Extension, Distribution
 from distutils2.command.build_ext import build_ext
 from distutils2.tests import support
diff --git a/distutils2/tests/test_build_py.py b/distutils2/tests/test_build_py.py
--- a/distutils2/tests/test_build_py.py
+++ b/distutils2/tests/test_build_py.py
@@ -8,8 +8,7 @@
 from distutils2.core import Distribution
 from distutils2.errors import DistutilsFileError
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 
 class BuildPyTestCase(support.TempdirManager,
diff --git a/distutils2/tests/test_build_scripts.py b/distutils2/tests/test_build_scripts.py
--- a/distutils2/tests/test_build_scripts.py
+++ b/distutils2/tests/test_build_scripts.py
@@ -9,8 +9,7 @@
 except ImportError:
     from distutils2._backport import sysconfig
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 
 class BuildScriptsTestCase(support.TempdirManager,
diff --git a/distutils2/tests/test_ccompiler.py b/distutils2/tests/test_ccompiler.py
--- a/distutils2/tests/test_ccompiler.py
+++ b/distutils2/tests/test_ccompiler.py
@@ -4,8 +4,7 @@
 
 from distutils2.compiler.ccompiler import (gen_lib_options, CCompiler,
                                  get_default_compiler, customize_compiler)
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class FakeCompiler(object):
     def library_dir_option(self, dir):
diff --git a/distutils2/tests/test_check.py b/distutils2/tests/test_check.py
--- a/distutils2/tests/test_check.py
+++ b/distutils2/tests/test_check.py
@@ -2,8 +2,7 @@
 
 from distutils2.command.check import check
 from distutils2.metadata import _HAS_DOCUTILS
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2.errors import DistutilsSetupError
 
 class CheckTestCase(support.LoggingCatcher,
diff --git a/distutils2/tests/test_clean.py b/distutils2/tests/test_clean.py
--- a/distutils2/tests/test_clean.py
+++ b/distutils2/tests/test_clean.py
@@ -1,11 +1,8 @@
 """Tests for distutils.command.clean."""
-import sys
 import os
-import getpass
 
 from distutils2.command.clean import clean
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class cleanTestCase(support.TempdirManager,
                     support.LoggingCatcher,
diff --git a/distutils2/tests/test_cmd.py b/distutils2/tests/test_cmd.py
--- a/distutils2/tests/test_cmd.py
+++ b/distutils2/tests/test_cmd.py
@@ -5,7 +5,7 @@
 from distutils2.command.cmd import Command
 from distutils2.dist import Distribution
 from distutils2.errors import DistutilsOptionError
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 class MyCmd(Command):
     def initialize_options(self):
diff --git a/distutils2/tests/test_config.py b/distutils2/tests/test_config.py
--- a/distutils2/tests/test_config.py
+++ b/distutils2/tests/test_config.py
@@ -1,11 +1,10 @@
 # -*- encoding: utf8 -*-
 """Tests for distutils.config."""
+import os
 import sys
-import os
-import copy
+from StringIO import StringIO
 
-from distutils2.tests import support, run_unittest
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support, run_unittest
 
 
 SETUP_CFG = """
@@ -76,26 +75,28 @@
 class ConfigTestCase(support.TempdirManager,
                      unittest.TestCase):
 
+    def setUp(self):
+        super(ConfigTestCase, self).setUp()
+        self.addCleanup(setattr, sys, 'stdout', sys.stdout)
+        self.addCleanup(os.chdir, os.getcwd())
+
     def test_config(self):
         tempdir = self.mkdtemp()
-        setup_cfg = os.path.join(tempdir, 'setup.cfg')
-        f = open(setup_cfg, 'w')
-        try:
-            f.write(SETUP_CFG)
-        finally:
-            f.close()
+        os.chdir(tempdir)
+        self.write_file('setup.cfg', SETUP_CFG)
 
-        # trying to load the metadata now
-        old_args = copy.copy(sys.argv)
+        # try to load the metadata now
+        sys.stdout = StringIO()
         sys.argv[:] = ['setup.py', '--version']
-        old_wd = os.getcwd()
-        os.chdir(tempdir)
+        old_sys = sys.argv[:]
         try:
             from distutils2.core import setup
             dist = setup()
         finally:
-            os.chdir(old_wd)
-            sys.argv[:] = old_args
+            sys.argv[:] = old_sys
+
+        # sanity check
+        self.assertEqual(sys.stdout.getvalue(), '0.6.4' + os.linesep)
 
         # check what was done
         self.assertEqual(dist.metadata['Author'], 'Carl Meyer')
diff --git a/distutils2/tests/test_config_cmd.py b/distutils2/tests/test_config_cmd.py
--- a/distutils2/tests/test_config_cmd.py
+++ b/distutils2/tests/test_config_cmd.py
@@ -3,8 +3,7 @@
 import sys
 
 from distutils2.command.config import dump_file, config
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2 import log
 
 class ConfigTestCase(support.LoggingCatcher,
diff --git a/distutils2/tests/test_core.py b/distutils2/tests/test_core.py
--- a/distutils2/tests/test_core.py
+++ b/distutils2/tests/test_core.py
@@ -6,8 +6,7 @@
 import shutil
 import sys
 from distutils2.tests import captured_stdout
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 # setup script that uses __file__
 setup_using___file__ = """\
diff --git a/distutils2/tests/test_cygwinccompiler.py b/distutils2/tests/test_cygwinccompiler.py
--- a/distutils2/tests/test_cygwinccompiler.py
+++ b/distutils2/tests/test_cygwinccompiler.py
@@ -15,8 +15,7 @@
                                        CONFIG_H_UNCERTAIN, get_versions,
                                        get_msvcr, RE_VERSION)
 from distutils2.util import get_compiler_versions
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class CygwinCCompilerTestCase(support.TempdirManager,
                               unittest.TestCase):
diff --git a/distutils2/tests/test_depgraph.py b/distutils2/tests/test_depgraph.py
--- a/distutils2/tests/test_depgraph.py
+++ b/distutils2/tests/test_depgraph.py
@@ -1,7 +1,6 @@
 """Tests for distutils.depgraph """
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2 import depgraph
 from distutils2._backport import pkgutil
 
@@ -33,6 +32,7 @@
         path = os.path.abspath(path)
         self.sys_path = sys.path[:]
         sys.path[0:0] = [path]
+        pkgutil.disable_cache()
 
     def test_generate_graph(self):
         dists = []
@@ -178,6 +178,7 @@
 
     def tearDown(self):
         super(DepGraphTestCase, self).tearDown()
+        pkgutil.enable_cache()
         sys.path = self.sys_path
 
 def test_suite():
diff --git a/distutils2/tests/test_dist.py b/distutils2/tests/test_dist.py
--- a/distutils2/tests/test_dist.py
+++ b/distutils2/tests/test_dist.py
@@ -11,8 +11,8 @@
 from distutils2.command.cmd import Command
 from distutils2.errors import DistutilsModuleError, DistutilsOptionError
 from distutils2.tests import TESTFN, captured_stdout
-from distutils2.tests import support
-from distutils2.tests.support import unittest, create_distribution
+from distutils2.tests import support, unittest
+from distutils2.tests.support import create_distribution
 
 
 class test_dist(Command):
diff --git a/distutils2/tests/test_emxccompiler.py b/distutils2/tests/test_emxccompiler.py
--- a/distutils2/tests/test_emxccompiler.py
+++ b/distutils2/tests/test_emxccompiler.py
@@ -7,8 +7,7 @@
 
 from distutils2.compiler.emxccompiler import get_versions
 from distutils2.util import get_compiler_versions
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class EmxCCompilerTestCase(support.TempdirManager,
                            unittest.TestCase):
diff --git a/distutils2/tests/test_extension.py b/distutils2/tests/test_extension.py
--- a/distutils2/tests/test_extension.py
+++ b/distutils2/tests/test_extension.py
@@ -2,7 +2,7 @@
 import os
 
 from distutils2.extension import Extension
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 class ExtensionTestCase(unittest.TestCase):
 
diff --git a/distutils2/tests/test_index_dist.py b/distutils2/tests/test_index_dist.py
--- a/distutils2/tests/test_index_dist.py
+++ b/distutils2/tests/test_index_dist.py
@@ -4,7 +4,8 @@
 
 from distutils2.tests.pypi_server import use_pypi_server
 from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest, TempdirManager
+from distutils2.tests import unittest
+from distutils2.tests.support import TempdirManager
 from distutils2.version import VersionPredicate
 from distutils2.index.errors import HashDoesNotMatch, UnsupportedHashName
 from distutils2.index.dist import (ReleaseInfo, ReleasesList, DistInfo,
diff --git a/distutils2/tests/test_index_simple.py b/distutils2/tests/test_index_simple.py
--- a/distutils2/tests/test_index_simple.py
+++ b/distutils2/tests/test_index_simple.py
@@ -6,8 +6,7 @@
 import urllib2
 
 from distutils2.index.simple import Crawler
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2.tests.pypi_server import (use_pypi_server, PyPIServer,
                                           PYPI_DEFAULT_STATIC_PATH)
 
@@ -20,7 +19,7 @@
         urls
         """
         if hosts is None:
-            hosts = (server.full_address.strip("http://"),)
+            hosts = (server.full_address.replace("http://", ""),)
         kwargs['hosts'] = hosts
         return Crawler(server.full_address + base_url, *args,
             **kwargs)
diff --git a/distutils2/tests/test_index_xmlrpc.py b/distutils2/tests/test_index_xmlrpc.py
--- a/distutils2/tests/test_index_xmlrpc.py
+++ b/distutils2/tests/test_index_xmlrpc.py
@@ -1,8 +1,7 @@
 """Tests for the distutils2.index.xmlrpc module."""
 
 from distutils2.tests.pypi_server import use_xmlrpc_server
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, run_unittest
 from distutils2.index.xmlrpc import Client, InvalidSearchField, ProjectNotFound
 
 
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
@@ -17,8 +17,7 @@
 from distutils2.core import Distribution
 from distutils2.errors import DistutilsOptionError
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class InstallTestCase(support.TempdirManager,
                       support.EnvironGuard,
diff --git a/distutils2/tests/test_install_data.py b/distutils2/tests/test_install_data.py
--- a/distutils2/tests/test_install_data.py
+++ b/distutils2/tests/test_install_data.py
@@ -4,8 +4,7 @@
 import getpass
 
 from distutils2.command.install_data import install_data
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class InstallDataTestCase(support.TempdirManager,
                           support.LoggingCatcher,
diff --git a/distutils2/tests/test_install_distinfo.py b/distutils2/tests/test_install_distinfo.py
--- a/distutils2/tests/test_install_distinfo.py
+++ b/distutils2/tests/test_install_distinfo.py
@@ -7,8 +7,7 @@
 from distutils2.command.install_distinfo import install_distinfo
 from distutils2.core import Command
 from distutils2.metadata import DistributionMetadata
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 try:
     import hashlib
diff --git a/distutils2/tests/test_install_headers.py b/distutils2/tests/test_install_headers.py
--- a/distutils2/tests/test_install_headers.py
+++ b/distutils2/tests/test_install_headers.py
@@ -4,8 +4,7 @@
 import getpass
 
 from distutils2.command.install_headers import install_headers
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 class InstallHeadersTestCase(support.TempdirManager,
                              support.LoggingCatcher,
diff --git a/distutils2/tests/test_install_lib.py b/distutils2/tests/test_install_lib.py
--- a/distutils2/tests/test_install_lib.py
+++ b/distutils2/tests/test_install_lib.py
@@ -4,9 +4,8 @@
 
 from distutils2.command.install_lib import install_lib
 from distutils2.extension import Extension
-from distutils2.tests import support
+from distutils2.tests import unittest, support
 from distutils2.errors import DistutilsOptionError
-from distutils2.tests.support import unittest
 
 try:
     no_bytecode = sys.dont_write_bytecode
diff --git a/distutils2/tests/test_install_scripts.py b/distutils2/tests/test_install_scripts.py
--- a/distutils2/tests/test_install_scripts.py
+++ b/distutils2/tests/test_install_scripts.py
@@ -5,8 +5,7 @@
 from distutils2.command.install_scripts import install_scripts
 from distutils2.core import Distribution
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 
 class InstallScriptsTestCase(support.TempdirManager,
diff --git a/distutils2/tests/test_install_tools.py b/distutils2/tests/test_install_tools.py
--- a/distutils2/tests/test_install_tools.py
+++ b/distutils2/tests/test_install_tools.py
@@ -1,8 +1,7 @@
 """Tests for the distutils2.index.xmlrpc module."""
 
 from distutils2.tests.pypi_server import use_xmlrpc_server
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, run_unittest
 from distutils2.index.xmlrpc import Client
 from distutils2.install_tools import (get_infos,
                                           InstallationException)
diff --git a/distutils2/tests/test_manifest.py b/distutils2/tests/test_manifest.py
--- a/distutils2/tests/test_manifest.py
+++ b/distutils2/tests/test_manifest.py
@@ -4,8 +4,7 @@
 import logging
 
 from distutils2.tests import run_unittest
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 from distutils2.manifest import Manifest
 
 _MANIFEST = """\
diff --git a/distutils2/tests/test_metadata.py b/distutils2/tests/test_metadata.py
--- a/distutils2/tests/test_metadata.py
+++ b/distutils2/tests/test_metadata.py
@@ -6,8 +6,8 @@
 
 from distutils2.metadata import (DistributionMetadata, _interpret,
                                  PKG_INFO_PREFERRED_VERSION)
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest, LoggingCatcher
+from distutils2.tests import run_unittest, unittest
+from distutils2.tests.support import LoggingCatcher
 from distutils2.errors import (MetadataConflictError,
                                MetadataUnrecognizedVersionError)
 
diff --git a/distutils2/tests/test_msvc9compiler.py b/distutils2/tests/test_msvc9compiler.py
--- a/distutils2/tests/test_msvc9compiler.py
+++ b/distutils2/tests/test_msvc9compiler.py
@@ -3,8 +3,7 @@
 import os
 
 from distutils2.errors import DistutilsPlatformError
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 _MANIFEST = """\
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
diff --git a/distutils2/tests/test_pypi_server.py b/distutils2/tests/test_pypi_server.py
--- a/distutils2/tests/test_pypi_server.py
+++ b/distutils2/tests/test_pypi_server.py
@@ -4,7 +4,7 @@
 import os.path
 
 from distutils2.tests.pypi_server import PyPIServer, PYPI_DEFAULT_STATIC_PATH
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 
 class PyPIServerTest(unittest.TestCase):
diff --git a/distutils2/tests/test_pypi_versions.py b/distutils2/tests/test_pypi_versions.py
--- a/distutils2/tests/test_pypi_versions.py
+++ b/distutils2/tests/test_pypi_versions.py
@@ -18,8 +18,7 @@
    import pickle
 
 from distutils2.version import suggest_normalized_version
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, run_unittest
 
 def test_pypi():
     # FIXME need a better way to do that
diff --git a/distutils2/tests/test_register.py b/distutils2/tests/test_register.py
--- a/distutils2/tests/test_register.py
+++ b/distutils2/tests/test_register.py
@@ -16,9 +16,7 @@
 from distutils2.core import Distribution
 from distutils2.errors import DistutilsSetupError
 
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
+from distutils2.tests import unittest, support
 
 PYPIRC_NOPASSWORD = """\
 [distutils]
@@ -67,7 +65,9 @@
     def read(self):
         return 'xxx'
 
-class RegisterTestCase(support.TempdirManager, support.EnvironGuard,
+class RegisterTestCase(support.TempdirManager,
+                       support.EnvironGuard,
+                       support.LoggingCatcher,
                        unittest.TestCase):
 
     def setUp(self):
diff --git a/distutils2/tests/test_sdist.py b/distutils2/tests/test_sdist.py
--- a/distutils2/tests/test_sdist.py
+++ b/distutils2/tests/test_sdist.py
@@ -26,7 +26,7 @@
 from distutils2.command.sdist import sdist
 from distutils2.command.sdist import show_formats
 from distutils2.core import Distribution
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 from distutils2.errors import DistutilsExecError, DistutilsOptionError
 from distutils2.util import find_executable
 from distutils2.tests import support
diff --git a/distutils2/tests/test_test.py b/distutils2/tests/test_test.py
--- a/distutils2/tests/test_test.py
+++ b/distutils2/tests/test_test.py
@@ -9,9 +9,11 @@
 from operator import getitem, setitem, delitem
 from StringIO import StringIO
 from distutils2.core import Command
-from distutils2.tests.support import unittest, TempdirManager
+from distutils2.tests import unittest
+from distutils2.tests.support import TempdirManager, LoggingCatcher
 from distutils2.command.test import test
 from distutils2.dist import Distribution
+from distutils2._backport import pkgutil
 
 try:
     any
@@ -29,6 +31,7 @@
 here = os.path.dirname(os.path.abspath(__file__))
 
 class TestTest(TempdirManager,
+               LoggingCatcher,
                unittest.TestCase):
 
     def setUp(self):
@@ -39,6 +42,7 @@
         os.environ['PYTHONPATH'] = distutils2path + os.pathsep + self.old_pythonpath
 
     def tearDown(self):
+        pkgutil.clear_cache()
         os.environ['PYTHONPATH'] = self.old_pythonpath
         super(TestTest, self).tearDown()
 
@@ -73,7 +77,7 @@
 
         orig_has_attr = _hasattr(obj, attr)
         if orig_has_attr:
-            orig_val = _getattr(obj, attr) 
+            orig_val = _getattr(obj, attr)
 
         if delete is False:
             _setattr(obj, attr, new_val)
diff --git a/distutils2/tests/test_unixccompiler.py b/distutils2/tests/test_unixccompiler.py
--- a/distutils2/tests/test_unixccompiler.py
+++ b/distutils2/tests/test_unixccompiler.py
@@ -7,7 +7,7 @@
     from distutils2._backport import sysconfig
 
 from distutils2.compiler.unixccompiler import UnixCCompiler
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 class UnixCCompilerTestCase(unittest.TestCase):
 
diff --git a/distutils2/tests/test_upload.py b/distutils2/tests/test_upload.py
--- a/distutils2/tests/test_upload.py
+++ b/distutils2/tests/test_upload.py
@@ -6,9 +6,8 @@
 from distutils2.command.upload import upload
 from distutils2.core import Distribution
 
-from distutils2.tests import support
+from distutils2.tests import unittest, support
 from distutils2.tests.pypi_server import PyPIServer, PyPIServerTestCase
-from distutils2.tests.support import unittest
 
 
 PYPIRC_NOPASSWORD = """\
diff --git a/distutils2/tests/test_upload_docs.py b/distutils2/tests/test_upload_docs.py
--- a/distutils2/tests/test_upload_docs.py
+++ b/distutils2/tests/test_upload_docs.py
@@ -16,9 +16,8 @@
 from distutils2.core import Distribution
 from distutils2.errors import DistutilsFileError, DistutilsOptionError
 
-from distutils2.tests import support
+from distutils2.tests import unittest, support
 from distutils2.tests.pypi_server import PyPIServer, PyPIServerTestCase
-from distutils2.tests.support import unittest
 
 
 EXPECTED_MULTIPART_OUTPUT = "\r\n".join([
diff --git a/distutils2/tests/test_util.py b/distutils2/tests/test_util.py
--- a/distutils2/tests/test_util.py
+++ b/distutils2/tests/test_util.py
@@ -7,7 +7,7 @@
 import time
 
 from distutils2.tests import captured_stdout
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 from distutils2.errors import (DistutilsPlatformError,
                                DistutilsByteCompileError,
                                DistutilsFileError,
@@ -21,8 +21,7 @@
                              read_pypirc, resolve_name)
 
 from distutils2 import util
-from distutils2.tests import support
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest, support
 
 
 PYPIRC = """\
diff --git a/distutils2/tests/test_version.py b/distutils2/tests/test_version.py
--- a/distutils2/tests/test_version.py
+++ b/distutils2/tests/test_version.py
@@ -6,7 +6,7 @@
 from distutils2.version import HugeMajorVersionNumError, IrrationalVersionError
 from distutils2.version import suggest_normalized_version as suggest
 from distutils2.version import VersionPredicate
-from distutils2.tests.support import unittest
+from distutils2.tests import unittest
 
 class VersionTestCase(unittest.TestCase):
 
@@ -31,6 +31,17 @@
         for v, s in self.versions:
             self.assertEqual(str(v), s)
 
+    def test_hash(self):
+
+        for v, s in self.versions:
+            self.assertEqual(hash(v), hash(V(s)))
+
+        versions = set([v for v,s in self.versions])
+        for v, s in self.versions:
+            self.assertIn(v, versions)
+
+        self.assertEqual(set([V('1.0')]), set([V('1.0'), V('1.0')]))
+
     def test_from_parts(self):
 
         for v, s in self.versions:
@@ -188,6 +199,10 @@
         # XXX need to silent the micro version in this case
         #assert not VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.3')
 
+        # test repr
+        for predicate in predicates:
+            self.assertEqual(str(VersionPredicate(predicate)), predicate)
+
     def test_predicate_name(self):
         # Test that names are parsed the right way
 
diff --git a/distutils2/version.py b/distutils2/version.py
--- a/distutils2/version.py
+++ b/distutils2/version.py
@@ -131,7 +131,7 @@
                        pad_zeros_length=0):
         """Parse 'N.N.N' sequences, return a list of ints.
 
-        @param s {str} 'N.N.N..." sequence to be parsed
+        @param s {str} 'N.N.N...' sequence to be parsed
         @param full_ver_str {str} The full version string from which this
             comes. Used for error strings.
         @param drop_trailing_zeros {bool} Whether to drop trailing zeros
@@ -206,7 +206,8 @@
         return self.__eq__(other) or self.__gt__(other)
 
     # See http://docs.python.org/reference/datamodel#object.__hash__
-    __hash__ = object.__hash__
+    def __hash__(self):
+        return hash(self.parts)
 
 
 def suggest_normalized_version(s):
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -12,7 +12,9 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
+import os
+import sys
+import sphinx
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -98,7 +100,8 @@
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-html_theme_options = {'collapsiblesidebar': True}
+if sphinx.__version__[:3] >= '1.0':
+    html_theme_options = {'collapsiblesidebar': True}
 
 # Add any paths that contain custom themes here, relative to this directory.
 #html_theme_path = []
diff --git a/docs/source/devresources.rst b/docs/source/devresources.rst
--- a/docs/source/devresources.rst
+++ b/docs/source/devresources.rst
@@ -13,6 +13,9 @@
 ~~~~~~~~~~~~
 
 * unittest2
+* If your operating system splits core python and a python-dev (or -devel)
+  packages, install the dev package too: It contains header files needed by
+  tests.
 
 Issue Tracker
 ~~~~~~~~~~~~~
diff --git a/docs/source/distutils/introduction.rst b/docs/source/distutils/introduction.rst
--- a/docs/source/distutils/introduction.rst
+++ b/docs/source/distutils/introduction.rst
@@ -5,42 +5,42 @@
 *****************************
 
 This document covers using Distutils2 to distribute your Python modules,
-concentrating on the role of developer/distributor; if you're looking for
-information on installing Python modules, you should refer to the
+concentrating on the role of developer/distributor.  If you're looking for
+information on installing Python modules you should refer to the
 :ref:`install-index` chapter.
 
 Throughout this documentation, the terms "Distutils", "the Distutils" and
-"Distutils2" will be used with the same meaning.
+"Distutils2" will be used interchangeably.
 
 .. _distutils-concepts:
 
 Concepts & Terminology
 ======================
 
-Using the Distutils is quite simple, both for module developers and for
+Using Distutils is quite simple both for module developers and for
 users/administrators installing third-party modules.  As a developer, your
 responsibilities (apart from writing solid, well-documented and well-tested
 code, of course!) are:
 
-* write a setup script (:file:`setup.py` by convention)
+* writing a setup script (:file:`setup.py` by convention)
 
-* (optional) write a setup configuration file
+* (optional) writing a setup configuration file
 
-* create a source distribution
+* creating a source distribution
 
-* (optional) create one or more built (binary) distributions
+* (optional) creating one or more "built" (binary) distributions of your
+  project
 
-Each of these tasks is covered in this document.
+All of these tasks are covered in this document.
 
-Not all module developers have access to a multitude of platforms, so it's not
-always feasible to expect them to create a multitude of built distributions.  It
-is hoped that a class of intermediaries, called *packagers*, will arise to
-address this need.  Packagers will take source distributions released by module
-developers, build them on one or more platforms, and release the resulting built
-distributions.  Thus, users on the most popular platforms will be able to
-install most popular Python module distributions in the most natural way for
-their platform, without having to run a single setup script or compile a line of
-code.
+Not all module developers have access to multiple platforms, so one cannot 
+expect them to create buildt distributions for every platform.  To remedy
+this, it is hoped that intermediaries called *packagers* will arise to address
+this need.  Packagers take source distributions released by module developers,
+build them on one or more platforms and release the resulting built 
+distributions.  Thus, users on a greater range of platforms will be able to 
+install the most popular Python modules in the most natural way for their 
+platform without having to run a setup script or compile a single line of code.
 
 
 .. _distutils-simple-example:
@@ -48,15 +48,15 @@
 A Simple Example
 ================
 
-The setup script is usually quite simple, although since it's written in Python,
+A setup script is usually quite simple, although since it's written in Python
 there are no arbitrary limits to what you can do with it, though you should be
-careful about putting arbitrarily expensive operations in your setup script.
-Unlike, say, Autoconf-style configure scripts, the setup script may be run
-multiple times in the course of building and installing your module
+careful about putting expensive operations in your setup script.
+Unlike, say, Autoconf-style configure scripts the setup script may be run
+multiple times in the course of building and installing a module
 distribution.
 
 If all you want to do is distribute a module called :mod:`foo`, contained in a
-file :file:`foo.py`, then your setup script can be as simple as this::
+file :file:`foo.py`, then your setup script can be as simple as::
 
    from distutils2.core import setup
    setup(name='foo',
@@ -69,18 +69,18 @@
   arguments to the :func:`setup` function
 
 * those keyword arguments fall into two categories: package metadata (name,
-  version number) and information about what's in the package (a list of pure
-  Python modules, in this case)
+  version number, etc.) and information about what's in the package (a list 
+  of pure Python modules in this case)
 
 * modules are specified by module name, not filename (the same will hold true
   for packages and extensions)
 
-* it's recommended that you supply a little more metadata, in particular your
-  name, email address and a URL for the project (see section :ref:`setup-script`
-  for an example)
+* it's recommended that you supply a little more metadata than we have in the 
+  example.  In particular your name, email address and a URL for the 
+  project if appropriate (see section :ref:`setup-script` for an example)
 
-To create a source distribution for this module, you would create a setup
-script, :file:`setup.py`, containing the above code, and run::
+To create a source distribution for this module you would create a setup
+script, :file:`setup.py`, containing the above code and run::
 
    python setup.py sdist
 
@@ -89,32 +89,32 @@
 The archive file will be named :file:`foo-1.0.tar.gz` (or :file:`.zip`), and
 will unpack into a directory :file:`foo-1.0`.
 
-If an end-user wishes to install your :mod:`foo` module, all she has to do is
-download :file:`foo-1.0.tar.gz` (or :file:`.zip`), unpack it, and---from the
-:file:`foo-1.0` directory---run ::
+If an end-user wishes to install your :mod:`foo` module all he has to do is
+download :file:`foo-1.0.tar.gz` (or :file:`.zip`), unpack it, and from the
+:file:`foo-1.0` directory run ::
 
    python setup.py install
 
-which will ultimately copy :file:`foo.py` to the appropriate directory for
+which will copy :file:`foo.py` to the appropriate directory for
 third-party modules in their Python installation.
 
-This simple example demonstrates some fundamental concepts of the Distutils.
+This simple example demonstrates some fundamental concepts of Distutils.
 First, both developers and installers have the same basic user interface, i.e.
 the setup script.  The difference is which Distutils *commands* they use: the
 :command:`sdist` command is almost exclusively for module developers, while
-:command:`install` is more often for installers (although most developers will
-want to install their own code occasionally).
+:command:`install` is more often used by installers (although some developers 
+will want to install their own code occasionally).
 
-If you want to make things really easy for your users, you can create one or
-more built distributions for them.  For instance, if you are running on a
-Windows machine, and want to make things easy for other Windows users, you can
+If you want to make things really easy for your users, you can create more 
+than one built distributions for them.  For instance, if you are running on a
+Windows machine and want to make things easy for other Windows users, you can
 create an executable installer (the most appropriate type of built distribution
 for this platform) with the :command:`bdist_wininst` command.  For example::
 
    python setup.py bdist_wininst
 
 will create an executable installer, :file:`foo-1.0.win32.exe`, in the current
-directory. You can find out what distribution formats are available at any time
+directory.  You can find out what distribution formats are available at any time
 by running ::
 
    python setup.py bdist --help-formats
@@ -125,42 +125,42 @@
 General Python terminology
 ==========================
 
-If you're reading this document, you probably have a good idea of what modules,
-extensions, and so forth are.  Nevertheless, just to be sure that everyone is
-operating from a common starting point, we offer the following glossary of
-common Python terms:
+If you're reading this document, you probably have a good idea of what Python 
+modules, extensions and so forth are.  Nevertheless, just to be sure that 
+everyone is on the same page, here's a quick overview of Python terms:
 
 module
-   the basic unit of code reusability in Python: a block of code imported by some
-   other code.  Three types of modules concern us here: pure Python modules,
-   extension modules, and packages.
+   The basic unit of code reusability in Python: a block of code imported by 
+   some other code.  Three types of modules are important to us here: pure 
+   Python modules, extension modules and packages.
 
 pure Python module
-   a module written in Python and contained in a single :file:`.py` file (and
-   possibly associated :file:`.pyc` and/or :file:`.pyo` files).  Sometimes referred
-   to as a "pure module."
+   A module written in Python and contained in a single :file:`.py` file (and
+   possibly associated :file:`.pyc` and/or :file:`.pyo` files).  Sometimes 
+   referred to as a "pure module."
 
 extension module
-   a module written in the low-level language of the Python implementation: C/C++
-   for Python, Java for Jython. Typically contained in a single dynamically
-   loadable pre-compiled file, e.g. a shared object (:file:`.so`) file for Python
+   A module written in the low-level language of the Python implementation: C/C++
+   for Python, Java for Jython.  Typically contained in a single dynamically
+   loaded pre-compiled file, e.g. a shared object (:file:`.so`) file for Python
    extensions on Unix, a DLL (given the :file:`.pyd` extension) for Python
-   extensions on Windows, or a Java class file for Jython extensions.  (Note that
-   currently, the Distutils only handles C/C++ extensions for Python.)
+   extensions on Windows, or a Java class file for Jython extensions.  Note that
+   currently Distutils only handles C/C++ extensions for Python.
 
 package
-   a module that contains other modules; typically contained in a directory in the
-   filesystem and distinguished from other directories by the presence of a file
-   :file:`__init__.py`.
+   A module that contains other modules, typically contained in a directory of 
+   the filesystem and distinguished from other directories by the presence of a 
+   file :file:`__init__.py`.
 
 root package
-   the root of the hierarchy of packages.  (This isn't really a package, since it
-   doesn't have an :file:`__init__.py` file.  But we have to call it something.)
-   The vast majority of the standard library is in the root package, as are many
-   small, standalone third-party modules that don't belong to a larger module
-   collection. Unlike regular packages, modules in the root package can be found in
-   many directories: in fact, every directory listed in ``sys.path`` contributes
-   modules to the root package.
+   The root of the hierarchy of packages.  (This isn't really a package, 
+   since it doesn't have an :file:`__init__.py` file.  But... we have to 
+   call it something, right?)  The vast majority of the standard library is 
+   in the root package, as are many small standalone third-party modules that 
+   don't belong to a larger module collection.  Unlike regular packages, 
+   modules in the root package can be found in many directories: in fact, 
+   every directory listed in ``sys.path`` contributes modules to the root 
+   package.
 
 
 .. _distutils-term:
@@ -169,25 +169,25 @@
 ==============================
 
 The following terms apply more specifically to the domain of distributing Python
-modules using the Distutils:
+modules using Distutils:
 
 module distribution
-   a collection of Python modules distributed together as a single downloadable
-   resource and meant to be installed *en masse*.  Examples of some well-known
+   A collection of Python modules distributed together as a single downloadable
+   resource and meant to be installed all as one.  Examples of some well-known
    module distributions are Numeric Python, PyXML, PIL (the Python Imaging
-   Library), or mxBase.  (This would be called a *package*, except that term is
-   already taken in the Python context: a single module distribution may contain
-   zero, one, or many Python packages.)
+   Library) or mxBase.  (Module distributions would be called a *package*, 
+   except that term is already taken in the Python context: a single module 
+   distribution may contain zero, one, or many Python packages.)
 
 pure module distribution
-   a module distribution that contains only pure Python modules and packages.
+   A module distribution that contains only pure Python modules and packages.
    Sometimes referred to as a "pure distribution."
 
 non-pure module distribution
-   a module distribution that contains at least one extension module.  Sometimes
+   A module distribution that contains at least one extension module.  Sometimes
    referred to as a "non-pure distribution."
 
 distribution root
-   the top-level directory of your source tree (or  source distribution); the
-   directory where :file:`setup.py` exists.  Generally  :file:`setup.py` will be
-   run from this directory.
+   The top-level directory of your source tree (or  source distribution).  The
+   directory where :file:`setup.py` exists.  Generally  :file:`setup.py` will 
+   be run from this directory.
diff --git a/docs/source/distutils/setupscript.rst b/docs/source/distutils/setupscript.rst
--- a/docs/source/distutils/setupscript.rst
+++ b/docs/source/distutils/setupscript.rst
@@ -5,12 +5,12 @@
 ************************
 
 The setup script is the center of all activity in building, distributing, and
-installing modules using the Distutils.  The main purpose of the setup script is
-to describe your module distribution to the Distutils, so that the various
+installing modules using Distutils.  The main purpose of the setup script is
+to describe your module distribution to Distutils, so that the various
 commands that operate on your modules do the right thing.  As we saw in section
-:ref:`distutils-simple-example` above, the setup script consists mainly of a
-call to :func:`setup`, and most information supplied to the Distutils by the
-module developer is supplied as keyword arguments to :func:`setup`.
+:ref:`distutils-simple-example`, the setup script consists mainly of a
+call to :func:`setup` where the most information is supplied as 
+keyword arguments to :func:`setup`.
 
 Here's a slightly more involved example, which we'll follow for the next couple
 of sections: a setup script that could be used for Distutils2 itself::
@@ -32,8 +32,8 @@
 
 There are only two differences between this and the trivial one-file
 distribution presented in section :ref:`distutils-simple-example`: more
-metadata, and the specification of pure Python modules by package, rather than
-by module.  This is important since the Distutils consist of a couple of dozen
+metadata and the specification of pure Python modules by package rather than
+by module.  This is important since Ristutils consist of a couple of dozen
 modules split into (so far) two packages; an explicit list of every module
 would be tedious to generate and difficult to maintain.  For more information
 on the additional metadata, see section :ref:`metadata`.
@@ -501,7 +501,7 @@
 file if no template is provided. See :ref:`manifest`.
 
 
-.. _distutils2-additional-files:
+.. _distutils-additional-files:
 
 Installing Additional Files
 ===========================
diff --git a/docs/source/distutils/sourcedist.rst b/docs/source/distutils/sourcedist.rst
--- a/docs/source/distutils/sourcedist.rst
+++ b/docs/source/distutils/sourcedist.rst
@@ -142,7 +142,7 @@
 
    python setup.py sdist --manifest-only
 
-:option:`-o` is a sortcut for :option:`--manifest-only`.
+:option:`-o` is a shortcut for :option:`--manifest-only`.
 
 .. _manifest_template:
 
diff --git a/runtests-cov.py b/runtests-cov.py
deleted file mode 100644
--- a/runtests-cov.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-"""Tests for distutils2.
-
-The tests for distutils2 are defined in the distutils2.tests package.
-"""
-
-import sys
-from os.path import dirname, islink, realpath, join, abspath
-from optparse import OptionParser
-
-COVERAGE_FILE = join(dirname(abspath(__file__)), '.coverage')
-
-def get_coverage():
-    """ Return a usable coverage object. """
-    # deferred import because coverage is optional
-    import coverage
-    cov = getattr(coverage, "the_coverage", None)
-    if not cov:
-        cov = coverage.coverage(COVERAGE_FILE)
-    return cov
-
-def ignore_prefixes(module):
-    """ Return a list of prefixes to ignore in the coverage report if
-    we want to completely skip `module`.
-    """
-    # A function like that is needed because some GNU/Linux
-    # distributions, such a Ubuntu, really like to build link farm in
-    # /usr/lib in order to save a few bytes on the disk.
-    dirnames = [dirname(module.__file__)]
-
-    pymod = module.__file__.rstrip("c")
-    if islink(pymod):
-        dirnames.append(dirname(realpath(pymod)))
-    return dirnames
-
-
-def parse_opts():
-    parser = OptionParser(usage="%prog [OPTIONS]",
-                          description="run the distutils2 unittests")
-
-    parser.add_option("-q", "--quiet", help="do not print verbose messages",
-                      action="store_true", default=False)
-    parser.add_option("-c", "--coverage", action="store_true", default=False,
-                      help="produce a coverage report at the end of the run")
-    parser.add_option("-r", "--report", action="store_true", default=False,
-                      help="produce a coverage report from the last test run")
-    parser.add_option("-m", "--show-missing", action="store_true",
-                      default=False,
-                      help=("Show line numbers of statements in each module "
-                            "that weren't executed."))
-
-    opts, args = parser.parse_args()
-    return opts, args
-
-
-def coverage_report(opts):
-    from distutils2.tests.support import unittest
-    cov = get_coverage()
-    if hasattr(cov, "load"):
-        # running coverage 3.x
-        cov.load()
-        morfs = None
-    else:
-        # running coverage 2.x
-        cov.cache = COVERAGE_FILE
-        cov.restore()
-        morfs = [m for m in cov.cexecuted.keys() if "distutils2" in m]
-
-    prefixes = ["runtests", "distutils2/tests", "distutils2/_backport"]
-    prefixes += ignore_prefixes(unittest)
-
-    try:
-        import docutils
-        prefixes += ignore_prefixes(docutils)
-    except ImportError:
-        # that module is completely optional
-        pass
-
-    try:
-        import roman
-        prefixes += ignore_prefixes(roman)
-    except ImportError:
-        # that module is also completely optional
-        pass
-
-    cov.report(morfs, omit_prefixes=prefixes, show_missing=opts.show_missing)
-
-
-def test_main():
-    opts, args = parse_opts()
-    verbose = not opts.quiet
-    ret = 0
-
-    if opts.coverage:
-        cov = get_coverage()
-        cov.erase()
-        cov.start()
-    if not opts.report:
-        ret = run_tests(verbose)
-    if opts.coverage:
-        cov.stop()
-        cov.save()
-
-    if opts.report or opts.coverage:
-        coverage_report(opts)
-
-    return ret
-
-
-def run_tests(verbose):
-    import distutils2.tests
-    from distutils2.tests import run_unittest, reap_children, TestFailed
-    from distutils2._backport.tests import test_suite as btest_suite
-    # XXX just supporting -q right now to enable detailed/quiet output
-    if len(sys.argv) > 1:
-        verbose = sys.argv[-1] != '-q'
-    else:
-        verbose = 1
-    try:
-        try:
-            run_unittest([distutils2.tests.test_suite(), btest_suite()],
-                         verbose_=verbose)
-            return 0
-        except TestFailed:
-            return 1
-    finally:
-        reap_children()
-
-
-if __name__ == "__main__":
-    try:
-        from distutils2.tests.support import unittest
-    except ImportError:
-        sys.stderr.write('Error: You have to install unittest2')
-        sys.exit(1)
-    sys.exit(test_main())
diff --git a/runtests.py b/runtests.py
--- a/runtests.py
+++ b/runtests.py
@@ -5,21 +5,123 @@
 """
 
 import sys
+from os.path import dirname, islink, realpath, join, abspath
+from optparse import OptionParser
 
+COVERAGE_FILE = join(dirname(abspath(__file__)), '.coverage')
+
+def get_coverage():
+    """ Return a usable coverage object. """
+    # deferred import because coverage is optional
+    import coverage
+    cov = getattr(coverage, "the_coverage", None)
+    if not cov:
+        cov = coverage.coverage(COVERAGE_FILE)
+    return cov
+
+def ignore_prefixes(module):
+    """ Return a list of prefixes to ignore in the coverage report if
+    we want to completely skip `module`.
+    """
+    # A function like that is needed because some GNU/Linux
+    # distributions, such a Ubuntu, really like to build link farm in
+    # /usr/lib in order to save a few bytes on the disk.
+    dirnames = [dirname(module.__file__)]
+
+    pymod = module.__file__.rstrip("c")
+    if islink(pymod):
+        dirnames.append(dirname(realpath(pymod)))
+    return dirnames
+
+
+def parse_opts():
+    parser = OptionParser(usage="%prog [OPTIONS]",
+                          description="run the distutils2 unittests")
+
+    parser.add_option("-q", "--quiet", help="do not print verbose messages",
+                      action="store_true", default=False)
+    parser.add_option("-c", "--coverage", action="store_true", default=False,
+                      help="produce a coverage report at the end of the run")
+    parser.add_option("-r", "--report", action="store_true", default=False,
+                      help="produce a coverage report from the last test run")
+    parser.add_option("-m", "--show-missing", action="store_true",
+                      default=False,
+                      help=("Show line numbers of statements in each module "
+                            "that weren't executed."))
+
+    opts, args = parser.parse_args()
+    return opts, args
+
+
+def coverage_report(opts):
+    from distutils2.tests.support import unittest
+    cov = get_coverage()
+    if hasattr(cov, "load"):
+        # running coverage 3.x
+        cov.load()
+        morfs = None
+    else:
+        # running coverage 2.x
+        cov.cache = COVERAGE_FILE
+        cov.restore()
+        morfs = [m for m in cov.cexecuted.keys() if "distutils2" in m]
+
+    prefixes = ["runtests", "distutils2/tests", "distutils2/_backport"]
+    prefixes += ignore_prefixes(unittest)
+
+    try:
+        import docutils
+        prefixes += ignore_prefixes(docutils)
+    except ImportError:
+        # that module is completely optional
+        pass
+
+    try:
+        import roman
+        prefixes += ignore_prefixes(roman)
+    except ImportError:
+        # that module is also completely optional
+        pass
+
+    try:
+        cov.report(morfs,
+                   omit_prefixes=prefixes,
+                   show_missing=opts.show_missing)
+    except TypeError:
+        # Coverage 3.4 turned `omit_prefixes` into a list of globbing patterns
+        cov.report(morfs,
+                   omit=[p + "*" for p in prefixes],
+                   show_missing=opts.show_missing)
 
 def test_main():
-    import distutils2.tests
-    from distutils2.tests import run_unittest, reap_children, TestFailed
+    opts, args = parse_opts()
+    verbose = not opts.quiet
+    ret = 0
+
+    if opts.coverage:
+        cov = get_coverage()
+        cov.erase()
+        cov.start()
+    if not opts.report:
+        ret = run_tests(verbose)
+    if opts.coverage:
+        cov.stop()
+        cov.save()
+
+    if opts.report or opts.coverage:
+        coverage_report(opts)
+
+    return ret
+
+
+def run_tests(verbose):
+    # do NOT import those at the top level, coverage will be inaccurate if
+    # modules are imported before its magic is started
+    from distutils2.tests import run_unittest, test_suite, reap_children, TestFailed
     from distutils2._backport.tests import test_suite as btest_suite
-    # XXX just supporting -q right now to enable detailed/quiet output
-    if len(sys.argv) > 1:
-        verbose = sys.argv[-1] != '-q'
-    else:
-        verbose = 1
     try:
         try:
-            run_unittest([distutils2.tests.test_suite(), btest_suite()],
-                         verbose_=verbose)
+            run_unittest([test_suite(), btest_suite()], verbose_=verbose)
             return 0
         except TestFailed:
             return 1
@@ -28,9 +130,10 @@
 
 
 if __name__ == "__main__":
-    try:
-        from distutils2.tests.support import unittest
-    except ImportError:
-        sys.stderr.write('Error: You have to install unittest2')
-        sys.exit(1)
+    if sys.version < '2.5':
+        try:
+            from distutils2._backport import hashlib
+        except ImportError:
+            import subprocess
+            subprocess.call([sys.executable, 'setup.py', 'build_ext'])
     sys.exit(test_main())
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -210,14 +210,14 @@
 
 setup(name="Distutils2",
       version=VERSION,
-      summary="Python Distribution Utilities",
+      description="Python Distribution Utilities",
       keywords=['packaging', 'distutils'],
       author="Tarek Ziade",
       author_email="tarek at ziade.org",
-      home_page="http://bitbucket.org/tarek/distutils2/wiki/Home",
+      url="http://bitbucket.org/tarek/distutils2/wiki/Home",
       license="PSF",
-      description=README,
-      classifier=_CLASSIFIERS.split('\n'),
+      long_description=README,
+      classifiers=_CLASSIFIERS.split('\n'),
       packages=find_packages(),
       cmdclass={'sdist_hg': sdist_hg, 'install_hg': install_hg},
       package_data={'distutils2._backport': ['sysconfig.cfg']},

--
Repository URL: http://hg.python.org/distutils2
More information about the Python-checkins mailing list

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4