(original) (raw)
changeset: 1218:5949563b9f1c user: Éric Araujo merwok@netwok.org date: Fri Oct 21 06:34:38 2011 +0200 files: distutils2/tests/support.py distutils2/tests/test_util.py distutils2/util.py description: Fix missing imports in generated setup scripts (#13205). I’ve made more edits than the bug report suggested to make sure the generated setup script is compatible with many Python versions; a comment in the source explains that in detail. Thanks to David Barnett for the report and original patch. diff -r e469b70fc25e -r 5949563b9f1c distutils2/tests/support.py --- a/distutils2/tests/support.py Wed Oct 19 05:58:37 2011 +0200 +++ b/distutils2/tests/support.py Fri Oct 21 06:34:38 2011 +0200 @@ -422,6 +422,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 -r e469b70fc25e -r 5949563b9f1c distutils2/tests/test_util.py --- a/distutils2/tests/test_util.py Wed Oct 19 05:58:37 2011 +0200 +++ b/distutils2/tests/test_util.py Fri Oct 21 06:34:38 2011 +0200 @@ -4,11 +4,10 @@ import time import logging import tempfile +import textwrap import subprocess from StringIO 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 +18,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 = """\ @@ -536,6 +539,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, 'SPAM\n') + self.assertEqual(err, '') + + # 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('setup.cfg', err) + def test_encode_multipart(self): fields = [('username', 'wok'), ('password', 'secret')] files = [('picture', 'wok.png', 'PNG89')] @@ -587,7 +610,6 @@ super(GlobTestCase, self).tearDown() def assertGlobMatch(self, glob, spec): - """""" tempdir = self.build_files_tree(spec) expected = self.clean_tree(spec) os.chdir(tempdir) diff -r e469b70fc25e -r 5949563b9f1c distutils2/util.py --- a/distutils2/util.py Wed Oct 19 05:58:37 2011 +0200 +++ b/distutils2/util.py Fri Oct 21 06:34:38 2011 +0200 @@ -556,6 +556,7 @@ finally: f.close() + def _is_package(path): return os.path.isdir(path) and os.path.isfile( os.path.join(path, '__init__.py')) @@ -928,6 +929,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. @@ -938,8 +957,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",), @@ -983,9 +1000,6 @@ # The real code starts here config = RawConfigParser() - if not os.path.exists(path): - raise PackagingFileError("file '%s' does not exist" % - os.path.abspath(path)) f = codecs.open(path, encoding='utf-8') try: config.readfp(f) @@ -1012,7 +1026,7 @@ filenames = split_multiline(filenames) in_cfg_value = [] for filename in filenames: - fp = open(filename) + fp = codecs.open(filename, encoding='utf-8') try: in_cfg_value.append(fp.read()) finally: @@ -1033,13 +1047,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()) """ @@ -1053,9 +1073,11 @@ 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)} fp = codecs.open("setup.py", "w", encoding='utf-8') try: - fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)}) + fp.write(source) finally: fp.close() @@ -1465,7 +1487,9 @@ l.extend(( '--' + boundary, # XXX should encode to match packaging but it causes bugs - ('Content-Disposition: form-data; name="%s"' % key), '', value)) + ('Content-Disposition: form-data; name="%s"' % key), + '', + value)) for key, filename, value in files: l.extend(( /merwok@netwok.org