]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-129849: Add tests for `Py_tp_bases` (GH-143208) (#146226)
authorAN Long <aisk@users.noreply.github.com>
Sat, 21 Mar 2026 09:52:45 +0000 (17:52 +0800)
committerGitHub <noreply@github.com>
Sat, 21 Mar 2026 09:52:45 +0000 (15:22 +0530)
(cherry picked from commit 6f8867a6765d3e6effdc09a22691830aa887c3d0)

Lib/test/test_capi/test_misc.py
Modules/_testcapi/heaptype.c

index c3012155e000689af13399351710b3cc84854982..3c51252c820cd0b91e4619d0643e115e88793adc 100644 (file)
@@ -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):
index 4526583a8059d95facb1ece57b7e748594788866..919d4714cc264abb533df64da34ef44bb4538da9 100644 (file)
@@ -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) {