From a902208602f63124118d33de9c775ad9a5b62015 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 6 Feb 2026 16:46:02 +0100 Subject: [PATCH] gh-144490: Test the internal C API in test_cppext Backport changes from the main branch. --- Lib/test/test_cppext/__init__.py | 59 +++++++++++++++++------------- Lib/test/test_cppext/extension.cpp | 17 +++++++++ Lib/test/test_cppext/setup.py | 4 ++ 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py index 2b7adac4bccd15..9013503995bdce 100644 --- a/Lib/test/test_cppext/__init__.py +++ b/Lib/test/test_cppext/__init__.py @@ -24,34 +24,12 @@ @support.requires_venv_with_pip() @support.requires_subprocess() @support.requires_resource('cpu') -class TestCPPExt(unittest.TestCase): +class BaseTests: + TEST_INTERNAL_C_API = False + def test_build(self): self.check_build('_testcppext') - def test_build_cpp03(self): - # In public docs, we say C API is compatible with C++11. However, - # in practice we do maintain C++03 compatibility in public headers. - # Please ask the C API WG before adding a new C++11-only feature. - self.check_build('_testcpp03ext', std='c++03') - - @support.requires_gil_enabled('incompatible with Free Threading') - def test_build_limited_cpp03(self): - self.check_build('_test_limited_cpp03ext', std='c++03', limited=True) - - @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11") - def test_build_cpp11(self): - self.check_build('_testcpp11ext', std='c++11') - - # Only test C++14 on MSVC. - # On s390x RHEL7, GCC 4.8.5 doesn't support C++14. - @unittest.skipIf(not support.MS_WINDOWS, "need Windows") - def test_build_cpp14(self): - self.check_build('_testcpp14ext', std='c++14') - - @support.requires_gil_enabled('incompatible with Free Threading') - def test_build_limited(self): - self.check_build('_testcppext_limited', limited=True) - def check_build(self, extension_name, std=None, limited=False): venv_dir = 'env' with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: @@ -71,6 +49,7 @@ def run_cmd(operation, cmd): if limited: env['CPYTHON_TEST_LIMITED'] = '1' env['CPYTHON_TEST_EXT_NAME'] = extension_name + env['TEST_INTERNAL_C_API'] = str(int(self.TEST_INTERNAL_C_API)) if support.verbose: print('Run:', ' '.join(map(shlex.quote, cmd))) subprocess.run(cmd, check=True, env=env) @@ -111,5 +90,35 @@ def run_cmd(operation, cmd): run_cmd('Import', cmd) +class TestPublicCAPI(BaseTests, unittest.TestCase): + @support.requires_gil_enabled('incompatible with Free Threading') + def test_build_limited_cpp03(self): + self.check_build('_test_limited_cpp03ext', std='c++03', limited=True) + + @support.requires_gil_enabled('incompatible with Free Threading') + def test_build_limited(self): + self.check_build('_testcppext_limited', limited=True) + + def test_build_cpp03(self): + # In public docs, we say C API is compatible with C++11. However, + # in practice we do maintain C++03 compatibility in public headers. + # Please ask the C API WG before adding a new C++11-only feature. + self.check_build('_testcpp03ext', std='c++03') + + @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11") + def test_build_cpp11(self): + self.check_build('_testcpp11ext', std='c++11') + + # Only test C++14 on MSVC. + # On s390x RHEL7, GCC 4.8.5 doesn't support C++14. + @unittest.skipIf(not support.MS_WINDOWS, "need Windows") + def test_build_cpp14(self): + self.check_build('_testcpp14ext', std='c++14') + + +class TestInteralCAPI(BaseTests, unittest.TestCase): + TEST_INTERNAL_C_API = True + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_cppext/extension.cpp b/Lib/test/test_cppext/extension.cpp index 5b3571b295bec3..038f67bbbe3f74 100644 --- a/Lib/test/test_cppext/extension.cpp +++ b/Lib/test/test_cppext/extension.cpp @@ -6,8 +6,25 @@ // Always enable assertions #undef NDEBUG +#ifdef TEST_INTERNAL_C_API +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" +#ifdef TEST_INTERNAL_C_API + // gh-135906: Check for compiler warnings in the internal C API +# include "internal/pycore_frame.h" + // mimalloc emits many compiler warnings when Python is built in debug + // mode (when MI_DEBUG is not zero) + // mimalloc emits compiler warnings when Python is built on Windows + // in free-threaded mode. +# if !defined(Py_DEBUG) && !(defined(MS_WINDOWS) && defined(Py_GIL_DISABLED)) +# include "internal/pycore_backoff.h" +# include "internal/pycore_cell.h" +# endif +#endif + #ifndef MODULE_NAME # error "MODULE_NAME macro must be defined" #endif diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py index ea1ed64bf7ab0a..98442b106b6113 100644 --- a/Lib/test/test_cppext/setup.py +++ b/Lib/test/test_cppext/setup.py @@ -47,6 +47,7 @@ def main(): std = os.environ.get("CPYTHON_TEST_CPP_STD", "") module_name = os.environ["CPYTHON_TEST_EXT_NAME"] limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", "")) + internal = bool(int(os.environ.get("TEST_INTERNAL_C_API", "0"))) cppflags = list(CPPFLAGS) cppflags.append(f'-DMODULE_NAME={module_name}') @@ -82,6 +83,9 @@ def main(): version = sys.hexversion cppflags.append(f'-DPy_LIMITED_API={version:#x}') + if internal: + cppflags.append('-DTEST_INTERNAL_C_API=1') + # On Windows, add PCbuild\amd64\ to include and library directories include_dirs = [] library_dirs = []