[Python-checkins] r72681 - in python/trunk: Lib/distutils/command/register.py Lib/distutils/command/sdist.py Lib/distutils/tests/support.py Lib/distutils/tests/test_register.py Lib/distutils/tests/test_sdist.py Misc/NEWS

tarek.ziade python-checkins at python.org
Sat May 16 18:37:06 CEST 2009


Author: tarek.ziade
Date: Sat May 16 18:37:06 2009
New Revision: 72681

Log:
#6041: sdist and register now use the check command. No more duplicate code for metadata checking

Modified:
   python/trunk/Lib/distutils/command/register.py
   python/trunk/Lib/distutils/command/sdist.py
   python/trunk/Lib/distutils/tests/support.py
   python/trunk/Lib/distutils/tests/test_register.py
   python/trunk/Lib/distutils/tests/test_sdist.py
   python/trunk/Misc/NEWS

Modified: python/trunk/Lib/distutils/command/register.py
==============================================================================
--- python/trunk/Lib/distutils/command/register.py	(original)
+++ python/trunk/Lib/distutils/command/register.py	Sat May 16 18:37:06 2009
@@ -9,6 +9,7 @@
 
 import os, string, urllib2, getpass, urlparse
 import StringIO
+from warnings import warn
 
 from distutils.core import PyPIRCCommand
 from distutils.errors import *
@@ -20,18 +21,34 @@
     user_options = PyPIRCCommand.user_options + [
         ('list-classifiers', None,
          'list the valid Trove classifiers'),
+        ('strict', None ,
+         'Will stop the registering if the meta-data are not fully compliant')
         ]
     boolean_options = PyPIRCCommand.boolean_options + [
-        'verify', 'list-classifiers']
+        'verify', 'list-classifiers', 'strict']
+
+    sub_commands = [('check', lambda self: True)]
 
     def initialize_options(self):
         PyPIRCCommand.initialize_options(self)
         self.list_classifiers = 0
+        self.strict = 0
+
+    def finalize_options(self):
+        PyPIRCCommand.finalize_options(self)
+        # setting options for the `check` subcommand
+        check_options = {'strict': ('register', self.strict),
+                         'restructuredtext': ('register', 1)}
+        self.distribution.command_options['check'] = check_options
 
     def run(self):
         self.finalize_options()
         self._set_config()
-        self.check_metadata()
+
+        # Run sub commands
+        for cmd_name in self.get_sub_commands():
+            self.run_command(cmd_name)
+
         if self.dry_run:
             self.verify_metadata()
         elif self.list_classifiers:
@@ -40,34 +57,14 @@
             self.send_metadata()
 
     def check_metadata(self):
-        """Ensure that all required elements of meta-data (name, version,
-           URL, (author and author_email) or (maintainer and
-           maintainer_email)) are supplied by the Distribution object; warn if
-           any are missing.
-        """
-        metadata = self.distribution.metadata
-
-        missing = []
-        for attr in ('name', 'version', 'url'):
-            if not (hasattr(metadata, attr) and getattr(metadata, attr)):
-                missing.append(attr)
-
-        if missing:
-            self.warn("missing required meta-data: " +
-                      string.join(missing, ", "))
-
-        if metadata.author:
-            if not metadata.author_email:
-                self.warn("missing meta-data: if 'author' supplied, " +
-                          "'author_email' must be supplied too")
-        elif metadata.maintainer:
-            if not metadata.maintainer_email:
-                self.warn("missing meta-data: if 'maintainer' supplied, " +
-                          "'maintainer_email' must be supplied too")
-        else:
-            self.warn("missing meta-data: either (author and author_email) " +
-                      "or (maintainer and maintainer_email) " +
-                      "must be supplied")
+        """Deprecated API."""
+        warn("distutils.command.register.check_metadata is deprecated, \
+              use the check command instead", PendingDeprecationWarning)
+        check = self.distribution.get_command_obj('check')
+        check.ensure_finalized()
+        check.strict = self.strict
+        check.restructuredtext = 1
+        check.run()
 
     def _set_config(self):
         ''' Reads the configuration file and set attributes.

Modified: python/trunk/Lib/distutils/command/sdist.py
==============================================================================
--- python/trunk/Lib/distutils/command/sdist.py	(original)
+++ python/trunk/Lib/distutils/command/sdist.py	Sat May 16 18:37:06 2009
@@ -8,6 +8,8 @@
 import sys
 from types import *
 from glob import glob
+from warnings import warn
+
 from distutils.core import Command
 from distutils import dir_util, dep_util, file_util, archive_util
 from distutils.text_file import TextFile
@@ -34,6 +36,12 @@
 
     description = "create a source distribution (tarball, zip file, etc.)"
 
+    def checking_metadata(self):
+        """Callable used for the check sub-command.
+
+        Placed here so user_options can view it"""
+        return self.metadata_check
+
     user_options = [
         ('template=', 't',
          "name of manifest template file [default: MANIFEST.in]"),
@@ -63,11 +71,14 @@
         ('dist-dir=', 'd',
          "directory to put the source distribution archive(s) in "
          "[default: dist]"),
+        ('medata-check', None,
+         "Ensure that all required elements of meta-data "
+         "are supplied. Warn if any missing. [default]"),
         ]
 
     boolean_options = ['use-defaults', 'prune',
                        'manifest-only', 'force-manifest',
-                       'keep-temp']
+                       'keep-temp', 'metadata-check']
 
     help_options = [
         ('help-formats', None,
@@ -80,6 +91,8 @@
     default_format = {'posix': 'gztar',
                       'nt': 'zip' }
 
+    sub_commands = [('check', checking_metadata)]
+
     def initialize_options(self):
         # 'template' and 'manifest' are, respectively, the names of
         # the manifest template and manifest file.
@@ -99,6 +112,7 @@
         self.dist_dir = None
 
         self.archive_files = None
+        self.metadata_check = 1
 
     def finalize_options(self):
         if self.manifest is None:
@@ -128,9 +142,9 @@
         # manifest
         self.filelist = FileList()
 
-        # Ensure that all required meta-data is given; warn if not (but
-        # don't die, it's not *that* serious!)
-        self.check_metadata()
+        # Run sub commands
+        for cmd_name in self.get_sub_commands():
+            self.run_command(cmd_name)
 
         # Do whatever it takes to get the list of files to process
         # (process the manifest template, read an existing manifest,
@@ -146,34 +160,12 @@
         self.make_distribution()
 
     def check_metadata(self):
-        """Ensure that all required elements of meta-data (name, version,
-        URL, (author and author_email) or (maintainer and
-        maintainer_email)) are supplied by the Distribution object; warn if
-        any are missing.
-        """
-        metadata = self.distribution.metadata
-
-        missing = []
-        for attr in ('name', 'version', 'url'):
-            if not (hasattr(metadata, attr) and getattr(metadata, attr)):
-                missing.append(attr)
-
-        if missing:
-            self.warn("missing required meta-data: " +
-                      string.join(missing, ", "))
-
-        if metadata.author:
-            if not metadata.author_email:
-                self.warn("missing meta-data: if 'author' supplied, " +
-                          "'author_email' must be supplied too")
-        elif metadata.maintainer:
-            if not metadata.maintainer_email:
-                self.warn("missing meta-data: if 'maintainer' supplied, " +
-                          "'maintainer_email' must be supplied too")
-        else:
-            self.warn("missing meta-data: either (author and author_email) " +
-                      "or (maintainer and maintainer_email) " +
-                      "must be supplied")
+        """Deprecated API."""
+        warn("distutils.command.sdist.check_metadata is deprecated, \
+              use the check command instead", PendingDeprecationWarning)
+        check = self.distribution.get_command_obj('check')
+        check.ensure_finalized()
+        check.run()
 
     def get_file_list(self):
         """Figure out the list of files to include in the source

Modified: python/trunk/Lib/distutils/tests/support.py
==============================================================================
--- python/trunk/Lib/distutils/tests/support.py	(original)
+++ python/trunk/Lib/distutils/tests/support.py	Sat May 16 18:37:06 2009
@@ -12,11 +12,31 @@
     def setUp(self):
         super(LoggingSilencer, self).setUp()
         self.threshold = log.set_threshold(log.FATAL)
+        # catching warnings
+        # when log will be replaced by logging
+        # we won't need such monkey-patch anymore
+        self._old_log = log.Log._log
+        log.Log._log = self._log
+        self.logs = []
 
     def tearDown(self):
         log.set_threshold(self.threshold)
+        log.Log._log = self._old_log
         super(LoggingSilencer, self).tearDown()
 
+    def _log(self, level, msg, args):
+        self.logs.append((level, msg, args))
+
+    def get_logs(self, *levels):
+        def _format(msg, args):
+            if len(args) == 0:
+                return msg
+            return msg % args
+        return [_format(msg, args) for level, msg, args
+                in self.logs if level in levels]
+
+    def clear_logs(self):
+        self.logs = []
 
 class TempdirManager(object):
     """Mix-in class that handles temporary directories for test cases.

Modified: python/trunk/Lib/distutils/tests/test_register.py
==============================================================================
--- python/trunk/Lib/distutils/tests/test_register.py	(original)
+++ python/trunk/Lib/distutils/tests/test_register.py	Sat May 16 18:37:06 2009
@@ -4,10 +4,14 @@
 import unittest
 import getpass
 import urllib2
+import warnings
+
+from test.test_support import check_warnings
 
 from distutils.command import register as register_module
 from distutils.command.register import register
 from distutils.core import Distribution
+from distutils.errors import DistutilsSetupError
 
 from distutils.tests import support
 from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
@@ -59,7 +63,7 @@
     def read(self):
         return 'xxx'
 
-class registerTestCase(PyPIRCCommandTestCase):
+class RegisterTestCase(PyPIRCCommandTestCase):
 
     def setUp(self):
         PyPIRCCommandTestCase.setUp(self)
@@ -76,10 +80,11 @@
         urllib2.build_opener = self.old_opener
         PyPIRCCommandTestCase.tearDown(self)
 
-    def _get_cmd(self):
-        metadata = {'url': 'xxx', 'author': 'xxx',
-                    'author_email': 'xxx',
-                    'name': 'xxx', 'version': 'xxx'}
+    def _get_cmd(self, metadata=None):
+        if metadata is None:
+            metadata = {'url': 'xxx', 'author': 'xxx',
+                        'author_email': 'xxx',
+                        'name': 'xxx', 'version': 'xxx'}
         pkg_info, dist = self.create_dist(**metadata)
         return register(dist)
 
@@ -184,8 +189,70 @@
         self.assertEquals(headers['Content-length'], '290')
         self.assert_('tarek' in req.data)
 
+    def test_strict(self):
+        # testing the script option
+        # when on, the register command stops if
+        # the metadata is incomplete or if
+        # long_description is not reSt compliant
+
+        # empty metadata
+        cmd = self._get_cmd({})
+        cmd.ensure_finalized()
+        cmd.strict = 1
+        self.assertRaises(DistutilsSetupError, cmd.run)
+
+        # we don't test the reSt feature if docutils
+        # is not installed
+        try:
+            import docutils
+        except ImportError:
+            return
+
+        # metadata are OK but long_description is broken
+        metadata = {'url': 'xxx', 'author': 'xxx',
+                    'author_email': 'xxx',
+                    'name': 'xxx', 'version': 'xxx',
+                    'long_description': 'title\n==\n\ntext'}
+
+        cmd = self._get_cmd(metadata)
+        cmd.ensure_finalized()
+        cmd.strict = 1
+        self.assertRaises(DistutilsSetupError, cmd.run)
+
+        # now something that works
+        metadata['long_description'] = 'title\n=====\n\ntext'
+        cmd = self._get_cmd(metadata)
+        cmd.ensure_finalized()
+        cmd.strict = 1
+        inputs = RawInputs('1', 'tarek', 'y')
+        register_module.raw_input = inputs.__call__
+        # let's run the command
+        try:
+            cmd.run()
+        finally:
+            del register_module.raw_input
+
+        # strict is not by default
+        cmd = self._get_cmd()
+        cmd.ensure_finalized()
+        inputs = RawInputs('1', 'tarek', 'y')
+        register_module.raw_input = inputs.__call__
+        # let's run the command
+        try:
+            cmd.run()
+        finally:
+            del register_module.raw_input
+
+    def test_check_metadata_deprecated(self):
+        # makes sure make_metadata is deprecated
+        cmd = self._get_cmd()
+        with check_warnings() as w:
+            warnings.simplefilter("always")
+            cmd.check_metadata()
+            self.assertEquals(len(w.warnings), 1)
+
 def test_suite():
-    return unittest.makeSuite(registerTestCase)
+    return unittest.makeSuite(RegisterTestCase)
 
 if __name__ == "__main__":
     unittest.main(defaultTest="test_suite")

Modified: python/trunk/Lib/distutils/tests/test_sdist.py
==============================================================================
--- python/trunk/Lib/distutils/tests/test_sdist.py	(original)
+++ python/trunk/Lib/distutils/tests/test_sdist.py	Sat May 16 18:37:06 2009
@@ -6,7 +6,9 @@
 from os.path import join
 import sys
 import tempfile
+import warnings
 
+from test.test_support import check_warnings
 from test.test_support import captured_stdout
 
 from distutils.command.sdist import sdist
@@ -16,6 +18,7 @@
 from distutils.errors import DistutilsExecError, DistutilsOptionError
 from distutils.spawn import find_executable
 from distutils.tests import support
+from distutils.log import WARN
 from distutils.archive_util import ARCHIVE_FORMATS
 
 SETUP_PY = """
@@ -38,12 +41,12 @@
 somecode%(sep)sdoc.txt
 """
 
-class sdistTestCase(PyPIRCCommandTestCase):
+class SDistTestCase(PyPIRCCommandTestCase):
 
     def setUp(self):
         # PyPIRCCommandTestCase creates a temp dir already
         # and put it in self.tmp_dir
-        super(sdistTestCase, self).setUp()
+        super(SDistTestCase, self).setUp()
         # setting up an environment
         self.old_path = os.getcwd()
         os.mkdir(join(self.tmp_dir, 'somecode'))
@@ -57,7 +60,7 @@
     def tearDown(self):
         # back to normal
         os.chdir(self.old_path)
-        super(sdistTestCase, self).tearDown()
+        super(SDistTestCase, self).tearDown()
 
     def get_cmd(self, metadata=None):
         """Returns a cmd"""
@@ -214,6 +217,34 @@
         manifest = open(join(self.tmp_dir, 'MANIFEST')).read()
         self.assertEquals(manifest, MANIFEST % {'sep': os.sep})
 
+    def test_metadata_check_option(self):
+        # testing the `medata-check` option
+        dist, cmd = self.get_cmd(metadata={})
+
+        # this should raise some warnings !
+        # with the `check` subcommand
+        cmd.ensure_finalized()
+        cmd.run()
+        warnings = self.get_logs(WARN)
+        self.assertEquals(len(warnings), 2)
+
+        # trying with a complete set of metadata
+        self.clear_logs()
+        dist, cmd = self.get_cmd()
+        cmd.ensure_finalized()
+        cmd.metadata_check = 0
+        cmd.run()
+        warnings = self.get_logs(WARN)
+        self.assertEquals(len(warnings), 0)
+
+    def test_check_metadata_deprecated(self):
+        # makes sure make_metadata is deprecated
+        dist, cmd = self.get_cmd()
+        with check_warnings() as w:
+            warnings.simplefilter("always")
+            cmd.check_metadata()
+            self.assertEquals(len(w.warnings), 1)
+
     def test_show_formats(self):
         with captured_stdout() as stdout:
             show_formats()
@@ -247,7 +278,7 @@
 
 
 def test_suite():
-    return unittest.makeSuite(sdistTestCase)
+    return unittest.makeSuite(SDistTestCase)
 
 if __name__ == "__main__":
     unittest.main(defaultTest="test_suite")

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sat May 16 18:37:06 2009
@@ -293,6 +293,9 @@
 Library
 -------
 
+- Issue #6041: Now distutils `sdist` and `register` commands use `check` as a 
+  subcommand.
+
 - Issue #2116: Weak references and weak dictionaries now support copy()ing and
   deepcopy()ing.
 


More information about the Python-checkins mailing list