Skip to content

Commit 6f8867a

Browse files
authored
gh-129849: Add tests for Py_tp_bases (#143208)
1 parent 70397fd commit 6f8867a

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

Lib/test/test_capi/test_misc.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,18 @@ def genf(): yield
916916
gen = genf()
917917
self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code)
918918

919+
def test_tp_bases_slot(self):
920+
cls = _testcapi.HeapCTypeWithBasesSlot
921+
self.assertEqual(cls.__bases__, (int,))
922+
self.assertEqual(cls.__base__, int)
923+
924+
def test_tp_bases_slot_none(self):
925+
self.assertRaisesRegex(
926+
SystemError,
927+
"Py_tp_bases is not a tuple",
928+
_testcapi.create_heapctype_with_none_bases_slot
929+
)
930+
919931

920932
@requires_limited_api
921933
class TestHeapTypeRelative(unittest.TestCase):

Modules/_testcapi/heaptype.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,25 @@ pytype_getmodulebytoken(PyObject *self, PyObject *args)
543543
return PyType_GetModuleByToken((PyTypeObject *)type, token);
544544
}
545545

546+
static PyType_Slot HeapCTypeWithBasesSlotNone_slots[] = {
547+
{Py_tp_bases, NULL}, /* filled out with Py_None in runtime */
548+
{0, 0},
549+
};
550+
551+
static PyType_Spec HeapCTypeWithBasesSlotNone_spec = {
552+
.name = "_testcapi.HeapCTypeWithBasesSlotNone",
553+
.basicsize = sizeof(PyObject),
554+
.flags = Py_TPFLAGS_DEFAULT,
555+
.slots = HeapCTypeWithBasesSlotNone_slots
556+
};
557+
558+
static PyObject *
559+
create_heapctype_with_none_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored))
560+
{
561+
HeapCTypeWithBasesSlotNone_slots[0].pfunc = Py_None;
562+
return PyType_FromSpec(&HeapCTypeWithBasesSlotNone_spec);
563+
}
564+
546565

547566
static PyMethodDef TestMethods[] = {
548567
{"pytype_fromspec_meta", pytype_fromspec_meta, METH_O},
@@ -562,6 +581,8 @@ static PyMethodDef TestMethods[] = {
562581
{"pytype_getbasebytoken", pytype_getbasebytoken, METH_VARARGS},
563582
{"pytype_getmodulebydef", pytype_getmodulebydef, METH_O},
564583
{"pytype_getmodulebytoken", pytype_getmodulebytoken, METH_VARARGS},
584+
{"create_heapctype_with_none_bases_slot",
585+
create_heapctype_with_none_bases_slot, METH_NOARGS},
565586
{NULL},
566587
};
567588

@@ -892,6 +913,18 @@ static PyType_Spec HeapCTypeMetaclassNullNew_spec = {
892913
.slots = empty_type_slots
893914
};
894915

916+
static PyType_Slot HeapCTypeWithBasesSlot_slots[] = {
917+
{Py_tp_bases, NULL}, /* filled out in module init function */
918+
{0, 0},
919+
};
920+
921+
static PyType_Spec HeapCTypeWithBasesSlot_spec = {
922+
.name = "_testcapi.HeapCTypeWithBasesSlot",
923+
.basicsize = sizeof(PyLongObject),
924+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
925+
.slots = HeapCTypeWithBasesSlot_slots
926+
};
927+
895928

896929
typedef struct {
897930
PyObject_HEAD
@@ -1432,6 +1465,18 @@ _PyTestCapi_Init_Heaptype(PyObject *m) {
14321465
&PyType_Type, m, &HeapCTypeMetaclassNullNew_spec, (PyObject *) &PyType_Type);
14331466
ADD("HeapCTypeMetaclassNullNew", HeapCTypeMetaclassNullNew);
14341467

1468+
PyObject *bases = PyTuple_Pack(1, &PyLong_Type);
1469+
if (bases == NULL) {
1470+
return -1;
1471+
}
1472+
HeapCTypeWithBasesSlot_slots[0].pfunc = bases;
1473+
PyObject *HeapCTypeWithBasesSlot = PyType_FromSpec(&HeapCTypeWithBasesSlot_spec);
1474+
Py_DECREF(bases);
1475+
if (HeapCTypeWithBasesSlot == NULL) {
1476+
return -1;
1477+
}
1478+
ADD("HeapCTypeWithBasesSlot", HeapCTypeWithBasesSlot);
1479+
14351480
ADD("Py_TP_USE_SPEC", PyLong_FromVoidPtr(Py_TP_USE_SPEC));
14361481

14371482
PyObject *HeapCCollection = PyType_FromMetaclass(

0 commit comments

Comments
 (0)