Skip to content

Commit 9bed8d3

Browse files
committed
gh-140550: Enable limited C API tests on Free Threading in test_cext
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. * Remove ";" from PyABIInfo_VAR macro definition, since "PyABIInfo_VAR(abi_info);" added two ";;" which is illegal in C++03.
1 parent e66bec0 commit 9bed8d3

6 files changed

Lines changed: 40 additions & 33 deletions

File tree

Include/modsupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ PyAPI_FUNC(int) PyABIInfo_Check(PyABIInfo *info, const char *module_name);
140140
/////////////////////////////////////////////////////////
141141

142142
#define PyABIInfo_VAR(NAME) \
143-
static PyABIInfo NAME = _PyABIInfo_DEFAULT;
143+
static PyABIInfo NAME = _PyABIInfo_DEFAULT
144144

145145
#undef _PyABIInfo_DEFAULT_STABLE
146146
#undef _PyABIInfo_DEFAULT_FT

Lib/test/test_cext/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,9 @@ def run_cmd(operation, cmd):
110110

111111

112112
class TestPublicCAPI(BaseTests, unittest.TestCase):
113-
@support.requires_gil_enabled('incompatible with Free Threading')
114113
def test_build_limited(self):
115114
self.check_build('_test_limited_cext', limited=True)
116115

117-
@support.requires_gil_enabled('broken for now with Free Threading')
118116
def test_build_limited_c11(self):
119117
self.check_build('_test_limited_c11_cext', limited=True, std='c11')
120118

Lib/test/test_cext/extension.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static PySlot _testcext_slots[] = {
139139
PySlot_STATIC_DATA(Py_mod_doc, (void*)(char*)_testcext_doc),
140140
PySlot_FUNC(Py_mod_exec, (void*)_testcext_exec),
141141
PySlot_STATIC_DATA(Py_mod_methods, _testcext_methods),
142+
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
142143
PySlot_END,
143144
};
144145

Lib/test/test_cppext/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,9 @@ class TestPublicCAPI(BaseTests, unittest.TestCase):
102102
def test_build(self):
103103
self.check_build('_testcppext')
104104

105-
@support.requires_gil_enabled('incompatible with Free Threading')
106105
def test_build_limited_cpp03(self):
107106
self.check_build('_test_limited_cpp03ext', std='c++03', limited=True)
108107

109-
@support.requires_gil_enabled('incompatible with Free Threading')
110108
def test_build_limited(self):
111109
self.check_build('_testcppext_limited', limited=True)
112110

Lib/test/test_cppext/extension.cpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// gh-91321: Very basic C++ test extension to check that the Python C API is
1+
// gh-91321: Basic C++ test extension to check that the Python C API is
22
// compatible with C++ and does not emit C++ compiler warnings.
33
//
44
// The code is only built, not executed.
@@ -159,6 +159,8 @@ test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
159159
Py_RETURN_NONE;
160160
}
161161

162+
// VirtualPyObject is incompatible with opaque PyObject
163+
#ifndef Py_TARGET_ABI3T
162164
/* Test a `new`-allocated object with a virtual method.
163165
* (https://github.com/python/cpython/issues/94731) */
164166

@@ -237,6 +239,8 @@ test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
237239
}
238240
Py_RETURN_NONE;
239241
}
242+
#endif // Py_TARGET_ABI3T
243+
240244

241245
static PyObject *
242246
test_datetime(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
@@ -256,7 +260,9 @@ static PyMethodDef _testcppext_methods[] = {
256260
{"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc},
257261
{"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL},
258262
{"test_unicode", test_unicode, METH_NOARGS, _Py_NULL},
263+
#ifndef Py_TARGET_ABI3T
259264
{"test_virtual_object", test_virtual_object, METH_NOARGS, _Py_NULL},
265+
#endif
260266
{"test_datetime", test_datetime, METH_NOARGS, _Py_NULL},
261267
// Note: _testcppext_exec currently runs all test functions directly.
262268
// When adding a new one, add a call there.
@@ -282,9 +288,11 @@ _testcppext_exec(PyObject *module)
282288
if (!result) return -1;
283289
Py_DECREF(result);
284290

291+
#ifndef Py_TARGET_ABI3T
285292
result = PyObject_CallMethod(module, "test_virtual_object", "");
286293
if (!result) return -1;
287294
Py_DECREF(result);
295+
#endif
288296

289297
result = PyObject_CallMethod(module, "test_datetime", "");
290298
if (!result) return -1;
@@ -313,40 +321,40 @@ _testcppext_exec(PyObject *module)
313321
return 0;
314322
}
315323

316-
// Need to ignore "-Wpedantic" warnings; see VirtualPyObject_Slots above
317-
_Py_COMP_DIAG_PUSH
318-
#if defined(__GNUC__)
319-
#pragma GCC diagnostic ignored "-Wpedantic"
320-
#elif defined(__clang__)
321-
#pragma clang diagnostic ignored "-Wpedantic"
322-
#endif
323324

324-
static PyModuleDef_Slot _testcppext_slots[] = {
325-
{Py_mod_exec, reinterpret_cast<void*>(_testcppext_exec)},
326-
{0, _Py_NULL}
325+
PyDoc_STRVAR(_testcppext_doc, "C++ test extension.");
326+
PyABIInfo_VAR(abi_info);
327+
328+
static PySlot _testcppext_slots[] = {
329+
PySlot_PTR_STATIC(Py_mod_abi, &abi_info),
330+
PySlot_PTR_STATIC(Py_mod_name, (void*)STR(MODULE_NAME)),
331+
PySlot_PTR_STATIC(Py_mod_doc, (void*)(char*)_testcppext_doc),
332+
PySlot_PTR_STATIC(Py_mod_exec, (void*)_testcppext_exec),
333+
PySlot_PTR_STATIC(Py_mod_methods, _testcppext_methods),
334+
PySlot_PTR_STATIC(Py_mod_gil, Py_MOD_GIL_NOT_USED),
335+
PySlot_END,
327336
};
328337

329-
_Py_COMP_DIAG_POP
330338

331-
PyDoc_STRVAR(_testcppext_doc, "C++ test extension.");
339+
#define _FUNC_NAME(NAME) PyModExport_ ## NAME
340+
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)
332341

333-
static struct PyModuleDef _testcppext_module = {
334-
PyModuleDef_HEAD_INIT, // m_base
335-
STR(MODULE_NAME), // m_name
336-
_testcppext_doc, // m_doc
337-
0, // m_size
338-
_testcppext_methods, // m_methods
339-
_testcppext_slots, // m_slots
340-
_Py_NULL, // m_traverse
341-
_Py_NULL, // m_clear
342-
_Py_NULL, // m_free
343-
};
342+
PyMODEXPORT_FUNC
343+
FUNC_NAME(MODULE_NAME)(void)
344+
{
345+
return _testcppext_slots;
346+
}
344347

345-
#define _FUNC_NAME(NAME) PyInit_ ## NAME
346-
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)
348+
// Also define the soft-deprecated entrypoint to ensure it isn't called
349+
350+
#define _INITFUNC_NAME(NAME) PyInit_ ## NAME
351+
#define INITFUNC_NAME(NAME) _INITFUNC_NAME(NAME)
347352

348353
PyMODINIT_FUNC
349-
FUNC_NAME(MODULE_NAME)(void)
354+
INITFUNC_NAME(MODULE_NAME)(void)
350355
{
351-
return PyModuleDef_Init(&_testcppext_module);
356+
PyErr_SetString(
357+
PyExc_AssertionError,
358+
"PyInit_* function called while a PyModExport_* one is available");
359+
return NULL;
352360
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Enable limited C API tests on Free Threading in test_cext and test_cppext:
2+
test the :c:macro:`Py_TARGET_ABI3T` macro. Patch by Victor Stinner.

0 commit comments

Comments
 (0)