distutils2: 5949563b9f1c (original) (raw)
Mercurial > distutils2
changeset 1218:5949563b9f1c
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.
Éric Araujo merwok@netwok.org | |
---|---|
date | Fri, 21 Oct 2011 06:34:38 +0200 |
parents | e469b70fc25e |
children | eb845a9a00b7 70c220cd2f59 |
files | distutils2/tests/support.py distutils2/tests/test_util.py distutils2/util.py |
diffstat | 3 files changed, 70 insertions(+), 15 deletions(-)[+] [-] distutils2/tests/support.py 9 distutils2/tests/test_util.py 30 distutils2/util.py 46 |
line wrap: on
line diff
--- a/distutils2/tests/support.py +++ b/distutils2/tests/support.py @@ -422,6 +422,15 @@ def assert_python_ok(*args, **env_vars): 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]
--- a/distutils2/tests/test_util.py +++ b/distutils2/tests/test_util.py @@ -4,11 +4,10 @@ import sys 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 @@ from distutils2.util import ( 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,
+ +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 = """[](#l2.28) @@ -536,6 +539,26 @@ class UtilTestCase(support.EnvironRestor 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_*[](#l2.34)
subprocess.Popen = self.old_popen[](#l2.35)
os.chdir(self.mkdtemp())[](#l2.36)
self.write_file('setup.cfg', textwrap.dedent("""\[](#l2.37)
[metadata][](#l2.38)
name = SPAM[](#l2.39)
classifier = Programming Language :: Python[](#l2.40)
"""))[](#l2.41)
generate_setup_py()[](#l2.42)
self.assertTrue(os.path.exists('setup.py'), 'setup.py not created')[](#l2.43)
rc, out, err = assert_python_ok('setup.py', '--name')[](#l2.44)
self.assertEqual(out, 'SPAM\n')[](#l2.45)
self.assertEqual(err, '')[](#l2.46)
# a generated setup.py should complain if no setup.cfg is present[](#l2.48)
os.unlink('setup.cfg')[](#l2.49)
rc, out, err = assert_python_failure('setup.py', '--name')[](#l2.50)
self.assertIn('setup.cfg', err)[](#l2.51)
+ def test_encode_multipart(self): fields = [('username', 'wok'), ('password', 'secret')] files = [('picture', 'wok.png', 'PNG89')] @@ -587,7 +610,6 @@ class GlobTestCase(GlobTestCaseBase): super(GlobTestCase, self).tearDown() def assertGlobMatch(self, glob, spec):
""""""[](#l2.60) tempdir = self.build_files_tree(spec)[](#l2.61) expected = self.clean_tree(spec)[](#l2.62) os.chdir(tempdir)[](#l2.63)
--- a/distutils2/util.py +++ b/distutils2/util.py @@ -556,6 +556,7 @@ def write_file(filename, contents): 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 @@ def _iglob(path_glob): 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 @@ def cfg_to_args(path='setup.cfg'): 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 @@ def cfg_to_args(path='setup.cfg'): # The real code starts here config = RawConfigParser()
- if not os.path.exists(path):
raise PackagingFileError("file '%s' does not exist" %[](#l3.50)
f = codecs.open(path, encoding='utf-8') try: config.readfp(f)os.path.abspath(path))[](#l3.51)
@@ -1012,7 +1026,7 @@ def cfg_to_args(path='setup.cfg'): filenames = split_multiline(filenames) in_cfg_value = [] for filename in filenames:
fp = open(filename)[](#l3.59)
fp = codecs.open(filename, encoding='utf-8')[](#l3.60) try:[](#l3.61) in_cfg_value.append(fp.read())[](#l3.62) finally:[](#l3.63)
@@ -1033,13 +1047,19 @@ def cfg_to_args(path='setup.cfg'): return kwargs -_SETUP_TMPL = """[](#l3.68) +SETUP_TEMPLATE = """[](#l3.69)
This script was automatically generated by distutils2
import os +import codecs from distutils.core import setup -from ConfigParser import RawConfigParser +try:
-%(func)s +%(split_multiline)s + +%(cfg_to_args)s setup(**cfg_to_args()) """ @@ -1053,9 +1073,11 @@ def generate_setup_py(): if os.path.exists("setup.py"): raise PackagingFileError("a setup.py file already exists")
- source = SETUP_TEMPLATE % {'split_multiline': getsource(split_multiline),
fp = codecs.open("setup.py", "w", encoding='utf-8') try:'cfg_to_args': getsource(cfg_to_args)}[](#l3.92)
fp.write(_SETUP_TMPL % {'func': getsource(cfg_to_args)})[](#l3.95)
@@ -1465,7 +1487,9 @@ def encode_multipart(fields, files, boun l.extend(( '--' + boundary, # XXX should encode to match packaging but it causes bugs
('Content-Disposition: form-data; name="%s"' % key), '', value))[](#l3.104)
('Content-Disposition: form-data; name="%s"' % key),[](#l3.105)
'',[](#l3.106)
value))[](#l3.107)