https://github.com/python/cpython/commit/fb123c860aad1e4312a9c488bfc8c28d52b0aabb
commit: fb123c860aad1e4312a9c488bfc8c28d52b0aabb
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-15T15:17:43Z
summary:
gh-140550: Enable limited C API tests on Free Threading in test_cext (#157493)
Enable limited C API tests on Free Threading in test_cext and
test_cppext: test Py_TARGET_ABI3T macro.
* Convert test_cppext to PySlot API using PySlot_PTR_STATIC().
* Define Py_MOD_GIL_NOT_USED in test_cext and test_cppext.
* Disable C++ test_virtual_object() if Py_TARGET_ABI3T is defined.
files:
A Misc/NEWS.d/next/Tests/2026-09-14-14-50-42.gh-issue-140550.7jirEN.rst
M Lib/test/test_cext/__init__.py
M Lib/test/test_cext/extension.c
M Lib/test/test_cppext/__init__.py
M Lib/test/test_cppext/extension.cpp
diff --git a/Lib/test/test_cext/__init__.py b/Lib/test/test_cext/__init__.py
index 4cc5f843dd388da..dfc7d230426cf8c 100644
--- a/Lib/test/test_cext/__init__.py
+++ b/Lib/test/test_cext/__init__.py
@@ -110,11 +110,9 @@ def run_cmd(operation, cmd):
class TestPublicCAPI(BaseTests, unittest.TestCase):
- @support.requires_gil_enabled('incompatible with Free Threading')
def test_build_limited(self):
self.check_build('_test_limited_cext', limited=True)
- @support.requires_gil_enabled('broken for now with Free Threading')
def test_build_limited_c11(self):
self.check_build('_test_limited_c11_cext', limited=True, std='c11')
diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c
index 543a8096f16f8aa..b58c889ba8bcb3b 100644
--- a/Lib/test/test_cext/extension.c
+++ b/Lib/test/test_cext/extension.c
@@ -139,6 +139,7 @@ static PySlot _testcext_slots[] = {
PySlot_STATIC_DATA(Py_mod_doc, (void*)(char*)_testcext_doc),
PySlot_FUNC(Py_mod_exec, (void*)_testcext_exec),
PySlot_STATIC_DATA(Py_mod_methods, _testcext_methods),
+ PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
PySlot_END,
};
diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py
index 967feee6693c037..db7f41d9ef7a11f 100644
--- a/Lib/test/test_cppext/__init__.py
+++ b/Lib/test/test_cppext/__init__.py
@@ -102,11 +102,9 @@ class TestPublicCAPI(BaseTests, unittest.TestCase):
def test_build(self):
self.check_build('_testcppext')
- @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)
diff --git a/Lib/test/test_cppext/extension.cpp
b/Lib/test/test_cppext/extension.cpp
index 62ce81e2b510c7a..7496581c6756dac 100644
--- a/Lib/test/test_cppext/extension.cpp
+++ b/Lib/test/test_cppext/extension.cpp
@@ -1,4 +1,4 @@
-// gh-91321: Very basic C++ test extension to check that the Python C API is
+// gh-91321: Basic C++ test extension to check that the Python C API is
// compatible with C++ and does not emit C++ compiler warnings.
//
// The code is only built, not executed.
@@ -159,6 +159,8 @@ test_unicode(PyObject *Py_UNUSED(module), PyObject
*Py_UNUSED(args))
Py_RETURN_NONE;
}
+// VirtualPyObject is incompatible with opaque PyObject
+#ifndef Py_TARGET_ABI3T
/* Test a `new`-allocated object with a virtual method.
* (https://github.com/python/cpython/issues/94731) */
@@ -237,6 +239,8 @@ test_virtual_object(PyObject *Py_UNUSED(module), PyObject
*Py_UNUSED(args))
}
Py_RETURN_NONE;
}
+#endif // Py_TARGET_ABI3T
+
static PyObject *
test_datetime(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
@@ -256,7 +260,9 @@ static PyMethodDef _testcppext_methods[] = {
{"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc},
{"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL},
{"test_unicode", test_unicode, METH_NOARGS, _Py_NULL},
+#ifndef Py_TARGET_ABI3T
{"test_virtual_object", test_virtual_object, METH_NOARGS, _Py_NULL},
+#endif
{"test_datetime", test_datetime, METH_NOARGS, _Py_NULL},
// Note: _testcppext_exec currently runs all test functions directly.
// When adding a new one, add a call there.
@@ -282,9 +288,11 @@ _testcppext_exec(PyObject *module)
if (!result) return -1;
Py_DECREF(result);
+#ifndef Py_TARGET_ABI3T
result = PyObject_CallMethod(module, "test_virtual_object", "");
if (!result) return -1;
Py_DECREF(result);
+#endif
result = PyObject_CallMethod(module, "test_datetime", "");
if (!result) return -1;
@@ -313,6 +321,10 @@ _testcppext_exec(PyObject *module)
return 0;
}
+
+PyDoc_STRVAR(_testcppext_doc, "C++ test extension.");
+PyABIInfo_VAR(abi_info);
+
// Need to ignore "-Wpedantic" warnings; see VirtualPyObject_Slots above
_Py_COMP_DIAG_PUSH
#if defined(__GNUC__)
@@ -321,32 +333,38 @@ _Py_COMP_DIAG_PUSH
#pragma clang diagnostic ignored "-Wpedantic"
#endif
-static PyModuleDef_Slot _testcppext_slots[] = {
- {Py_mod_exec, reinterpret_cast<void*>(_testcppext_exec)},
- {0, _Py_NULL}
+static PySlot _testcppext_slots[] = {
+ PySlot_PTR_STATIC(Py_mod_abi, &abi_info),
+ PySlot_PTR_STATIC(Py_mod_name, (void*)STR(MODULE_NAME)),
+ PySlot_PTR_STATIC(Py_mod_doc, (void*)(char*)_testcppext_doc),
+ PySlot_PTR_STATIC(Py_mod_exec, (void*)_testcppext_exec),
+ PySlot_PTR_STATIC(Py_mod_methods, _testcppext_methods),
+ PySlot_PTR_STATIC(Py_mod_gil, Py_MOD_GIL_NOT_USED),
+ PySlot_END,
};
_Py_COMP_DIAG_POP
-PyDoc_STRVAR(_testcppext_doc, "C++ test extension.");
-
-static struct PyModuleDef _testcppext_module = {
- PyModuleDef_HEAD_INIT, // m_base
- STR(MODULE_NAME), // m_name
- _testcppext_doc, // m_doc
- 0, // m_size
- _testcppext_methods, // m_methods
- _testcppext_slots, // m_slots
- _Py_NULL, // m_traverse
- _Py_NULL, // m_clear
- _Py_NULL, // m_free
-};
-#define _FUNC_NAME(NAME) PyInit_ ## NAME
+#define _FUNC_NAME(NAME) PyModExport_ ## NAME
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)
-PyMODINIT_FUNC
+PyMODEXPORT_FUNC
FUNC_NAME(MODULE_NAME)(void)
{
- return PyModuleDef_Init(&_testcppext_module);
+ return _testcppext_slots;
+}
+
+// Also define the soft-deprecated entrypoint to ensure it isn't called
+
+#define _INITFUNC_NAME(NAME) PyInit_ ## NAME
+#define INITFUNC_NAME(NAME) _INITFUNC_NAME(NAME)
+
+PyMODINIT_FUNC
+INITFUNC_NAME(MODULE_NAME)(void)
+{
+ PyErr_SetString(
+ PyExc_AssertionError,
+ "PyInit_* function called while a PyModExport_* one is available");
+ return NULL;
}
diff --git
a/Misc/NEWS.d/next/Tests/2026-09-14-14-50-42.gh-issue-140550.7jirEN.rst
b/Misc/NEWS.d/next/Tests/2026-09-14-14-50-42.gh-issue-140550.7jirEN.rst
new file mode 100644
index 000000000000000..6de18208c1979c9
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2026-09-14-14-50-42.gh-issue-140550.7jirEN.rst
@@ -0,0 +1,2 @@
+Enable limited C API tests on Free Threading in test_cext and test_cppext:
+test the :c:macro:`Py_TARGET_ABI3T` macro. Patch by Victor Stinner.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]