[Python-checkins] distutils2: Merge upstream

tarek.ziade python-checkins at python.org
Sun Aug 8 11:50:46 CEST 2010


tarek.ziade pushed 196d1ecad12b to distutils2:

http://hg.python.org/distutils2/rev/196d1ecad12b
changeset:   446:196d1ecad12b
parent:      445:1d2f4bc24ad3
parent:      382:733c3bdaa25e
user:        Alexis Metaireau <ametaireau at gmail.com>
date:        Mon Jul 19 15:29:26 2010 +0200
summary:     Merge upstream
files:       

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -6,3 +6,4 @@
 MANIFEST
 dist/
 *.swp
+.coverage
\ No newline at end of file
diff --git a/src/CONTRIBUTORS.txt b/src/CONTRIBUTORS.txt
--- a/src/CONTRIBUTORS.txt
+++ b/src/CONTRIBUTORS.txt
@@ -13,15 +13,18 @@
 - Pior Bastida
 - Titus Brown
 - Nicolas Cadou
+- Konrad Delong
 - Josip Djolonga
 - Yannick Gringas
 - Jeremy Kloth
 - Martin von Löwis
 - Carl Meyer
-- Alexis Metaireau
+- Alexis Métaireau
+- Zubin Mithra
 - Michael Mulich
-- George Peris
+- George Peristerakis
 - Sean Reifschneider
+- Luis Rojas
 - Erik Rose
 - Brian Rosner
 - Alexandre Vassalotti
diff --git a/src/distutils2/command/bdist_dumb.py b/src/distutils2/command/bdist_dumb.py
--- a/src/distutils2/command/bdist_dumb.py
+++ b/src/distutils2/command/bdist_dumb.py
@@ -115,8 +115,9 @@
                        % (repr(install.install_base),
                           repr(install.install_platbase)))
             else:
-                archive_root = os.path.join(self.bdist_dir,
-                                   ensure_relative(install.install_base))
+                archive_root = os.path.join(
+                    self.bdist_dir,
+                    self._ensure_relative(install.install_base))
 
         # Make the archive
         filename = self.make_archive(pseudoinstall_root,
@@ -135,3 +136,9 @@
             else:
                 rmtree(self.bdist_dir)
 
+    def _ensure_relative(self, path):
+        # copied from dir_util, deleted
+        drive, path = os.path.splitdrive(path)
+        if path[0:1] == os.sep:
+            path = drive + path[1:]
+        return path
diff --git a/src/distutils2/command/bdist_wininst.py b/src/distutils2/command/bdist_wininst.py
--- a/src/distutils2/command/bdist_wininst.py
+++ b/src/distutils2/command/bdist_wininst.py
@@ -8,6 +8,7 @@
 import sys
 import os
 import string
+from shutil import rmtree
 try:
     from sysconfig import get_python_version
 except ImportError:
diff --git a/src/distutils2/command/build_py.py b/src/distutils2/command/build_py.py
--- a/src/distutils2/command/build_py.py
+++ b/src/distutils2/command/build_py.py
@@ -9,6 +9,7 @@
 import logging
 from glob import glob
 
+import distutils2
 from distutils2.core import Command
 from distutils2.errors import DistutilsOptionError, DistutilsFileError
 from distutils2.util import convert_path
diff --git a/src/distutils2/command/cmd.py b/src/distutils2/command/cmd.py
--- a/src/distutils2/command/cmd.py
+++ b/src/distutils2/command/cmd.py
@@ -6,7 +6,7 @@
 
 __revision__ = "$Id: cmd.py 75192 2009-10-02 23:49:48Z tarek.ziade $"
 
-import sys, os, re
+import os, re
 from distutils2.errors import DistutilsOptionError
 from distutils2 import util
 from distutils2 import log
@@ -447,7 +447,7 @@
         # If 'outfile' must be regenerated (either because it doesn't
         # exist, is out-of-date, or the 'force' flag is true) then
         # perform the action that presumably regenerates it
-        if self.force or dep_util.newer_group(infiles, outfile):
+        if self.force or util.newer_group(infiles, outfile):
             self.execute(func, args, exec_msg, level)
 
         # Otherwise, print the "skip" message
diff --git a/src/distutils2/command/sdist.py b/src/distutils2/command/sdist.py
--- a/src/distutils2/command/sdist.py
+++ b/src/distutils2/command/sdist.py
@@ -18,12 +18,11 @@
     from distutils2._backport.shutil import get_archive_formats
 
 from distutils2.core import Command
-from distutils2 import util
 from distutils2.errors import (DistutilsPlatformError, DistutilsOptionError,
                                DistutilsTemplateError)
 from distutils2.manifest import Manifest
 from distutils2 import log
-from distutils2.util import convert_path, newer
+from distutils2.util import convert_path
 
 def show_formats():
     """Print all possible values for the 'formats' option (used by
diff --git a/src/distutils2/command/upload_docs.py b/src/distutils2/command/upload_docs.py
--- a/src/distutils2/command/upload_docs.py
+++ b/src/distutils2/command/upload_docs.py
@@ -1,4 +1,4 @@
-import base64, httplib, os.path, socket, tempfile, urlparse, zipfile
+import base64, httplib, os.path, socket, urlparse, zipfile
 from cStringIO import StringIO
 from distutils2 import log
 from distutils2.command.upload import upload
@@ -81,7 +81,6 @@
             raise DistutilsFileError(mesg % upload_dir)
 
     def run(self):
-        tmp_dir = tempfile.mkdtemp()
         name = self.distribution.metadata['Name']
         zip_file = zip_dir(self.upload_dir)
 
@@ -124,7 +123,7 @@
         elif r.status == 301:
             location = r.getheader('Location')
             if location is None:
-                location = 'http://packages.python.org/%s/' % meta.get_name()
+                location = 'http://packages.python.org/%s/' % name
             self.announce('Upload successful. Visit %s' % location,
                           log.INFO)
         else:
diff --git a/src/distutils2/converter/fixers/fix_imports.py b/src/distutils2/converter/fixers/fix_imports.py
--- a/src/distutils2/converter/fixers/fix_imports.py
+++ b/src/distutils2/converter/fixers/fix_imports.py
@@ -36,11 +36,16 @@
             pattern = []
             next = imp.next_sibling
             while next is not None:
+                # Get the first child if we have a Node
+                if not hasattr(next, "value"):
+                    next = next.children[0]
                 pattern.append(next.value)
                 if not hasattr(next, "next_sibling"):
                     next.next_sibling = next.get_next_sibling()
                 next = next.next_sibling
-            if pattern == ['import', 'setup']:
+            
+            if set(pattern).issubset(set(
+                    ['import', ',', 'setup', 'find_packages'])):
                 imp.value = 'distutils2.core'
                 imp.changed()
 
diff --git a/src/distutils2/extension.py b/src/distutils2/extension.py
--- a/src/distutils2/extension.py
+++ b/src/distutils2/extension.py
@@ -5,14 +5,8 @@
 
 __revision__ = "$Id: extension.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
 
-import os
 import warnings
 
-try:
-    import sysconfig
-except ImportError:
-    from distutils2._backport import sysconfig
-
 # This class is really only used by the "build_ext" command, so it might
 # make sense to put it in distutils.command.build_ext.  However, that
 # module is already big enough, and I want to make this class a bit more
diff --git a/src/distutils2/tests/conversions/05_after.py b/src/distutils2/tests/conversions/05_after.py
new file mode 100644
--- /dev/null
+++ b/src/distutils2/tests/conversions/05_after.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2003-2009 Edgewall Software
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://trac.edgewall.org/wiki/TracLicense.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://trac.edgewall.org/log/.
+
+from distutils2.core import setup, find_packages
+
+extra = {}
+
+try:
+    import babel
+    
+    extractors = [
+        ('**.py',                'python', None),
+        ('**/templates/**.html', 'genshi', None),
+        ('**/templates/**.txt',  'genshi',
+         {'template_class': 'genshi.template:NewTextTemplate'}),
+    ]
+    extra['message_extractors'] = {
+        'trac': extractors,
+        'tracopt': extractors,
+    }
+
+    from trac.util.dist import get_l10n_js_cmdclass
+    extra['cmdclass'] = get_l10n_js_cmdclass()
+
+except ImportError, e:
+    pass
+
+setup(
+    name = 'Trac',
+    version = '0.12.1',
+    summary = 'Integrated SCM, wiki, issue tracker and project environment',
+    description = """
+Trac is a minimalistic web-based software project management and bug/issue
+tracking system. It provides an interface to the Subversion revision control
+systems, an integrated wiki, flexible issue tracking and convenient report
+facilities.
+""",
+    author = 'Edgewall Software',
+    author_email = 'info at edgewall.com',
+    license = 'BSD',
+    home_page = 'http://trac.edgewall.org/',
+    download_url = 'http://trac.edgewall.org/wiki/TracDownload',
+    classifiers = [
+        'Environment :: Web Environment',
+        'Framework :: Trac',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Software Development :: Bug Tracking',
+        'Topic :: Software Development :: Version Control',
+    ],
+
+    packages = find_packages(exclude=['*.tests']),
+    package_data = {
+        '': ['templates/*'],
+        'trac': ['htdocs/*.*', 'htdocs/README', 'htdocs/js/*.*',
+                 'htdocs/js/messages/*.*', 'htdocs/css/*.*',
+                 'htdocs/guide/*', 'locale/*/LC_MESSAGES/messages.mo'],
+        'trac.wiki': ['default-pages/*'],
+        'trac.ticket': ['workflows/*.ini'],
+    },
+
+    test_suite = 'trac.test.suite',
+    zip_safe = True,
+
+    requires_dist = [
+        'setuptools>=0.6b1',
+        'Genshi>=0.6',
+    ],
+    extras_require = {
+        'Babel': ['Babel>=0.9.5'],
+        'Pygments': ['Pygments>=0.6'],
+        'reST': ['docutils>=0.3'],
+        'SilverCity': ['SilverCity>=0.9.4'],
+        'Textile': ['textile>=2.0'],
+    },
+
+    entry_points = """
+        [console_scripts]
+        trac-admin = trac.admin.console:run
+        tracd = trac.web.standalone:main
+
+        [trac.plugins]
+        trac.about = trac.about
+        trac.admin.console = trac.admin.console
+        trac.admin.web_ui = trac.admin.web_ui
+        trac.attachment = trac.attachment
+        trac.db.mysql = trac.db.mysql_backend
+        trac.db.postgres = trac.db.postgres_backend
+        trac.db.sqlite = trac.db.sqlite_backend
+        trac.mimeview.patch = trac.mimeview.patch
+        trac.mimeview.pygments = trac.mimeview.pygments[Pygments]
+        trac.mimeview.rst = trac.mimeview.rst[reST]
+        trac.mimeview.silvercity = trac.mimeview.silvercity[SilverCity]
+        trac.mimeview.txtl = trac.mimeview.txtl[Textile]
+        trac.prefs = trac.prefs.web_ui
+        trac.search = trac.search.web_ui
+        trac.ticket.admin = trac.ticket.admin
+        trac.ticket.query = trac.ticket.query
+        trac.ticket.report = trac.ticket.report
+        trac.ticket.roadmap = trac.ticket.roadmap
+        trac.ticket.web_ui = trac.ticket.web_ui
+        trac.timeline = trac.timeline.web_ui
+        trac.versioncontrol.admin = trac.versioncontrol.admin
+        trac.versioncontrol.svn_authz = trac.versioncontrol.svn_authz
+        trac.versioncontrol.svn_fs = trac.versioncontrol.svn_fs
+        trac.versioncontrol.svn_prop = trac.versioncontrol.svn_prop
+        trac.versioncontrol.web_ui = trac.versioncontrol.web_ui
+        trac.web.auth = trac.web.auth
+        trac.web.session = trac.web.session
+        trac.wiki.admin = trac.wiki.admin
+        trac.wiki.interwiki = trac.wiki.interwiki
+        trac.wiki.macros = trac.wiki.macros
+        trac.wiki.web_ui = trac.wiki.web_ui
+        trac.wiki.web_api = trac.wiki.web_api
+        tracopt.mimeview.enscript = tracopt.mimeview.enscript
+        tracopt.mimeview.php = tracopt.mimeview.php
+        tracopt.perm.authz_policy = tracopt.perm.authz_policy
+        tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
+        tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
+        tracopt.ticket.deleter = tracopt.ticket.deleter
+    """,
+
+    **extra
+)
diff --git a/src/distutils2/tests/conversions/05_before.py b/src/distutils2/tests/conversions/05_before.py
new file mode 100755
--- /dev/null
+++ b/src/distutils2/tests/conversions/05_before.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2003-2009 Edgewall Software
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://trac.edgewall.org/wiki/TracLicense.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://trac.edgewall.org/log/.
+
+from setuptools import setup, find_packages
+
+extra = {}
+
+try:
+    import babel
+    
+    extractors = [
+        ('**.py',                'python', None),
+        ('**/templates/**.html', 'genshi', None),
+        ('**/templates/**.txt',  'genshi',
+         {'template_class': 'genshi.template:NewTextTemplate'}),
+    ]
+    extra['message_extractors'] = {
+        'trac': extractors,
+        'tracopt': extractors,
+    }
+
+    from trac.util.dist import get_l10n_js_cmdclass
+    extra['cmdclass'] = get_l10n_js_cmdclass()
+
+except ImportError, e:
+    pass
+
+setup(
+    name = 'Trac',
+    version = '0.12.1',
+    description = 'Integrated SCM, wiki, issue tracker and project environment',
+    long_description = """
+Trac is a minimalistic web-based software project management and bug/issue
+tracking system. It provides an interface to the Subversion revision control
+systems, an integrated wiki, flexible issue tracking and convenient report
+facilities.
+""",
+    author = 'Edgewall Software',
+    author_email = 'info at edgewall.com',
+    license = 'BSD',
+    url = 'http://trac.edgewall.org/',
+    download_url = 'http://trac.edgewall.org/wiki/TracDownload',
+    classifiers = [
+        'Environment :: Web Environment',
+        'Framework :: Trac',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Software Development :: Bug Tracking',
+        'Topic :: Software Development :: Version Control',
+    ],
+
+    packages = find_packages(exclude=['*.tests']),
+    package_data = {
+        '': ['templates/*'],
+        'trac': ['htdocs/*.*', 'htdocs/README', 'htdocs/js/*.*',
+                 'htdocs/js/messages/*.*', 'htdocs/css/*.*',
+                 'htdocs/guide/*', 'locale/*/LC_MESSAGES/messages.mo'],
+        'trac.wiki': ['default-pages/*'],
+        'trac.ticket': ['workflows/*.ini'],
+    },
+
+    test_suite = 'trac.test.suite',
+    zip_safe = True,
+
+    install_requires = [
+        'setuptools>=0.6b1',
+        'Genshi>=0.6',
+    ],
+    extras_require = {
+        'Babel': ['Babel>=0.9.5'],
+        'Pygments': ['Pygments>=0.6'],
+        'reST': ['docutils>=0.3'],
+        'SilverCity': ['SilverCity>=0.9.4'],
+        'Textile': ['textile>=2.0'],
+    },
+
+    entry_points = """
+        [console_scripts]
+        trac-admin = trac.admin.console:run
+        tracd = trac.web.standalone:main
+
+        [trac.plugins]
+        trac.about = trac.about
+        trac.admin.console = trac.admin.console
+        trac.admin.web_ui = trac.admin.web_ui
+        trac.attachment = trac.attachment
+        trac.db.mysql = trac.db.mysql_backend
+        trac.db.postgres = trac.db.postgres_backend
+        trac.db.sqlite = trac.db.sqlite_backend
+        trac.mimeview.patch = trac.mimeview.patch
+        trac.mimeview.pygments = trac.mimeview.pygments[Pygments]
+        trac.mimeview.rst = trac.mimeview.rst[reST]
+        trac.mimeview.silvercity = trac.mimeview.silvercity[SilverCity]
+        trac.mimeview.txtl = trac.mimeview.txtl[Textile]
+        trac.prefs = trac.prefs.web_ui
+        trac.search = trac.search.web_ui
+        trac.ticket.admin = trac.ticket.admin
+        trac.ticket.query = trac.ticket.query
+        trac.ticket.report = trac.ticket.report
+        trac.ticket.roadmap = trac.ticket.roadmap
+        trac.ticket.web_ui = trac.ticket.web_ui
+        trac.timeline = trac.timeline.web_ui
+        trac.versioncontrol.admin = trac.versioncontrol.admin
+        trac.versioncontrol.svn_authz = trac.versioncontrol.svn_authz
+        trac.versioncontrol.svn_fs = trac.versioncontrol.svn_fs
+        trac.versioncontrol.svn_prop = trac.versioncontrol.svn_prop
+        trac.versioncontrol.web_ui = trac.versioncontrol.web_ui
+        trac.web.auth = trac.web.auth
+        trac.web.session = trac.web.session
+        trac.wiki.admin = trac.wiki.admin
+        trac.wiki.interwiki = trac.wiki.interwiki
+        trac.wiki.macros = trac.wiki.macros
+        trac.wiki.web_ui = trac.wiki.web_ui
+        trac.wiki.web_api = trac.wiki.web_api
+        tracopt.mimeview.enscript = tracopt.mimeview.enscript
+        tracopt.mimeview.php = tracopt.mimeview.php
+        tracopt.perm.authz_policy = tracopt.perm.authz_policy
+        tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
+        tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
+        tracopt.ticket.deleter = tracopt.ticket.deleter
+    """,
+
+    **extra
+)
diff --git a/src/distutils2/tests/test_build_ext.py b/src/distutils2/tests/test_build_ext.py
--- a/src/distutils2/tests/test_build_ext.py
+++ b/src/distutils2/tests/test_build_ext.py
@@ -368,4 +368,4 @@
     else: return unittest.makeSuite(BuildExtTestCase)
 
 if __name__ == '__main__':
-    distsutils2.tests.run_unittest(test_suite())
+    distutils2.tests.run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_depgraph.py b/src/distutils2/tests/test_depgraph.py
--- a/src/distutils2/tests/test_depgraph.py
+++ b/src/distutils2/tests/test_depgraph.py
@@ -10,7 +10,7 @@
 import re
 try:
     import cStringIO as StringIO
-except ImportErorr:
+except ImportError:
     import StringIO
 
 class DepGraphTestCase(support.LoggingSilencer,
diff --git a/src/distutils2/tests/test_manifest.py b/src/distutils2/tests/test_manifest.py
--- a/src/distutils2/tests/test_manifest.py
+++ b/src/distutils2/tests/test_manifest.py
@@ -3,6 +3,7 @@
 import sys
 import logging
 
+from distutils2.tests import run_unittest
 from distutils2.tests import support
 from distutils2.tests.support import unittest
 from distutils2.manifest import Manifest
diff --git a/src/distutils2/tests/test_metadata.py b/src/distutils2/tests/test_metadata.py
--- a/src/distutils2/tests/test_metadata.py
+++ b/src/distutils2/tests/test_metadata.py
@@ -5,7 +5,10 @@
 
 from distutils2.metadata import (DistributionMetadata, _interpret,
                                  PKG_INFO_PREFERRED_VERSION)
+from distutils2.tests import run_unittest
 from distutils2.tests.support import unittest, LoggingSilencer
+from distutils2.errors import (MetadataConflictError,
+                               MetadataUnrecognizedVersionError)
 
 class DistributionMetadataTestCase(LoggingSilencer, unittest.TestCase):
 
@@ -125,6 +128,10 @@
         metadata['Obsoletes-Dist'] = 'ok'
         self.assertEqual(metadata['Metadata-Version'], '1.2')
 
+        self.assertRaises(MetadataConflictError, metadata.set,
+                          'Obsoletes', 'ok')
+
+        del metadata['Obsoletes']
         del metadata['Obsoletes-Dist']
         metadata['Version'] = '1'
         self.assertEqual(metadata['Metadata-Version'], '1.0')
@@ -139,6 +146,9 @@
         metadata.read_file(StringIO(open(PKG_INFO).read()))
         self.assertEqual(metadata['Metadata-Version'], '1.1')
 
+        metadata.version = '1.618'
+        self.assertRaises(MetadataUnrecognizedVersionError, metadata.keys)
+
     def test_warnings(self):
         metadata = DistributionMetadata()
 
diff --git a/src/distutils2/tests/test_pypi_versions.py b/src/distutils2/tests/test_pypi_versions.py
--- a/src/distutils2/tests/test_pypi_versions.py
+++ b/src/distutils2/tests/test_pypi_versions.py
@@ -19,6 +19,7 @@
 import os.path
 
 from distutils2.version import suggest_normalized_version
+from distutils2.tests import run_unittest
 from distutils2.tests.support import unittest
 
 def test_pypi():
@@ -52,7 +53,7 @@
         print "Saving package info..."
         f = open(INDEX_PICKLE_FILE, 'wb')
         try:
-            pickle.dump(package_info, o)
+            pickle.dump(package_info, f)
         finally:
             f.close()
 
diff --git a/src/distutils2/tests/test_util.py b/src/distutils2/tests/test_util.py
--- a/src/distutils2/tests/test_util.py
+++ b/src/distutils2/tests/test_util.py
@@ -4,6 +4,8 @@
 from copy import copy
 from StringIO import StringIO
 import subprocess
+import tempfile
+import time
 
 from distutils2.errors import (DistutilsPlatformError,
                                DistutilsByteCompileError,
@@ -257,7 +259,10 @@
 
     def test_newer(self):
         self.assertRaises(DistutilsFileError, util.newer, 'xxx', 'xxx')
-
+        self.newer_f1 = tempfile.NamedTemporaryFile()
+        time.sleep(1)
+        self.newer_f2 = tempfile.NamedTemporaryFile()
+        self.assertTrue(util.newer(self.newer_f2.name, self.newer_f1.name))
 
     def test_find_packages(self):
         # let's create a structure we want to scan:
diff --git a/src/distutils2/tests/test_version.py b/src/distutils2/tests/test_version.py
--- a/src/distutils2/tests/test_version.py
+++ b/src/distutils2/tests/test_version.py
@@ -3,7 +3,7 @@
 import os
 
 from distutils2.version import NormalizedVersion as V
-from distutils2.version import IrrationalVersionError
+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
@@ -22,6 +22,10 @@
                 (V('1.0.dev345'), '1.0.dev345'),
                 (V('1.0.post456.dev623'), '1.0.post456.dev623'))
 
+    def test_repr(self):
+
+        self.assertEqual(repr(V('1.0')), "NormalizedVersion('1.0')")
+
     def test_basic_versions(self):
 
         for v, s in self.versions:
@@ -44,6 +48,12 @@
         for s in irrational:
             self.assertRaises(IrrationalVersionError, V, s)
 
+    def test_huge_version(self):
+
+        self.assertEquals(str(V('1980.0')), '1980.0')
+        self.assertRaises(HugeMajorVersionNumError, V, '1981.0')
+        self.assertEquals(str(V('1981.0', error_on_huge_major_num=False)), '1981.0')
+
     def test_comparison(self):
         r"""
         >>> V('1.2.0') == '1.2'
@@ -51,12 +61,33 @@
         ...
         TypeError: cannot compare NormalizedVersion and str
 
+        >>> V('1.2') < '1.3'
+        Traceback (most recent call last):
+        ...
+        TypeError: cannot compare NormalizedVersion and str
+
         >>> V('1.2.0') == V('1.2')
         True
         >>> V('1.2.0') == V('1.2.3')
         False
+        >>> V('1.2.0') != V('1.2.3')
+        True
         >>> V('1.2.0') < V('1.2.3')
         True
+        >>> V('1.2.0') < V('1.2.0')
+        False
+        >>> V('1.2.0') <= V('1.2.0')
+        True
+        >>> V('1.2.0') <= V('1.2.3')
+        True
+        >>> V('1.2.3') <= V('1.2.0')
+        False
+        >>> V('1.2.0') >= V('1.2.0')
+        True
+        >>> V('1.2.3') >= V('1.2.0')
+        True
+        >>> V('1.2.0') >= V('1.2.3')
+        False
         >>> (V('1.0') > V('1.0b2'))
         True
         >>> (V('1.0') > V('1.0c2') > V('1.0c1') > V('1.0b2') > V('1.0b1')
@@ -101,6 +132,7 @@
         self.assertEqual(suggest('1.0c2'), '1.0c2')
         self.assertEqual(suggest('walla walla washington'), None)
         self.assertEqual(suggest('2.4c1'), '2.4c1')
+        self.assertEqual(suggest('v1.0'), '1.0')
 
         # from setuptools
         self.assertEqual(suggest('0.4a1.r10'), '0.4a1.post10')
@@ -151,6 +183,8 @@
         self.assertFalse(VersionPredicate('Hey (<=2.5)').match('2.6.0'))
         self.assertTrue(VersionPredicate('Hey (>=2.5)').match('2.5.1'))
 
+        self.assertRaises(ValueError, VersionPredicate, '')
+
         # XXX need to silent the micro version in this case
         #assert not VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.3')
 
@@ -164,11 +198,21 @@
         for version in other_versions:
             self.assertFalse(V(version).is_final)
 
+class VersionWhiteBoxTestCase(unittest.TestCase):
+
+    def test_parse_numdots(self):
+        # For code coverage completeness, as pad_zeros_length can't be set or
+        # influenced from the public interface
+        self.assertEquals(V('1.0')._parse_numdots('1.0', '1.0',
+                                                  pad_zeros_length=3),
+                          [1, 0, 0])
+
 
 def test_suite():
     #README = os.path.join(os.path.dirname(__file__), 'README.txt')
     #suite = [doctest.DocFileSuite(README), unittest.makeSuite(VersionTestCase)]
-    suite = [unittest.makeSuite(VersionTestCase)]
+    suite = [unittest.makeSuite(VersionTestCase),
+             unittest.makeSuite(VersionWhiteBoxTestCase)]
     return unittest.TestSuite(suite)
 
 if __name__ == "__main__":
diff --git a/src/distutils2/version.py b/src/distutils2/version.py
--- a/src/distutils2/version.py
+++ b/src/distutils2/version.py
@@ -1,4 +1,3 @@
-import sys
 import re
 
 from distutils2.errors import IrrationalVersionError, HugeMajorVersionNumError
@@ -379,8 +378,6 @@
     def __init__(self, predicate):
         predicate = predicate.strip()
         match = _PLAIN_VERSIONS.match(predicate)
-        if match is None:
-            raise ValueError('Bad predicate "%s"' % predicate)
         self.name = None
         predicates = match.groups()[0]
         self.predicates = [_split_predicate(pred.strip())
@@ -391,8 +388,6 @@
     def __init__(self, predicate):
         predicate = predicate.strip()
         match = _PLAIN_VERSIONS.match(predicate)
-        if match is None:
-            raise ValueError('Bad predicate "%s"' % predicate)
         self.name = None
         self.predicates = _split_predicate(match.groups()[0])
 
diff --git a/src/runtests-cov.py b/src/runtests-cov.py
new file mode 100755
--- /dev/null
+++ b/src/runtests-cov.py
@@ -0,0 +1,119 @@
+#!/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
+from optparse import OptionParser
+
+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):
+    import coverage
+    from distutils2.tests.support import unittest
+    cov = coverage.coverage()
+    cov.load()
+
+    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(omit_prefixes=prefixes, show_missing=opts.show_missing)
+
+
+def test_main():
+    opts, args = parse_opts()
+    verbose = not opts.quiet
+    ret = 0
+
+    if opts.coverage or opts.report:
+        import coverage
+
+    if opts.coverage:
+        cov = coverage.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/src/setup.py b/src/setup.py
--- a/src/setup.py
+++ b/src/setup.py
@@ -11,7 +11,6 @@
 from distutils2.compiler.ccompiler import new_compiler
 from distutils2.command.sdist import sdist
 from distutils2.command.install import install
-from distutils2 import __version__ as VERSION
 from distutils2.util import find_packages
 
 f = open('README.txt')

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


More information about the Python-checkins mailing list