|
32 | 32 | # error "_testcapi must test the public Python C API, not CPython internal C API"
|
33 | 33 | #endif
|
34 | 34 |
|
| 35 | +static struct PyModuleDef _testcapimodule; |
| 36 | + |
35 | 37 | static PyObject *TestError; /* set to exception object in init */
|
36 | 38 |
|
37 | 39 | /* Raise TestError with test_name + ": " + msg, and return NULL. */
|
@@ -5955,6 +5957,189 @@ static PyTypeObject MethodDescriptor2_Type = {
|
5955 | 5957 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | _Py_TPFLAGS_HAVE_VECTORCALL,
|
5956 | 5958 | };
|
5957 | 5959 |
|
| 5960 | +PyDoc_STRVAR(heapgctype__doc__, |
| 5961 | +"A heap type with GC, and with overridden dealloc.\n\n" |
| 5962 | +"The 'value' attribute is set to 10 in __init__."); |
| 5963 | + |
| 5964 | +typedef struct { |
| 5965 | + PyObject_HEAD |
| 5966 | + int value; |
| 5967 | +} HeapCTypeObject; |
| 5968 | + |
| 5969 | +static struct PyMemberDef heapctype_members[] = { |
| 5970 | + {"value", T_INT, offsetof(HeapCTypeObject, value)}, |
| 5971 | + {NULL} /* Sentinel */ |
| 5972 | +}; |
| 5973 | + |
| 5974 | +static int |
| 5975 | +heapctype_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 5976 | +{ |
| 5977 | + ((HeapCTypeObject *)self)->value = 10; |
| 5978 | + return 0; |
| 5979 | +} |
| 5980 | + |
| 5981 | +static void |
| 5982 | +heapgcctype_dealloc(HeapCTypeObject *self) |
| 5983 | +{ |
| 5984 | + PyTypeObject *tp = Py_TYPE(self); |
| 5985 | + PyObject_GC_UnTrack(self); |
| 5986 | + PyObject_GC_Del(self); |
| 5987 | + Py_DECREF(tp); |
| 5988 | +} |
| 5989 | + |
| 5990 | +static PyType_Slot HeapGcCType_slots[] = { |
| 5991 | + {Py_tp_init, heapctype_init}, |
| 5992 | + {Py_tp_members, heapctype_members}, |
| 5993 | + {Py_tp_dealloc, heapgcctype_dealloc}, |
| 5994 | + {Py_tp_doc, heapgctype__doc__}, |
| 5995 | + {0, 0}, |
| 5996 | +}; |
| 5997 | + |
| 5998 | +static PyType_Spec HeapGcCType_spec = { |
| 5999 | + "_testcapi.HeapGcCType", |
| 6000 | + sizeof(HeapCTypeObject), |
| 6001 | + 0, |
| 6002 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
| 6003 | + HeapGcCType_slots |
| 6004 | +}; |
| 6005 | + |
| 6006 | +PyDoc_STRVAR(heapctype__doc__, |
| 6007 | +"A heap type without GC, but with overridden dealloc.\n\n" |
| 6008 | +"The 'value' attribute is set to 10 in __init__."); |
| 6009 | + |
| 6010 | +static void |
| 6011 | +heapctype_dealloc(HeapCTypeObject *self) |
| 6012 | +{ |
| 6013 | + PyTypeObject *tp = Py_TYPE(self); |
| 6014 | + PyObject_Del(self); |
| 6015 | + Py_DECREF(tp); |
| 6016 | +} |
| 6017 | + |
| 6018 | +static PyType_Slot HeapCType_slots[] = { |
| 6019 | + {Py_tp_init, heapctype_init}, |
| 6020 | + {Py_tp_members, heapctype_members}, |
| 6021 | + {Py_tp_dealloc, heapctype_dealloc}, |
| 6022 | + {Py_tp_doc, heapctype__doc__}, |
| 6023 | + {0, 0}, |
| 6024 | +}; |
| 6025 | + |
| 6026 | +static PyType_Spec HeapCType_spec = { |
| 6027 | + "_testcapi.HeapCType", |
| 6028 | + sizeof(HeapCTypeObject), |
| 6029 | + 0, |
| 6030 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 6031 | + HeapCType_slots |
| 6032 | +}; |
| 6033 | + |
| 6034 | +PyDoc_STRVAR(heapctypesubclass__doc__, |
| 6035 | +"Subclass of HeapCType, without GC.\n\n" |
| 6036 | +"__init__ sets the 'value' attribute to 10 and 'value2' to 20."); |
| 6037 | + |
| 6038 | +typedef struct { |
| 6039 | + HeapCTypeObject base; |
| 6040 | + int value2; |
| 6041 | +} HeapCTypeSubclassObject; |
| 6042 | + |
| 6043 | +static int |
| 6044 | +heapctypesubclass_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 6045 | +{ |
| 6046 | + /* Call __init__ of the superclass */ |
| 6047 | + if (heapctype_init(self, args, kwargs) < 0) { |
| 6048 | + return -1; |
| 6049 | + } |
| 6050 | + /* Initialize additional element */ |
| 6051 | + ((HeapCTypeSubclassObject *)self)->value2 = 20; |
| 6052 | + return 0; |
| 6053 | +} |
| 6054 | + |
| 6055 | +static struct PyMemberDef heapctypesubclass_members[] = { |
| 6056 | + {"value2", T_INT, offsetof(HeapCTypeSubclassObject, value2)}, |
| 6057 | + {NULL} /* Sentinel */ |
| 6058 | +}; |
| 6059 | + |
| 6060 | +static PyType_Slot HeapCTypeSubclass_slots[] = { |
| 6061 | + {Py_tp_init, heapctypesubclass_init}, |
| 6062 | + {Py_tp_members, heapctypesubclass_members}, |
| 6063 | + {Py_tp_doc, heapctypesubclass__doc__}, |
| 6064 | + {0, 0}, |
| 6065 | +}; |
| 6066 | + |
| 6067 | +static PyType_Spec HeapCTypeSubclass_spec = { |
| 6068 | + "_testcapi.HeapCTypeSubclass", |
| 6069 | + sizeof(HeapCTypeSubclassObject), |
| 6070 | + 0, |
| 6071 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 6072 | + HeapCTypeSubclass_slots |
| 6073 | +}; |
| 6074 | + |
| 6075 | +PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__, |
| 6076 | +"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n" |
| 6077 | +"__class__ is set to plain HeapCTypeSubclass during finalization.\n" |
| 6078 | +"__init__ sets the 'value' attribute to 10 and 'value2' to 20."); |
| 6079 | + |
| 6080 | +static int |
| 6081 | +heapctypesubclasswithfinalizer_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 6082 | +{ |
| 6083 | + PyTypeObject *base = (PyTypeObject *)PyType_GetSlot(Py_TYPE(self), Py_tp_base); |
| 6084 | + initproc base_init = PyType_GetSlot(base, Py_tp_init); |
| 6085 | + base_init(self, args, kwargs); |
| 6086 | + return 0; |
| 6087 | +} |
| 6088 | + |
| 6089 | +static void |
| 6090 | +heapctypesubclasswithfinalizer_finalize(PyObject *self) |
| 6091 | +{ |
| 6092 | + PyObject *error_type, *error_value, *error_traceback, *m, *oldtype, *newtype; |
| 6093 | + |
| 6094 | + /* Save the current exception, if any. */ |
| 6095 | + PyErr_Fetch(&error_type, &error_value, &error_traceback); |
| 6096 | + |
| 6097 | + m = PyState_FindModule(&_testcapimodule); |
| 6098 | + if (m == NULL) { |
| 6099 | + goto cleanup_finalize; |
| 6100 | + } |
| 6101 | + oldtype = PyObject_GetAttrString(m, "HeapCTypeSubclassWithFinalizer"); |
| 6102 | + newtype = PyObject_GetAttrString(m, "HeapCTypeSubclass"); |
| 6103 | + if (oldtype == NULL || newtype == NULL) { |
| 6104 | + goto cleanup_finalize; |
| 6105 | + } |
| 6106 | + |
| 6107 | + if (PyObject_SetAttrString(self, "__class__", newtype) < 0) { |
| 6108 | + goto cleanup_finalize; |
| 6109 | + } |
| 6110 | + if (PyObject_SetAttrString( |
| 6111 | + oldtype, "refcnt_in_del", PyLong_FromSsize_t(Py_REFCNT(oldtype))) < 0) { |
| 6112 | + goto cleanup_finalize; |
| 6113 | + } |
| 6114 | + if (PyObject_SetAttrString( |
| 6115 | + newtype, "refcnt_in_del", PyLong_FromSsize_t(Py_REFCNT(newtype))) < 0) { |
| 6116 | + goto cleanup_finalize; |
| 6117 | + } |
| 6118 | + |
| 6119 | +cleanup_finalize: |
| 6120 | + Py_XDECREF(oldtype); |
| 6121 | + Py_XDECREF(newtype); |
| 6122 | + |
| 6123 | + /* Restore the saved exception. */ |
| 6124 | + PyErr_Restore(error_type, error_value, error_traceback); |
| 6125 | +} |
| 6126 | + |
| 6127 | +static PyType_Slot HeapCTypeSubclassWithFinalizer_slots[] = { |
| 6128 | + {Py_tp_init, heapctypesubclasswithfinalizer_init}, |
| 6129 | + {Py_tp_members, heapctypesubclass_members}, |
| 6130 | + {Py_tp_finalize, heapctypesubclasswithfinalizer_finalize}, |
| 6131 | + {Py_tp_doc, heapctypesubclasswithfinalizer__doc__}, |
| 6132 | + {0, 0}, |
| 6133 | +}; |
| 6134 | + |
| 6135 | +static PyType_Spec HeapCTypeSubclassWithFinalizer_spec = { |
| 6136 | + "_testcapi.HeapCTypeSubclassWithFinalizer", |
| 6137 | + sizeof(HeapCTypeSubclassObject), |
| 6138 | + 0, |
| 6139 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, |
| 6140 | + HeapCTypeSubclassWithFinalizer_slots |
| 6141 | +}; |
| 6142 | + |
5958 | 6143 |
|
5959 | 6144 | static struct PyModuleDef _testcapimodule = {
|
5960 | 6145 | PyModuleDef_HEAD_INIT,
|
@@ -6089,5 +6274,40 @@ PyInit__testcapi(void)
|
6089 | 6274 | TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
|
6090 | 6275 | Py_INCREF(TestError);
|
6091 | 6276 | PyModule_AddObject(m, "error", TestError);
|
| 6277 | + |
| 6278 | + PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec); |
| 6279 | + if (HeapGcCType == NULL) { |
| 6280 | + return NULL; |
| 6281 | + } |
| 6282 | + PyModule_AddObject(m, "HeapGcCType", HeapGcCType); |
| 6283 | + |
| 6284 | + PyObject *HeapCType = PyType_FromSpec(&HeapCType_spec); |
| 6285 | + if (HeapCType == NULL) { |
| 6286 | + return NULL; |
| 6287 | + } |
| 6288 | + PyObject *subclass_bases = PyTuple_Pack(1, HeapCType); |
| 6289 | + if (subclass_bases == NULL) { |
| 6290 | + return NULL; |
| 6291 | + } |
| 6292 | + PyObject *HeapCTypeSubclass = PyType_FromSpecWithBases(&HeapCTypeSubclass_spec, subclass_bases); |
| 6293 | + if (HeapCTypeSubclass == NULL) { |
| 6294 | + return NULL; |
| 6295 | + } |
| 6296 | + Py_DECREF(subclass_bases); |
| 6297 | + PyModule_AddObject(m, "HeapCTypeSubclass", HeapCTypeSubclass); |
| 6298 | + |
| 6299 | + PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass); |
| 6300 | + if (subclass_with_finalizer_bases == NULL) { |
| 6301 | + return NULL; |
| 6302 | + } |
| 6303 | + PyObject *HeapCTypeSubclassWithFinalizer = PyType_FromSpecWithBases( |
| 6304 | + &HeapCTypeSubclassWithFinalizer_spec, subclass_with_finalizer_bases); |
| 6305 | + if (HeapCTypeSubclassWithFinalizer == NULL) { |
| 6306 | + return NULL; |
| 6307 | + } |
| 6308 | + Py_DECREF(subclass_with_finalizer_bases); |
| 6309 | + PyModule_AddObject(m, "HeapCTypeSubclassWithFinalizer", HeapCTypeSubclassWithFinalizer); |
| 6310 | + |
| 6311 | + PyState_AddModule(m, &_testcapimodule); |
6092 | 6312 | return m;
|
6093 | 6313 | }
|
0 commit comments