[Python-checkins] cpython (2.7): Refactor helpers for compiling the xx module in distutils tests.

eric.araujo python-checkins at python.org
Fri Aug 26 16:37:34 CEST 2011


http://hg.python.org/cpython/rev/3168c2448d77
changeset:   72088:3168c2448d77
branch:      2.7
user:        Éric Araujo <merwok at netwok.org>
date:        Fri Aug 26 01:56:15 2011 +0200
summary:
  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.

files:
  Lib/distutils/tests/support.py        |  76 +++++++++++++++
  Lib/distutils/tests/test_build_ext.py |  68 +-----------
  2 files changed, 85 insertions(+), 59 deletions(-)


diff --git a/Lib/distutils/tests/support.py b/Lib/distutils/tests/support.py
--- a/Lib/distutils/tests/support.py
+++ b/Lib/distutils/tests/support.py
@@ -1,7 +1,10 @@
 """Support code for distutils test cases."""
 import os
+import sys
 import shutil
 import tempfile
+import unittest
+import sysconfig
 from copy import deepcopy
 import warnings
 
@@ -9,6 +12,7 @@
 from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
 from distutils.core import Distribution
 
+
 def capture_warnings(func):
     def _capture_warnings(*args, **kw):
         with warnings.catch_warnings():
@@ -16,6 +20,7 @@
             return func(*args, **kw)
     return _capture_warnings
 
+
 class LoggingSilencer(object):
 
     def setUp(self):
@@ -49,6 +54,7 @@
     def clear_logs(self):
         self.logs = []
 
+
 class TempdirManager(object):
     """Mix-in class that handles temporary directories for test cases.
 
@@ -105,6 +111,7 @@
 
         return pkg_dir, dist
 
+
 class DummyCommand:
     """Class to store options for retrieval via set_undefined_options()."""
 
@@ -115,6 +122,7 @@
     def ensure_finalized(self):
         pass
 
+
 class EnvironGuard(object):
 
     def setUp(self):
@@ -131,3 +139,71 @@
                 del os.environ[key]
 
         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)
diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
--- a/Lib/distutils/tests/test_build_ext.py
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -1,7 +1,5 @@
 import sys
 import os
-import tempfile
-import shutil
 from StringIO import StringIO
 import textwrap
 
@@ -19,76 +17,34 @@
 # Don't load the xx module more than once.
 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,
                        support.LoggingSilencer,
                        unittest.TestCase):
     def setUp(self):
-        # Create a simple test environment
-        # Note that we're making changes to sys.path
         super(BuildExtTestCase, self).setUp()
-        self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_")
-        if os.path.exists(_XX_MODULE_PATH):
-            self.sys_path = sys.path[:]
-            sys.path.append(self.tmp_dir)
-            shutil.copy(_XX_MODULE_PATH, self.tmp_dir)
+        self.tmp_dir = self.mkdtemp()
+        self.xx_created = False
+        sys.path.append(self.tmp_dir)
+        self.addCleanup(sys.path.remove, self.tmp_dir)
 
     def tearDown(self):
-        # Get everything back to normal
-        if os.path.exists(_XX_MODULE_PATH):
+        if self.xx_created:
             test_support.unload('xx')
-            sys.path[:] = self.sys_path
             # XXX on Windows the test leaves a directory
             # with xx module in TEMP
-        shutil.rmtree(self.tmp_dir, os.name == 'nt' or
-                                    sys.platform == 'cygwin')
         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):
         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_ext = Extension('xx', [xx_c])
         dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
         dist.package_dir = self.tmp_dir
         cmd = build_ext(dist)
-        self._fixup_command(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")
+        support.fixup_build_ext(cmd)
         cmd.build_lib = self.tmp_dir
         cmd.build_temp = self.tmp_dir
 
@@ -149,7 +105,6 @@
         cmd = build_ext(dist)
         cmd.finalize_options()
 
-        from distutils import sysconfig
         py_include = sysconfig.get_python_inc()
         self.assertTrue(py_include in cmd.include_dirs)
 
@@ -277,13 +232,10 @@
         dist = Distribution({'name': 'xx',
                              'ext_modules': [ext]})
         cmd = build_ext(dist)
-        self._fixup_command(cmd)
+        support.fixup_build_ext(cmd)
         cmd.ensure_finalized()
         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_temp = os.path.join(self.tmp_dir, 'tempt')
 
@@ -509,10 +461,8 @@
         cmd.build_temp = self.tmp_dir
 
         try:
-            old_stdout = sys.stdout
             cmd.ensure_finalized()
             cmd.run()
-
         except CompileError:
             self.fail("Wrong deployment target during compilation")
 

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


More information about the Python-checkins mailing list