From 5af55c63607fb6bebfc95c57e6eda5db0c669b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarek=20Ziad=C3=A9?= Date: Sat, 16 May 2009 16:52:13 +0000 Subject: [PATCH] Merged revisions 72681 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72681 | tarek.ziade | 2009-05-16 18:37:06 +0200 (Sat, 16 May 2009) | 1 line #6041: sdist and register now use the check command. No more duplicate code for metadata checking ........ --- Lib/distutils/command/register.py | 57 ++++++++++---------- Lib/distutils/command/sdist.py | 56 +++++++++----------- Lib/distutils/tests/support.py | 20 +++++++ Lib/distutils/tests/test_register.py | 79 +++++++++++++++++++++++++--- Lib/distutils/tests/test_sdist.py | 39 ++++++++++++-- Misc/NEWS | 3 ++ 6 files changed, 182 insertions(+), 72 deletions(-) diff --git a/Lib/distutils/command/register.py b/Lib/distutils/command/register.py index 7dd30999122..bdf5f8f09cc 100644 --- a/Lib/distutils/command/register.py +++ b/Lib/distutils/command/register.py @@ -10,6 +10,7 @@ __revision__ = "$Id$" import os, string, getpass import io import urllib.parse, urllib.request +from warnings import warn from distutils.core import PyPIRCCommand from distutils.errors import * @@ -21,18 +22,34 @@ class register(PyPIRCCommand): 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: @@ -41,34 +58,14 @@ class register(PyPIRCCommand): 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: " + - ", ".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. diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py index cbb77c212e5..ace9eeeb615 100644 --- a/Lib/distutils/command/sdist.py +++ b/Lib/distutils/command/sdist.py @@ -9,6 +9,8 @@ import string 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 @@ -35,6 +37,12 @@ class sdist(Command): 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]"), @@ -64,11 +72,14 @@ class sdist(Command): ('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, @@ -81,6 +92,8 @@ class sdist(Command): 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. @@ -100,6 +113,7 @@ class sdist(Command): self.dist_dir = None self.archive_files = None + self.metadata_check = 1 def finalize_options(self): if self.manifest is None: @@ -129,9 +143,9 @@ class sdist(Command): # 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, @@ -147,34 +161,12 @@ class sdist(Command): 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: " + - ", ".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 diff --git a/Lib/distutils/tests/support.py b/Lib/distutils/tests/support.py index cdcbc378623..1255413989e 100644 --- a/Lib/distutils/tests/support.py +++ b/Lib/distutils/tests/support.py @@ -12,11 +12,31 @@ class LoggingSilencer(object): def setUp(self): super().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().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. diff --git a/Lib/distutils/tests/test_register.py b/Lib/distutils/tests/test_register.py index 46f7761d808..f486cf797ed 100644 --- a/Lib/distutils/tests/test_register.py +++ b/Lib/distutils/tests/test_register.py @@ -4,10 +4,14 @@ import os import unittest import getpass import urllib +import warnings + +from 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 @@ class FakeOpener(object): def read(self): return 'xxx' -class registerTestCase(PyPIRCCommandTestCase): +class RegisterTestCase(PyPIRCCommandTestCase): def setUp(self): PyPIRCCommandTestCase.setUp(self) @@ -76,10 +80,11 @@ class registerTestCase(PyPIRCCommandTestCase): urllib.request.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 @@ class registerTestCase(PyPIRCCommandTestCase): self.assertEquals(headers['Content-length'], '290') self.assert_((b'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") diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py index 9e279337733..b7e5859cb94 100644 --- a/Lib/distutils/tests/test_sdist.py +++ b/Lib/distutils/tests/test_sdist.py @@ -6,7 +6,9 @@ import zipfile from os.path import join import sys import tempfile +import warnings +from test.support import check_warnings from test.support import captured_stdout from distutils.command.sdist import sdist @@ -16,6 +18,7 @@ from distutils.tests.test_config import PyPIRCCommandTestCase 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.dat 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 @@ class sdistTestCase(PyPIRCCommandTestCase): 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 @@ class sdistTestCase(PyPIRCCommandTestCase): 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 @@ class sdistTestCase(PyPIRCCommandTestCase): def test_suite(): - return unittest.makeSuite(sdistTestCase) + return unittest.makeSuite(SDistTestCase) if __name__ == "__main__": unittest.main(defaultTest="test_suite") diff --git a/Misc/NEWS b/Misc/NEWS index 173c096f1b4..47976ce8606 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -616,6 +616,9 @@ Core and Builtins Library ------- +- Issue #6041: Now distutils `sdist` and `register` commands use `check` as a + subcommand. + - Issue #6022: a test file was created in the current working directory by test_get_outputs in Distutils.