From: AN Long Date: Sat, 21 Mar 2026 09:52:45 +0000 (+0800) Subject: [3.13] gh-129849: Add tests for `Py_tp_bases` (GH-143208) (#146226) X-Git-Tag: v3.13.13~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d513f9ef8f6843eddd95594f96a56c871cf85327;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-129849: Add tests for `Py_tp_bases` (GH-143208) (#146226) (cherry picked from commit 6f8867a6765d3e6effdc09a22691830aa887c3d0) --- diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index c3012155e000..3c51252c820c 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -1152,6 +1152,18 @@ class CAPITest(unittest.TestCase): gen = genf() self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code) + def test_tp_bases_slot(self): + cls = _testcapi.HeapCTypeWithBasesSlot + self.assertEqual(cls.__bases__, (int,)) + self.assertEqual(cls.__base__, int) + + def test_tp_bases_slot_none(self): + self.assertRaisesRegex( + SystemError, + "Py_tp_bases is not a tuple", + _testcapi.create_heapctype_with_none_bases_slot + ) + @requires_limited_api class TestHeapTypeRelative(unittest.TestCase): diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index 4526583a8059..919d4714cc26 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -410,6 +410,26 @@ pyobject_getitemdata(PyObject *self, PyObject *o) } +static PyType_Slot HeapCTypeWithBasesSlotNone_slots[] = { + {Py_tp_bases, NULL}, /* filled out with Py_None in runtime */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlotNone_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlotNone", + .basicsize = sizeof(PyObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = HeapCTypeWithBasesSlotNone_slots +}; + +static PyObject * +create_heapctype_with_none_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + HeapCTypeWithBasesSlotNone_slots[0].pfunc = Py_None; + return PyType_FromSpec(&HeapCTypeWithBasesSlotNone_spec); +} + + static PyMethodDef TestMethods[] = { {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O}, {"test_type_from_ephemeral_spec", test_type_from_ephemeral_spec, METH_NOARGS}, @@ -423,6 +443,8 @@ static PyMethodDef TestMethods[] = { {"make_immutable_type_with_base", make_immutable_type_with_base, METH_O}, {"make_type_with_base", make_type_with_base, METH_O}, {"pyobject_getitemdata", pyobject_getitemdata, METH_O}, + {"create_heapctype_with_none_bases_slot", + create_heapctype_with_none_bases_slot, METH_NOARGS}, {NULL}, }; @@ -751,6 +773,18 @@ static PyType_Spec HeapCTypeMetaclassNullNew_spec = { .slots = empty_type_slots }; +static PyType_Slot HeapCTypeWithBasesSlot_slots[] = { + {Py_tp_bases, NULL}, /* filled out in module init function */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlot_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlot", + .basicsize = sizeof(PyLongObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = HeapCTypeWithBasesSlot_slots +}; + typedef struct { PyObject_HEAD @@ -1201,6 +1235,18 @@ _PyTestCapi_Init_Heaptype(PyObject *m) { &PyType_Type, m, &HeapCTypeMetaclassNullNew_spec, (PyObject *) &PyType_Type); ADD("HeapCTypeMetaclassNullNew", HeapCTypeMetaclassNullNew); + PyObject *bases = PyTuple_Pack(1, &PyLong_Type); + if (bases == NULL) { + return -1; + } + HeapCTypeWithBasesSlot_slots[0].pfunc = bases; + PyObject *HeapCTypeWithBasesSlot = PyType_FromSpec(&HeapCTypeWithBasesSlot_spec); + Py_DECREF(bases); + if (HeapCTypeWithBasesSlot == NULL) { + return -1; + } + ADD("HeapCTypeWithBasesSlot", HeapCTypeWithBasesSlot); + PyObject *HeapCCollection = PyType_FromMetaclass( NULL, m, &HeapCCollection_spec, NULL); if (HeapCCollection == NULL) {