mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Refactor helpers for compiling the xx module in distutils tests.
I need to copy the xxmodule.c file in other tests, so I moved the support code to distutils.tests.support and improved it: - don’t skip when run from the Lib/distutils/tests directory - use proper skip machinery instead of custom print/return/test suite fiddling. I also took out the fixup_build_ext function, which is needed for tests to pass on Unix shared builds and Windows debug builds. Finally, I cleaned up a few things: - don’t remove directories in tearDown when the parent class’ tearDown has already registered the directories for removal - simplify restoration of sys.path - remove a few unused names found by pyflakes.
This commit is contained in:
parent
04295009b8
commit
04612d6092
2 changed files with 85 additions and 59 deletions
|
@ -1,7 +1,10 @@
|
||||||
"""Support code for distutils test cases."""
|
"""Support code for distutils test cases."""
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
import sysconfig
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
@ -9,6 +12,7 @@ from distutils import log
|
||||||
from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
|
from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
|
||||||
from distutils.core import Distribution
|
from distutils.core import Distribution
|
||||||
|
|
||||||
|
|
||||||
def capture_warnings(func):
|
def capture_warnings(func):
|
||||||
def _capture_warnings(*args, **kw):
|
def _capture_warnings(*args, **kw):
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
@ -16,6 +20,7 @@ def capture_warnings(func):
|
||||||
return func(*args, **kw)
|
return func(*args, **kw)
|
||||||
return _capture_warnings
|
return _capture_warnings
|
||||||
|
|
||||||
|
|
||||||
class LoggingSilencer(object):
|
class LoggingSilencer(object):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -49,6 +54,7 @@ class LoggingSilencer(object):
|
||||||
def clear_logs(self):
|
def clear_logs(self):
|
||||||
self.logs = []
|
self.logs = []
|
||||||
|
|
||||||
|
|
||||||
class TempdirManager(object):
|
class TempdirManager(object):
|
||||||
"""Mix-in class that handles temporary directories for test cases.
|
"""Mix-in class that handles temporary directories for test cases.
|
||||||
|
|
||||||
|
@ -105,6 +111,7 @@ class TempdirManager(object):
|
||||||
|
|
||||||
return pkg_dir, dist
|
return pkg_dir, dist
|
||||||
|
|
||||||
|
|
||||||
class DummyCommand:
|
class DummyCommand:
|
||||||
"""Class to store options for retrieval via set_undefined_options()."""
|
"""Class to store options for retrieval via set_undefined_options()."""
|
||||||
|
|
||||||
|
@ -115,6 +122,7 @@ class DummyCommand:
|
||||||
def ensure_finalized(self):
|
def ensure_finalized(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EnvironGuard(object):
|
class EnvironGuard(object):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -131,3 +139,71 @@ class EnvironGuard(object):
|
||||||
del os.environ[key]
|
del os.environ[key]
|
||||||
|
|
||||||
super(EnvironGuard, self).tearDown()
|
super(EnvironGuard, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
|
def copy_xxmodule_c(directory):
|
||||||
|
"""Helper for tests that need the xxmodule.c source file.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
def test_compile(self):
|
||||||
|
copy_xxmodule_c(self.tmpdir)
|
||||||
|
self.assertIn('xxmodule.c', os.listdir(self.tmpdir))
|
||||||
|
|
||||||
|
If the source file can be found, it will be copied to *directory*. If not,
|
||||||
|
the test will be skipped. Errors during copy are not caught.
|
||||||
|
"""
|
||||||
|
filename = _get_xxmodule_path()
|
||||||
|
if filename is None:
|
||||||
|
raise unittest.SkipTest('cannot find xxmodule.c (test must run in '
|
||||||
|
'the python build dir)')
|
||||||
|
shutil.copy(filename, directory)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_xxmodule_path():
|
||||||
|
srcdir = sysconfig.get_config_var('srcdir')
|
||||||
|
candidates = [
|
||||||
|
# use installed copy if available
|
||||||
|
os.path.join(os.path.dirname(__file__), 'xxmodule.c'),
|
||||||
|
# otherwise try using copy from build directory
|
||||||
|
os.path.join(srcdir, 'Modules', 'xxmodule.c'),
|
||||||
|
# srcdir mysteriously can be $srcdir/Lib/distutils/tests when
|
||||||
|
# this file is run from its parent directory, so walk up the
|
||||||
|
# tree to find the real srcdir
|
||||||
|
os.path.join(srcdir, '..', '..', '..', 'Modules', 'xxmodule.c'),
|
||||||
|
]
|
||||||
|
for path in candidates:
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def fixup_build_ext(cmd):
|
||||||
|
"""Function needed to make build_ext tests pass.
|
||||||
|
|
||||||
|
When Python was build with --enable-shared on Unix, -L. is not good
|
||||||
|
enough to find the libpython<blah>.so. This is because regrtest runs
|
||||||
|
it under a tempdir, not in the top level where the .so lives. By the
|
||||||
|
time we've gotten here, Python's already been chdir'd to the tempdir.
|
||||||
|
|
||||||
|
When Python was built with in debug mode on Windows, build_ext commands
|
||||||
|
need their debug attribute set, and it is not done automatically for
|
||||||
|
some reason.
|
||||||
|
|
||||||
|
This function handles both of these things. Example use:
|
||||||
|
|
||||||
|
cmd = build_ext(dist)
|
||||||
|
support.fixup_build_ext(cmd)
|
||||||
|
cmd.ensure_finalized()
|
||||||
|
"""
|
||||||
|
if os.name == 'nt':
|
||||||
|
cmd.debug = sys.executable.endswith('_d.exe')
|
||||||
|
elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||||
|
# To further add to the shared builds fun on Unix, we can't just add
|
||||||
|
# library_dirs to the Extension() instance because that doesn't get
|
||||||
|
# plumbed through to the final compiler command.
|
||||||
|
runshared = sysconfig.get_config_var('RUNSHARED')
|
||||||
|
if runshared is None:
|
||||||
|
cmd.library_dirs = ['.']
|
||||||
|
else:
|
||||||
|
name, equals, value = runshared.partition('=')
|
||||||
|
cmd.library_dirs = value.split(os.pathsep)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import tempfile
|
|
||||||
import shutil
|
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
|
@ -19,76 +17,34 @@ from test import test_support
|
||||||
# Don't load the xx module more than once.
|
# Don't load the xx module more than once.
|
||||||
ALREADY_TESTED = False
|
ALREADY_TESTED = False
|
||||||
|
|
||||||
def _get_source_filename():
|
|
||||||
# use installed copy if available
|
|
||||||
tests_f = os.path.join(os.path.dirname(__file__), 'xxmodule.c')
|
|
||||||
if os.path.exists(tests_f):
|
|
||||||
return tests_f
|
|
||||||
# otherwise try using copy from build directory
|
|
||||||
srcdir = sysconfig.get_config_var('srcdir')
|
|
||||||
if srcdir is None:
|
|
||||||
return os.path.join(sysconfig.project_base, 'Modules', 'xxmodule.c')
|
|
||||||
return os.path.join(srcdir, 'Modules', 'xxmodule.c')
|
|
||||||
|
|
||||||
_XX_MODULE_PATH = _get_source_filename()
|
|
||||||
|
|
||||||
class BuildExtTestCase(support.TempdirManager,
|
class BuildExtTestCase(support.TempdirManager,
|
||||||
support.LoggingSilencer,
|
support.LoggingSilencer,
|
||||||
unittest.TestCase):
|
unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Create a simple test environment
|
|
||||||
# Note that we're making changes to sys.path
|
|
||||||
super(BuildExtTestCase, self).setUp()
|
super(BuildExtTestCase, self).setUp()
|
||||||
self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_")
|
self.tmp_dir = self.mkdtemp()
|
||||||
if os.path.exists(_XX_MODULE_PATH):
|
self.xx_created = False
|
||||||
self.sys_path = sys.path[:]
|
sys.path.append(self.tmp_dir)
|
||||||
sys.path.append(self.tmp_dir)
|
self.addCleanup(sys.path.remove, self.tmp_dir)
|
||||||
shutil.copy(_XX_MODULE_PATH, self.tmp_dir)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Get everything back to normal
|
if self.xx_created:
|
||||||
if os.path.exists(_XX_MODULE_PATH):
|
|
||||||
test_support.unload('xx')
|
test_support.unload('xx')
|
||||||
sys.path[:] = self.sys_path
|
|
||||||
# XXX on Windows the test leaves a directory
|
# XXX on Windows the test leaves a directory
|
||||||
# with xx module in TEMP
|
# with xx module in TEMP
|
||||||
shutil.rmtree(self.tmp_dir, os.name == 'nt' or
|
|
||||||
sys.platform == 'cygwin')
|
|
||||||
super(BuildExtTestCase, self).tearDown()
|
super(BuildExtTestCase, self).tearDown()
|
||||||
|
|
||||||
def _fixup_command(self, cmd):
|
|
||||||
# When Python was build with --enable-shared, -L. is not good enough
|
|
||||||
# to find the libpython<blah>.so. This is because regrtest runs it
|
|
||||||
# under a tempdir, not in the top level where the .so lives. By the
|
|
||||||
# time we've gotten here, Python's already been chdir'd to the
|
|
||||||
# tempdir.
|
|
||||||
#
|
|
||||||
# To further add to the fun, we can't just add library_dirs to the
|
|
||||||
# Extension() instance because that doesn't get plumbed through to the
|
|
||||||
# final compiler command.
|
|
||||||
if (sysconfig.get_config_var('Py_ENABLE_SHARED') and
|
|
||||||
not sys.platform.startswith('win')):
|
|
||||||
runshared = sysconfig.get_config_var('RUNSHARED')
|
|
||||||
if runshared is None:
|
|
||||||
cmd.library_dirs = ['.']
|
|
||||||
else:
|
|
||||||
name, equals, value = runshared.partition('=')
|
|
||||||
cmd.library_dirs = value.split(os.pathsep)
|
|
||||||
|
|
||||||
@unittest.skipIf(not os.path.exists(_XX_MODULE_PATH),
|
|
||||||
'xxmodule.c not found')
|
|
||||||
def test_build_ext(self):
|
def test_build_ext(self):
|
||||||
global ALREADY_TESTED
|
global ALREADY_TESTED
|
||||||
|
support.copy_xxmodule_c(self.tmp_dir)
|
||||||
|
self.xx_created = True
|
||||||
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
|
xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
|
||||||
xx_ext = Extension('xx', [xx_c])
|
xx_ext = Extension('xx', [xx_c])
|
||||||
dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
|
dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
|
||||||
dist.package_dir = self.tmp_dir
|
dist.package_dir = self.tmp_dir
|
||||||
cmd = build_ext(dist)
|
cmd = build_ext(dist)
|
||||||
self._fixup_command(cmd)
|
support.fixup_build_ext(cmd)
|
||||||
if os.name == "nt":
|
|
||||||
# On Windows, we must build a debug version iff running
|
|
||||||
# a debug build of Python
|
|
||||||
cmd.debug = sys.executable.endswith("_d.exe")
|
|
||||||
cmd.build_lib = self.tmp_dir
|
cmd.build_lib = self.tmp_dir
|
||||||
cmd.build_temp = self.tmp_dir
|
cmd.build_temp = self.tmp_dir
|
||||||
|
|
||||||
|
@ -149,7 +105,6 @@ class BuildExtTestCase(support.TempdirManager,
|
||||||
cmd = build_ext(dist)
|
cmd = build_ext(dist)
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
|
|
||||||
from distutils import sysconfig
|
|
||||||
py_include = sysconfig.get_python_inc()
|
py_include = sysconfig.get_python_inc()
|
||||||
self.assertTrue(py_include in cmd.include_dirs)
|
self.assertTrue(py_include in cmd.include_dirs)
|
||||||
|
|
||||||
|
@ -277,13 +232,10 @@ class BuildExtTestCase(support.TempdirManager,
|
||||||
dist = Distribution({'name': 'xx',
|
dist = Distribution({'name': 'xx',
|
||||||
'ext_modules': [ext]})
|
'ext_modules': [ext]})
|
||||||
cmd = build_ext(dist)
|
cmd = build_ext(dist)
|
||||||
self._fixup_command(cmd)
|
support.fixup_build_ext(cmd)
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
self.assertEqual(len(cmd.get_outputs()), 1)
|
self.assertEqual(len(cmd.get_outputs()), 1)
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
cmd.debug = sys.executable.endswith("_d.exe")
|
|
||||||
|
|
||||||
cmd.build_lib = os.path.join(self.tmp_dir, 'build')
|
cmd.build_lib = os.path.join(self.tmp_dir, 'build')
|
||||||
cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
|
cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
|
||||||
|
|
||||||
|
@ -509,10 +461,8 @@ class BuildExtTestCase(support.TempdirManager,
|
||||||
cmd.build_temp = self.tmp_dir
|
cmd.build_temp = self.tmp_dir
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_stdout = sys.stdout
|
|
||||||
cmd.ensure_finalized()
|
cmd.ensure_finalized()
|
||||||
cmd.run()
|
cmd.run()
|
||||||
|
|
||||||
except CompileError:
|
except CompileError:
|
||||||
self.fail("Wrong deployment target during compilation")
|
self.fail("Wrong deployment target during compilation")
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue