[Python-checkins] gh-92584: test_cppext uses setuptools (#92639)

vstinner webhook-mailer at python.org
Thu May 12 18:20:18 EDT 2022


https://github.com/python/cpython/commit/4e283777229ade11012b590624bd2cf04c42436d
commit: 4e283777229ade11012b590624bd2cf04c42436d
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-05-13T00:20:13+02:00
summary:

gh-92584: test_cppext uses setuptools (#92639)

Rewrite test_cppext to run in a virtual environment and to build the
C++ extension with setuptools rather than distutils.

files:
A Lib/test/setup_testcppext.py
M Lib/test/test_cppext.py

diff --git a/Lib/test/setup_testcppext.py b/Lib/test/setup_testcppext.py
new file mode 100644
index 0000000000000..780cb7b24a78c
--- /dev/null
+++ b/Lib/test/setup_testcppext.py
@@ -0,0 +1,42 @@
+# gh-91321: Build a basic C++ test extension to check that the Python C API is
+# compatible with C++ and does not emit C++ compiler warnings.
+import sys
+from test import support
+
+from setuptools import setup, Extension
+
+
+MS_WINDOWS = (sys.platform == 'win32')
+
+
+SOURCE = support.findfile('_testcppext.cpp')
+if not MS_WINDOWS:
+    # C++ compiler flags for GCC and clang
+    CPPFLAGS = [
+        # Python currently targets C++11
+        '-std=c++11',
+        # gh-91321: The purpose of _testcppext extension is to check that building
+        # a C++ extension using the Python C API does not emit C++ compiler
+        # warnings
+        '-Werror',
+        # Warn on old-style cast (C cast) like: (PyObject*)op
+        '-Wold-style-cast',
+        # Warn when using NULL rather than _Py_NULL in static inline functions
+        '-Wzero-as-null-pointer-constant',
+    ]
+else:
+    # Don't pass any compiler flag to MSVC
+    CPPFLAGS = []
+
+
+def main():
+    cpp_ext = Extension(
+        '_testcppext',
+        sources=[SOURCE],
+        language='c++',
+        extra_compile_args=CPPFLAGS)
+    setup(name="_testcppext", ext_modules=[cpp_ext])
+
+
+if __name__ == "__main__":
+    main()
diff --git a/Lib/test/test_cppext.py b/Lib/test/test_cppext.py
index 337cb08f8c9d8..8acf0f1b7c0dc 100644
--- a/Lib/test/test_cppext.py
+++ b/Lib/test/test_cppext.py
@@ -1,91 +1,59 @@
 # gh-91321: Build a basic C++ test extension to check that the Python C API is
 # compatible with C++ and does not emit C++ compiler warnings.
-import contextlib
-import os
+import os.path
 import sys
 import unittest
-import warnings
+import subprocess
 from test import support
 from test.support import os_helper
 
-with warnings.catch_warnings():
-    warnings.simplefilter('ignore', DeprecationWarning)
-    from distutils.core import setup, Extension
-    import distutils.sysconfig
-
 
 MS_WINDOWS = (sys.platform == 'win32')
 
 
-SOURCE = support.findfile('_testcppext.cpp')
-if not MS_WINDOWS:
-    # C++ compiler flags for GCC and clang
-    CPPFLAGS = [
-        # Python currently targets C++11
-        '-std=c++11',
-        # gh-91321: The purpose of _testcppext extension is to check that building
-        # a C++ extension using the Python C API does not emit C++ compiler
-        # warnings
-        '-Werror',
-        # Warn on old-style cast (C cast) like: (PyObject*)op
-        '-Wold-style-cast',
-        # Warn when using NULL rather than _Py_NULL in static inline functions
-        '-Wzero-as-null-pointer-constant',
-    ]
-else:
-    # Don't pass any compiler flag to MSVC
-    CPPFLAGS = []
+SETUP_TESTCPPEXT = support.findfile('setup_testcppext.py')
 
 
 @support.requires_subprocess()
 class TestCPPExt(unittest.TestCase):
-    def build(self):
-        cpp_ext = Extension(
-            '_testcppext',
-            sources=[SOURCE],
-            language='c++',
-            extra_compile_args=CPPFLAGS)
-        capture_stdout = (not support.verbose)
-
-        try:
-            try:
-                if capture_stdout:
-                    stdout = support.captured_stdout()
-                else:
-                    print()
-                    stdout = contextlib.nullcontext()
-                with (stdout,
-                      support.swap_attr(sys, 'argv', ['setup.py', 'build_ext', '--verbose'])):
-                    setup(name="_testcppext", ext_modules=[cpp_ext])
-                    return
-            except:
-                if capture_stdout:
-                    # Show output on error
-                    print()
-                    print(stdout.getvalue())
-                raise
-        except SystemExit:
-            self.fail("Build failed")
-
     # With MSVC, the linker fails with: cannot open file 'python311.lib'
     # https://github.com/python/cpython/pull/32175#issuecomment-1111175897
     @unittest.skipIf(MS_WINDOWS, 'test fails on Windows')
     def test_build(self):
-        # save/restore os.environ
-        def restore_env(old_env):
-            os.environ.clear()
-            os.environ.update(old_env)
-        self.addCleanup(restore_env, dict(os.environ))
-
-        def restore_sysconfig_vars(old_config_vars):
-            distutils.sysconfig._config_vars.clear()
-            distutils.sysconfig._config_vars.update(old_config_vars)
-        self.addCleanup(restore_sysconfig_vars,
-                        dict(distutils.sysconfig._config_vars))
-
         # Build in a temporary directory
         with os_helper.temp_cwd():
-            self.build()
+            self._test_build()
+
+    def _test_build(self):
+        venv_dir = 'env'
+
+        # Create virtual environment to get setuptools
+        cmd = [sys.executable, '-X', 'dev', '-m', 'venv', venv_dir]
+        if support.verbose:
+            print()
+            print('Run:', ' '.join(cmd))
+        subprocess.run(cmd, check=True)
+
+        # Get the Python executable of the venv
+        python_exe = 'python'
+        if sys.executable.endswith('.exe'):
+            python_exe += '.exe'
+        if MS_WINDOWS:
+            python = os.path.join(venv_dir, 'Scripts', python_exe)
+        else:
+            python = os.path.join(venv_dir, 'bin', python_exe)
+
+        # Build the C++ extension
+        cmd = [python, '-X', 'dev', SETUP_TESTCPPEXT, 'build_ext', '--verbose']
+        if support.verbose:
+            print('Run:', ' '.join(cmd))
+        proc = subprocess.run(cmd,
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.STDOUT,
+                              text=True)
+        if proc.returncode:
+            print(proc.stdout, end='')
+            self.fail(f"Build failed with exit code {proc.returncode}")
 
 
 if __name__ == "__main__":



More information about the Python-checkins mailing list