From 9b5df8b940deb27f18f0c4ec71e2a471be293077 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 27 Dec 2025 16:57:51 +0900 Subject: [PATCH 1/2] Add test for Py_tp_bases --- Lib/test/test_capi/test_misc.py | 12 ++++++++++ Modules/_testcapi/heaptype.c | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 3997acbdf84695..363768b793ae03 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -916,6 +916,18 @@ def genf(): yield 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_invalid(self): + self.assertRaisesRegex( + SystemError, + "Py_tp_bases is not a tuple", + _testcapi.create_heapctype_with_invalid_bases_slot + ) + @requires_limited_api class TestHeapTypeRelative(unittest.TestCase): diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index 4fdcc850a339b4..3663a7a44cc0c4 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -543,6 +543,24 @@ pytype_getmodulebytoken(PyObject *self, PyObject *args) return PyType_GetModuleByToken((PyTypeObject *)type, token); } +static PyType_Slot HeapCTypeWithBasesSlotInvalid_slots[] = { + {Py_tp_bases, Py_None}, /* Not a tuple - should raise SystemError */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlotInvalid_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlotInvalid", + .basicsize = sizeof(PyObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = HeapCTypeWithBasesSlotInvalid_slots +}; + +static PyObject * +create_heapctype_with_invalid_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyType_FromSpec(&HeapCTypeWithBasesSlotInvalid_spec); +} + static PyMethodDef TestMethods[] = { {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O}, @@ -562,6 +580,8 @@ static PyMethodDef TestMethods[] = { {"pytype_getbasebytoken", pytype_getbasebytoken, METH_VARARGS}, {"pytype_getmodulebydef", pytype_getmodulebydef, METH_O}, {"pytype_getmodulebytoken", pytype_getmodulebytoken, METH_VARARGS}, + {"create_heapctype_with_invalid_bases_slot", + create_heapctype_with_invalid_bases_slot, METH_NOARGS}, {NULL}, }; @@ -892,6 +912,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 @@ -1432,6 +1464,15 @@ _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); + ADD("HeapCTypeWithBasesSlot", HeapCTypeWithBasesSlot); + ADD("Py_TP_USE_SPEC", PyLong_FromVoidPtr(Py_TP_USE_SPEC)); PyObject *HeapCCollection = PyType_FromMetaclass( From e592491984f189f08b0cb97569c08013e41cd3bb Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 27 Dec 2025 17:34:20 +0900 Subject: [PATCH 2/2] Fix test on Windows --- Modules/_testcapi/heaptype.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index 3663a7a44cc0c4..0ffed2e32a52ec 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -544,7 +544,7 @@ pytype_getmodulebytoken(PyObject *self, PyObject *args) } static PyType_Slot HeapCTypeWithBasesSlotInvalid_slots[] = { - {Py_tp_bases, Py_None}, /* Not a tuple - should raise SystemError */ + {Py_tp_bases, NULL}, /* filled out with Py_None in runtime */ {0, 0}, }; @@ -558,6 +558,7 @@ static PyType_Spec HeapCTypeWithBasesSlotInvalid_spec = { static PyObject * create_heapctype_with_invalid_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored)) { + HeapCTypeWithBasesSlotInvalid_slots[0].pfunc = Py_None; return PyType_FromSpec(&HeapCTypeWithBasesSlotInvalid_spec); }