[Python-checkins] distutils2 (merge default -> python3): Merge fix for #13205 and other changes from default.

eric.araujo python-checkins at python.org
Fri Oct 21 15:57:56 CEST 2011


http://hg.python.org/distutils2/rev/eb845a9a00b7
changeset:   1219:eb845a9a00b7
branch:      python3
parent:      1215:6b57f8917452
parent:      1218:5949563b9f1c
user:        Éric Araujo <merwok at netwok.org>
date:        Fri Oct 21 07:08:31 2011 +0200
summary:
  Merge fix for #13205 and other changes from default.

The deprecation warning emitted by RawConfigParser.readfp (used in util
and config, and from config in many places) will be annoying for
developers using distutils2 as a library; maybe we should drop 3.1
compat (people are expected to switch from 2.7 to 3.2 directly) and
switch to RawConfigParser.read_file.

One test in test_pypi_simple fails on 3.3 due to a recent change (see
#10680); I didn’t fix it because I can’t open the bug report that the
test was written for, and anyway the whole file should be rewritten to
use assertRaises.  I have to leave some things for Alexis :)

files:
  distutils2/tests/support.py   |   9 ++++
  distutils2/tests/test_util.py |  43 ++++++++++++++++---
  distutils2/util.py            |  50 +++++++++++++++++-----
  setup.cfg                     |   2 +-
  4 files changed, 85 insertions(+), 19 deletions(-)


diff --git a/distutils2/tests/support.py b/distutils2/tests/support.py
--- a/distutils2/tests/support.py
+++ b/distutils2/tests/support.py
@@ -429,6 +429,15 @@
     return _assert_python(True, *args, **env_vars)
 
 
+def assert_python_failure(*args, **env_vars):
+    """
+    Assert that running the interpreter with `args` and optional environment
+    variables `env_vars` fails and return a (return code, stdout, stderr)
+    tuple.
+    """
+    return _assert_python(False, *args, **env_vars)
+
+
 def unload(name):
     try:
         del sys.modules[name]
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
@@ -4,11 +4,11 @@
 import time
 import logging
 import tempfile
+import textwrap
+import warnings
 import subprocess
 from io import StringIO
 
-from distutils2.tests import support, unittest
-from distutils2.tests.test_config import SETUP_CFG
 from distutils2.errors import (
     PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
     PackagingExecError, InstallationException)
@@ -19,7 +19,11 @@
     get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
     spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
     RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
-    get_install_method, cfg_to_args, encode_multipart)
+    get_install_method, cfg_to_args, generate_setup_py, encode_multipart)
+
+from distutils2.tests import support, unittest
+from distutils2.tests.test_config import SETUP_CFG
+from distutils2.tests.support import assert_python_ok, assert_python_failure
 
 
 PYPIRC = """\
@@ -503,10 +507,14 @@
         self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
         self.write_file('README', 'loooong description')
 
-        args = cfg_to_args()
+        with warnings.catch_warnings():
+            warnings.simplefilter('ignore', DeprecationWarning)
+            args = cfg_to_args()
         # use Distribution to get the contents of the setup.cfg file
         dist = Distribution()
-        dist.parse_config_files()
+        with warnings.catch_warnings():
+            warnings.simplefilter('ignore', DeprecationWarning)
+            dist.parse_config_files()
         metadata = dist.metadata
 
         self.assertEqual(args['name'], metadata['Name'])
@@ -529,6 +537,26 @@
         self.assertEqual(args['scripts'], dist.scripts)
         self.assertEqual(args['py_modules'], dist.py_modules)
 
+    def test_generate_setup_py(self):
+        # undo subprocess.Popen monkey-patching before using assert_python_*
+        subprocess.Popen = self.old_popen
+        os.chdir(self.mkdtemp())
+        self.write_file('setup.cfg', textwrap.dedent("""\
+            [metadata]
+            name = SPAM
+            classifier = Programming Language :: Python
+            """))
+        generate_setup_py()
+        self.assertTrue(os.path.exists('setup.py'), 'setup.py not created')
+        rc, out, err = assert_python_ok('setup.py', '--name')
+        self.assertEqual(out, b'SPAM\n')
+        self.assertEqual(err, b'')
+
+        # a generated setup.py should complain if no setup.cfg is present
+        os.unlink('setup.cfg')
+        rc, out, err = assert_python_failure('setup.py', '--name')
+        self.assertIn(b'setup.cfg', err)
+
     def test_encode_multipart(self):
         fields = [('username', 'wok'), ('password', 'secret')]
         files = [('picture', 'wok.png', b'PNG89')]
@@ -580,7 +608,6 @@
         super(GlobTestCase, self).tearDown()
 
     def assertGlobMatch(self, glob, spec):
-        """"""
         tempdir = self.build_files_tree(spec)
         expected = self.clean_tree(spec)
         os.chdir(tempdir)
@@ -849,7 +876,9 @@
 
     def test_get_install_method_with_packaging_pkg(self):
         path = self._valid_setup_cfg_pkg()
-        self.assertEqual("distutils2", get_install_method(path))
+        with warnings.catch_warnings():
+            warnings.simplefilter('ignore', DeprecationWarning)
+            self.assertEqual("distutils2", get_install_method(path))
 
     def test_get_install_method_with_unknown_pkg(self):
         path = self._invalid_setup_cfg_pkg()
diff --git a/distutils2/util.py b/distutils2/util.py
--- a/distutils2/util.py
+++ b/distutils2/util.py
@@ -6,6 +6,7 @@
 import imp
 import sys
 import errno
+import codecs
 import shutil
 import string
 import hashlib
@@ -925,6 +926,24 @@
                     yield file
 
 
+# HOWTO change cfg_to_args
+#
+# This function has two major constraints: It is copied by inspect.getsource
+# in generate_setup_py; it is used in generated setup.py which may be run by
+# any Python version supported by distutils2 (2.4-3.3).
+#
+# * Keep objects like D1_D2_SETUP_ARGS static, i.e. in the function body
+#   instead of global.
+# * If you use a function from another module, update the imports in
+#   SETUP_TEMPLATE.  Use only modules, classes and functions compatible with
+#   all versions: codecs.open instead of open, RawConfigParser.readfp instead
+#   of read, standard exceptions instead of Packaging*Error, etc.
+# * If you use a function from this module, update the template and
+#   generate_setup_py.
+#
+# test_util tests this function and the generated setup.py, but does not test
+# that it's compatible with all Python versions.
+
 def cfg_to_args(path='setup.cfg'):
     """Compatibility helper to use setup.cfg in setup.py.
 
@@ -935,8 +954,6 @@
     *file* is the path to the setup.cfg file.  If it doesn't exist,
     PackagingFileError is raised.
     """
-    # We need to declare the following constants here so that it's easier to
-    # generate the setup.py afterwards, using inspect.getsource.
 
     # XXX ** == needs testing
     D1_D2_SETUP_ARGS = {"name": ("metadata",),
@@ -980,11 +997,11 @@
 
     # The real code starts here
     config = RawConfigParser()
-    if not os.path.exists(path):
-        raise PackagingFileError("file '%s' does not exist" %
-                                 os.path.abspath(path))
-    with open(path, encoding='utf-8') as f:
+    f = codecs.open(path, encoding='utf-8')
+    try:
         config.readfp(f)
+    finally:
+        f.close()
 
     kwargs = {}
     for arg in D1_D2_SETUP_ARGS:
@@ -1006,8 +1023,11 @@
                     filenames = split_multiline(filenames)
                     in_cfg_value = []
                     for filename in filenames:
-                        with open(filename) as fp:
+                        fp = codecs.open(filename, encoding='utf-8')
+                        try:
                             in_cfg_value.append(fp.read())
+                        finally:
+                            fp.close()
                     in_cfg_value = '\n\n'.join(in_cfg_value)
             else:
                 continue
@@ -1024,13 +1044,19 @@
     return kwargs
 
 
-_SETUP_TMPL = """\
+SETUP_TEMPLATE = """\
 # This script was automatically generated by distutils2
 import os
+import codecs
 from distutils.core import setup
-from ConfigParser import RawConfigParser
+try:
+    from ConfigParser import RawConfigParser
+except ImportError:
+    from configparser import RawConfigParser
 
-%(func)s
+%(split_multiline)s
+
+%(cfg_to_args)s
 
 setup(**cfg_to_args())
 """
@@ -1044,8 +1070,10 @@
     if os.path.exists("setup.py"):
         raise PackagingFileError("a setup.py file already exists")
 
+    source = SETUP_TEMPLATE % {'split_multiline': getsource(split_multiline),
+                               'cfg_to_args': getsource(cfg_to_args)}
     with open("setup.py", "w", encoding='utf-8') as fp:
-        fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)})
+        fp.write(source)
 
 
 # Taken from the pip project
diff --git a/setup.cfg b/setup.cfg
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,7 @@
 [metadata]
 name = Distutils2
 version = 1.0a3
-summary = Python Distribution Utilities
+summary = Python Packaging Library
 description-file = README.txt
 home-page = http://bitbucket.org/tarek/distutils2/wiki/Home
 author = The Fellowship of the Packaging

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


More information about the Python-checkins mailing list