[Python-checkins] distutils2: Branch merge

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


tarek.ziade pushed d5aa0034f8ed to distutils2:

http://hg.python.org/distutils2/rev/d5aa0034f8ed
changeset:   493:d5aa0034f8ed
parent:      489:bce5ffe93848
parent:      492:21e341cd6b11
user:        ?ric Araujo <merwok at netwok.org>
date:        Fri Aug 06 06:18:02 2010 +0200
summary:     Branch merge
files:       src/distutils2/dist.py

diff --git a/src/distutils2/__init__.py b/src/distutils2/__init__.py
--- a/src/distutils2/__init__.py
+++ b/src/distutils2/__init__.py
@@ -20,7 +20,7 @@
 __version__ = "1.0a2"
 
 
-# when set to True, converts doctests by default too 
+# when set to True, converts doctests by default too
 run_2to3_on_doctests = True
 # Standard package names for fixer packages
 lib2to3_fixer_packages = ['lib2to3.fixes']
diff --git a/src/distutils2/core.py b/src/distutils2/core.py
--- a/src/distutils2/core.py
+++ b/src/distutils2/core.py
@@ -33,6 +33,7 @@
    or: %(script)s cmd --help
 """
 
+
 def gen_usage(script_name):
     script = os.path.basename(script_name)
     return USAGE % {'script': script}
@@ -59,6 +60,7 @@
                       'extra_objects', 'extra_compile_args', 'extra_link_args',
                       'swig_opts', 'export_symbols', 'depends', 'language')
 
+
 def setup(**attrs):
     """The gateway to the Distutils: do everything your setup script needs
     to do, in a highly flexible and user-driven way.  Briefly: create a
diff --git a/src/distutils2/depgraph.py b/src/distutils2/depgraph.py
--- a/src/distutils2/depgraph.py
+++ b/src/distutils2/depgraph.py
@@ -1,5 +1,5 @@
-"""Analyse the relationships between the distributions in the system and generate
-a dependency graph.
+"""Analyse the relationships between the distributions in the system
+and generate a dependency graph.
 """
 
 from distutils2.errors import DistutilsError
diff --git a/src/distutils2/dist.py b/src/distutils2/dist.py
--- a/src/distutils2/dist.py
+++ b/src/distutils2/dist.py
@@ -6,12 +6,10 @@
 
 __revision__ = "$Id: dist.py 77717 2010-01-24 00:33:32Z tarek.ziade $"
 
-import sys, os, re
-
-try:
-    import warnings
-except ImportError:
-    warnings = None
+import sys
+import os
+import re
+import warnings
 
 from ConfigParser import RawConfigParser
 
@@ -26,7 +24,8 @@
 # the same as a Python NAME -- I don't allow leading underscores.  The fact
 # that they're very similar is no coincidence; the default naming scheme is
 # to look for a Python module named after the command.
-command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
+command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
+
 
 class Distribution(object):
     """The core of the Distutils.  Most of the work hiding behind 'setup'
@@ -123,10 +122,8 @@
     # negative options are options that exclude other options
     negative_opt = {'quiet': 'verbose'}
 
-
     # -- Creation/initialization methods -------------------------------
-
-    def __init__ (self, attrs=None):
+    def __init__(self, attrs=None):
         """Construct a new Distribution instance: initialize all the
         attributes of a Distribution, and then use 'attrs' (a dictionary
         mapping attribute names to values) to assign some of those
@@ -251,10 +248,7 @@
                     setattr(self, key, val)
                 else:
                     msg = "Unknown distribution option: %r" % key
-                    if warnings is not None:
-                        warnings.warn(msg)
-                    else:
-                        sys.stderr.write(msg + "\n")
+                    warnings.warn(msg)
 
         # no-user-cfg is handled before other command line args
         # because other args override the config files, and this
@@ -565,10 +559,10 @@
 
         if (hasattr(cmd_class, 'help_options') and
             isinstance(cmd_class.help_options, list)):
-            help_option_found=0
+            help_option_found = 0
             for (help_option, short, desc, func) in cmd_class.help_options:
                 if hasattr(opts, parser.get_attr_name(help_option)):
-                    help_option_found=1
+                    help_option_found = 1
                     if hasattr(func, '__call__'):
                         func()
                     else:
@@ -807,7 +801,7 @@
             class_name = command
 
             try:
-                __import__ (module_name)
+                __import__(module_name)
                 module = sys.modules[module_name]
             except ImportError:
                 continue
@@ -824,7 +818,6 @@
 
         raise DistutilsModuleError("invalid command '%s'" % command)
 
-
     def get_command_obj(self, command, create=1):
         """Return the command object for 'command'.  Normally this object
         is cached on a previous call to 'get_command_obj()'; if no command
@@ -967,7 +960,6 @@
         self.run_command_hooks(cmd_obj, 'post_hook')
         self.have_run[command] = 1
 
-
     def run_command_hooks(self, cmd_obj, hook_kind):
         hooks = getattr(cmd_obj, hook_kind)
         if hooks is None:
@@ -977,7 +969,6 @@
             hook_func(cmd_obj)
 
     # -- Distribution query methods ------------------------------------
-
     def has_pure_modules(self):
         return len(self.packages or self.py_modules or []) > 0
 
diff --git a/src/distutils2/errors.py b/src/distutils2/errors.py
--- a/src/distutils2/errors.py
+++ b/src/distutils2/errors.py
@@ -10,31 +10,38 @@
 
 __revision__ = "$Id: errors.py 75901 2009-10-28 06:45:18Z tarek.ziade $"
 
+
 class DistutilsError(Exception):
     """The root of all Distutils evil."""
 
+
 class DistutilsModuleError(DistutilsError):
     """Unable to load an expected module, or to find an expected class
     within some module (in particular, command modules and classes)."""
 
+
 class DistutilsClassError(DistutilsError):
     """Some command class (or possibly distribution class, if anyone
     feels a need to subclass Distribution) is found not to be holding
     up its end of the bargain, ie. implementing some part of the
     "command "interface."""
 
+
 class DistutilsGetoptError(DistutilsError):
     """The option table provided to 'fancy_getopt()' is bogus."""
 
+
 class DistutilsArgError(DistutilsError):
     """Raised by fancy_getopt in response to getopt.error -- ie. an
     error in the command line usage."""
 
+
 class DistutilsFileError(DistutilsError):
     """Any problems in the filesystem: expected file not found, etc.
     Typically this is for problems that we detect before IOError or
     OSError could be raised."""
 
+
 class DistutilsOptionError(DistutilsError):
     """Syntactic/semantic errors in command options, such as use of
     mutually conflicting options, or inconsistent options,
@@ -43,60 +50,76 @@
     files, or what-have-you -- but if we *know* something originated in
     the setup script, we'll raise DistutilsSetupError instead."""
 
+
 class DistutilsSetupError(DistutilsError):
     """For errors that can be definitely blamed on the setup script,
     such as invalid keyword arguments to 'setup()'."""
 
+
 class DistutilsPlatformError(DistutilsError):
     """We don't know how to do something on the current platform (but
     we do know how to do it on some platform) -- eg. trying to compile
     C files on a platform not supported by a CCompiler subclass."""
 
+
 class DistutilsExecError(DistutilsError):
     """Any problems executing an external program (such as the C
     compiler, when compiling C files)."""
 
+
 class DistutilsInternalError(DistutilsError):
     """Internal inconsistencies or impossibilities (obviously, this
     should never be seen if the code is working!)."""
 
+
 class DistutilsTemplateError(DistutilsError):
     """Syntax error in a file list template."""
 
+
 class DistutilsByteCompileError(DistutilsError):
     """Byte compile error."""
 
+
 # Exception classes used by the CCompiler implementation classes
 class CCompilerError(Exception):
     """Some compile/link operation failed."""
 
+
 class PreprocessError(CCompilerError):
     """Failure to preprocess one or more C/C++ files."""
 
+
 class CompileError(CCompilerError):
     """Failure to compile one or more C/C++ source files."""
 
+
 class LibError(CCompilerError):
     """Failure to create a static library from one or more C/C++ object
     files."""
 
+
 class LinkError(CCompilerError):
     """Failure to link one or more C/C++ object files into an executable
     or shared library file."""
 
+
 class UnknownFileError(CCompilerError):
     """Attempt to process an unknown file type."""
 
+
 class MetadataConflictError(DistutilsError):
     """Attempt to read or write metadata fields that are conflictual."""
 
+
 class MetadataUnrecognizedVersionError(DistutilsError):
     """Unknown metadata version number."""
 
+
 class IrrationalVersionError(Exception):
     """This is an irrational version."""
     pass
 
+
 class HugeMajorVersionNumError(IrrationalVersionError):
     """An irrational version because the major version number is huge
     (often because a year or date was used).
@@ -105,4 +128,3 @@
     This guard can be disabled by setting that option False.
     """
     pass
-
diff --git a/src/distutils2/extension.py b/src/distutils2/extension.py
--- a/src/distutils2/extension.py
+++ b/src/distutils2/extension.py
@@ -17,6 +17,7 @@
 # import that large-ish module (indirectly, through distutils.core) in
 # order to do anything.
 
+
 class Extension(object):
     """Just a collection of attributes that describes an extension
     module and everything needed to build it (hopefully in a portable
@@ -84,7 +85,7 @@
 
     # When adding arguments to this constructor, be sure to update
     # setup_keywords in core.py.
-    def __init__ (self, name, sources,
+    def __init__(self, name, sources,
                   include_dirs=None,
                   define_macros=None,
                   undef_macros=None,
@@ -95,11 +96,11 @@
                   extra_compile_args=None,
                   extra_link_args=None,
                   export_symbols=None,
-                  swig_opts = None,
+                  swig_opts=None,
                   depends=None,
                   language=None,
                   optional=None,
-                  **kw                      # To catch unknown keywords
+                  **kw # To catch unknown keywords
                  ):
         if not isinstance(name, str):
             raise AssertionError("'name' must be a string")
@@ -134,4 +135,3 @@
             options = ', '.join(sorted(options))
             msg = "Unknown Extension options: %s" % options
             warnings.warn(msg)
-
diff --git a/src/distutils2/fancy_getopt.py b/src/distutils2/fancy_getopt.py
--- a/src/distutils2/fancy_getopt.py
+++ b/src/distutils2/fancy_getopt.py
@@ -30,6 +30,7 @@
 # (for use as attributes of some object).
 longopt_xlate = string.maketrans('-', '_')
 
+
 class FancyGetopt(object):
     """Wrapper around the standard 'getopt()' module that provides some
     handy extra functionality:
@@ -42,7 +43,7 @@
         on the command line sets 'verbose' to false
     """
 
-    def __init__ (self, option_table=None):
+    def __init__(self, option_table=None):
 
         # The option table is (currently) a list of tuples.  The
         # tuples may have 3 or four values:
@@ -180,7 +181,8 @@
             self.long_opts.append(long)
 
             if long[-1] == '=':             # option takes an argument?
-                if short: short = short + ':'
+                if short:
+                    short = short + ':'
                 long = long[0:-1]
                 self.takes_arg[long] = 1
             else:
diff --git a/src/distutils2/manifest.py b/src/distutils2/manifest.py
--- a/src/distutils2/manifest.py
+++ b/src/distutils2/manifest.py
@@ -22,7 +22,7 @@
 
 # a \ followed by some spaces + EOL
 _COLLAPSE_PATTERN = re.compile('\\\w*\n', re.M)
-_COMMENTED_LINE = re.compile('#.*?(?=\n)|^\w*\n|\n(?=$)', re.M|re.S)
+_COMMENTED_LINE = re.compile('#.*?(?=\n)|^\w*\n|\n(?=$)', re.M | re.S)
 
 class Manifest(object):
     """A list of files built by on exploring the filesystem and filtered by
diff --git a/src/distutils2/metadata.py b/src/distutils2/metadata.py
--- a/src/distutils2/metadata.py
+++ b/src/distutils2/metadata.py
@@ -52,12 +52,12 @@
 PKG_INFO_PREFERRED_VERSION = '1.0'
 
 _LINE_PREFIX = re.compile('\n       \|')
-_241_FIELDS = ('Metadata-Version',  'Name', 'Version', 'Platform',
+_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
                'Summary', 'Description',
                'Keywords', 'Home-page', 'Author', 'Author-email',
                'License')
 
-_314_FIELDS = ('Metadata-Version',  'Name', 'Version', 'Platform',
+_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
                'Supported-Platform', 'Summary', 'Description',
                'Keywords', 'Home-page', 'Author', 'Author-email',
                'License', 'Classifier', 'Download-URL', 'Obsoletes',
@@ -65,7 +65,7 @@
 
 _314_MARKERS = ('Obsoletes', 'Provides', 'Requires')
 
-_345_FIELDS = ('Metadata-Version',  'Name', 'Version', 'Platform',
+_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
                'Supported-Platform', 'Summary', 'Description',
                'Keywords', 'Home-page', 'Author', 'Author-email',
                'Maintainer', 'Maintainer-email', 'License',
diff --git a/src/distutils2/mkpkg.py b/src/distutils2/mkpkg.py
--- a/src/distutils2/mkpkg.py
+++ b/src/distutils2/mkpkg.py
@@ -30,7 +30,11 @@
 #
 #    Detect scripts (not sure how.  #! outside of package?)
 
-import sys, os, re, shutil, ConfigParser
+import sys
+import os
+import re
+import shutil
+import ConfigParser
 
 
 helpText = {
@@ -629,19 +633,20 @@
         print '\nERROR: You must select "Y" or "N".\n'
 
 
-def ask(question, default = None, helptext = None, required = True,
-        lengthy = False, multiline = False):
-    prompt = '%s: ' % ( question, )
+def ask(question, default=None, helptext=None, required=True,
+        lengthy=False, multiline=False):
+    prompt = '%s: ' % (question,)
     if default:
-        prompt = '%s [%s]: ' % ( question, default )
+        prompt = '%s [%s]: ' % (question, default)
         if default and len(question) + len(default) > 70:
-            prompt = '%s\n    [%s]: ' % ( question, default )
+            prompt = '%s\n    [%s]: ' % (question, default)
     if lengthy or multiline:
         prompt += '\n   >'
 
-    if not helptext: helptext = 'No additional help available.'
-    if helptext[0] == '\n': helptext = helptext[1:]
-    if helptext[-1] == '\n': helptext = helptext[:-1]
+    if not helptext:
+        helptext = 'No additional help available.'
+
+    helptext = helptext.strip("\n")
 
     while True:
         sys.stdout.write(prompt)
@@ -653,12 +658,14 @@
             print helptext
             print '=' * 70
             continue
-        if default and not line: return(default)
+        if default and not line:
+            return(default)
         if not line and required:
             print '*' * 70
             print 'This value cannot be empty.'
             print '==========================='
-            if helptext: print helptext
+            if helptext:
+                print helptext
             print '*' * 70
             continue
         return(line)
@@ -669,7 +676,8 @@
     for key in troveList:
         subDict = dict
         for subkey in key.split(' :: '):
-            if not subkey in subDict: subDict[subkey] = {}
+            if not subkey in subDict:
+                subDict[subkey] = {}
             subDict = subDict[subkey]
     return(dict)
 troveDict = buildTroveDict(troveList)
@@ -687,7 +695,8 @@
 
 
     def lookupOption(self, key):
-        if not self.config.has_option('DEFAULT', key): return(None)
+        if not self.config.has_option('DEFAULT', key):
+            return(None)
         return(self.config.get('DEFAULT', key))
 
 
@@ -706,7 +715,8 @@
                 self.config.set('DEFAULT', compareKey,
                     self.setupData[compareKey])
 
-        if not valuesDifferent: return
+        if not valuesDifferent:
+            return
 
         self.config.write(open(os.path.expanduser('~/.pygiver'), 'w'))
 
@@ -718,7 +728,7 @@
     def inspectFile(self, path):
         fp = open(path, 'r')
         try:
-            for line in [ fp.readline() for x in range(10) ]:
+            for line in [fp.readline() for x in range(10)]:
                 m = re.match(r'^#!.*python((?P<major>\d)(\.\d+)?)?$', line)
                 if m:
                     if m.group('major') == '3':
@@ -761,16 +771,16 @@
               self.setupData.get('version'), helpText['version'])
         self.setupData['description'] = ask('Package description',
               self.setupData.get('description'), helpText['description'],
-              lengthy = True)
+              lengthy=True)
         self.setupData['author'] = ask('Author name',
               self.setupData.get('author'), helpText['author'])
         self.setupData['author_email'] = ask('Author e-mail address',
               self.setupData.get('author_email'), helpText['author_email'])
         self.setupData['url'] = ask('Project URL',
-              self.setupData.get('url'), helpText['url'], required = False)
+              self.setupData.get('url'), helpText['url'], required=False)
 
         if (askYn('Do you want to set Trove classifiers?',
-                helptext = helpText['do_classifier']) == 'y'):
+                helptext=helpText['do_classifier']) == 'y'):
             self.setTroveClassifier()
 
 
@@ -781,8 +791,10 @@
 
 
     def setTroveOther(self, classifierDict):
-        if askYn('Do you want to set other trove identifiers', 'n',
-                helpText['trove_generic']) != 'y': return
+        if askYn('Do you want to set other trove identifiers',
+                'n',
+                helpText['trove_generic']) != 'y':
+            return
 
         self.walkTrove(classifierDict, [troveDict], '')
 
@@ -799,7 +811,7 @@
                 continue
 
             if askYn('Do you want to set items under\n   "%s" (%d sub-items)'
-                    % ( key, len(trove[key]) ), 'n',
+                    % (key, len(trove[key])), 'n',
                     helpText['trove_generic']) == 'y':
                 self.walkTrove(classifierDict, trovePath + [trove[key]],
                         desc + ' :: ' + key)
@@ -808,15 +820,18 @@
     def setTroveLicense(self, classifierDict):
         while True:
             license = ask('What license do you use',
-                  helptext = helpText['trove_license'], required = False)
-            if not license: return
+                        helptext=helpText['trove_license'],
+                        required=False)
+            if not license:
+                return
 
             licenseWords = license.lower().split(' ')
 
             foundList = []
             for index in range(len(troveList)):
                 troveItem = troveList[index]
-                if not troveItem.startswith('License :: '): continue
+                if not troveItem.startswith('License :: '):
+                    continue
                 troveItem = troveItem[11:].lower()
 
                 allMatch = True
@@ -824,17 +839,20 @@
                     if not word in troveItem:
                         allMatch = False
                         break
-                if allMatch: foundList.append(index)
+                if allMatch:
+                    foundList.append(index)
 
             question = 'Matching licenses:\n\n'
             for i in xrange(1, len(foundList) + 1):
-                question += '   %s) %s\n' % ( i, troveList[foundList[i - 1]] )
+                question += '   %s) %s\n' % (i, troveList[foundList[i - 1]])
             question += ('\nType the number of the license you wish to use or '
                      '? to try again:')
-            troveLicense = ask(question, required = False)
+            troveLicense = ask(question, required=False)
 
-            if troveLicense == '?': continue
-            if troveLicense == '': return
+            if troveLicense == '?':
+                continue
+            if troveLicense == '':
+                return
             foundIndex = foundList[int(troveLicense) - 1]
             classifierDict[troveList[foundIndex]] = 1
             try:
@@ -856,7 +874,7 @@
 6 - Mature
 7 - Inactive
 
-Status''', required = False)
+Status''', required=False)
             if devStatus:
                 try:
                     key = {
@@ -884,7 +902,8 @@
         return modified_pkgs
 
     def writeSetup(self):
-        if os.path.exists('setup.py'): shutil.move('setup.py', 'setup.py.old')
+        if os.path.exists('setup.py'):
+            shutil.move('setup.py', 'setup.py.old')
 
         fp = open('setup.py', 'w')
         try:
diff --git a/src/distutils2/tests/test_dist.py b/src/distutils2/tests/test_dist.py
--- a/src/distutils2/tests/test_dist.py
+++ b/src/distutils2/tests/test_dist.py
@@ -153,6 +153,27 @@
         my_file2 = os.path.join(tmp_dir, 'f2')
         dist.metadata.write_file(open(my_file, 'w'))
 
+    def test_bad_attr(self):
+        cls = Distribution
+
+        # catching warnings
+        warns = []
+        def _warn(msg):
+            warns.append(msg)
+
+        old_warn = warnings.warn
+        warnings.warn = _warn
+        try:
+            dist = cls(attrs={'author': 'xxx',
+                              'name': 'xxx',
+                              'version': 'xxx',
+                              'url': 'xxxx',
+                              'badoptname': 'xxx'})
+        finally:
+            warnings.warn = old_warn
+
+        self.assertTrue(len(warns)==1 and "Unknown distribution" in warns[0])
+
     def test_empty_options(self):
         # an empty options dictionary should not stay in the
         # list of attributes
@@ -176,6 +197,21 @@
 
         self.assertEqual(len(warns), 0)
 
+    def test_non_empty_options(self):
+        # TODO: how to actually use options is not documented except
+        # for a few cryptic comments in dist.py.  If this is to stay
+        # in the public API, it deserves some better documentation.
+
+        # Here is an example of how it's used out there: 
+        # http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html#specifying-customizations
+        cls = Distribution
+        dist = cls(attrs={'author': 'xxx',
+                          'name': 'xxx',
+                          'version': 'xxx',
+                          'url': 'xxxx',
+                          'options': dict(sdist=dict(owner="root"))})
+        self.assertTrue("owner" in dist.get_option_dict("sdist"))
+
     def test_finalize_options(self):
 
         attrs = {'keywords': 'one,two',
diff --git a/src/runtests-cov.py b/src/runtests-cov.py
--- a/src/runtests-cov.py
+++ b/src/runtests-cov.py
@@ -5,9 +5,19 @@
 """
 
 import sys
-from os.path import dirname, islink, realpath
+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
@@ -44,10 +54,17 @@
 
 
 def coverage_report(opts):
-    import coverage
     from distutils2.tests.support import unittest
-    cov = coverage.coverage()
-    cov.load()
+    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)
@@ -66,7 +83,7 @@
         # that module is also completely optional
         pass
 
-    cov.report(omit_prefixes=prefixes, show_missing=opts.show_missing)
+    cov.report(morfs, omit_prefixes=prefixes, show_missing=opts.show_missing)
 
 
 def test_main():
@@ -74,11 +91,8 @@
     verbose = not opts.quiet
     ret = 0
 
-    if opts.coverage or opts.report:
-        import coverage
-
     if opts.coverage:
-        cov = coverage.coverage()
+        cov = get_coverage()
         cov.erase()
         cov.start()
     if not opts.report:

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


More information about the Python-checkins mailing list