|
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. */
|
@@ -6169,6 +6171,189 @@ static PyTypeObject MethodDescriptor2_Type = {
|
6169 | 6171 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | _Py_TPFLAGS_HAVE_VECTORCALL,
|
6170 | 6172 | };
|
6171 | 6173 |
|
| 6174 | +PyDoc_STRVAR(heapgctype__doc__, |
| 6175 | +"A heap type with GC, and with overridden dealloc.\n\n" |
| 6176 | +"The 'value' attribute is set to 10 in __init__."); |
| 6177 | + |
| 6178 | +typedef struct { |
| 6179 | + PyObject_HEAD |
| 6180 | + int value; |
| 6181 | +} HeapCTypeObject; |
| 6182 | + |
| 6183 | +static struct PyMemberDef heapctype_members[] = { |
| 6184 | + {"value", T_INT, offsetof(HeapCTypeObject, value)}, |
| 6185 | + {NULL} /* Sentinel */ |
| 6186 | +}; |
| 6187 | + |
| 6188 | +static int |
| 6189 | +heapctype_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 6190 | +{ |
| 6191 | + ((HeapCTypeObject *)self)->value = 10; |
| 6192 | + return 0; |
| 6193 | +} |
| 6194 | + |
| 6195 | +static void |
| 6196 | +heapgcctype_dealloc(HeapCTypeObject *self) |
| 6197 | +{ |
| 6198 | + PyTypeObject *tp = Py_TYPE(self); |
| 6199 | + PyObject_GC_UnTrack(self); |
| 6200 | + PyObject_GC_Del(self); |
| 6201 | + Py_DECREF(tp); |
| 6202 | +} |
| 6203 | + |
| 6204 | +static PyType_Slot HeapGcCType_slots[] = { |
| 6205 | + {Py_tp_init, heapctype_init}, |
| 6206 | + {Py_tp_members, heapctype_members}, |
| 6207 | + {Py_tp_dealloc, heapgcctype_dealloc}, |
| 6208 | + {Py_tp_doc, heapgctype__doc__}, |
| 6209 | + {0, 0}, |
| 6210 | +}; |
| 6211 | + |
| 6212 | +static PyType_Spec HeapGcCType_spec = { |
| 6213 | + "_testcapi.HeapGcCType", |
| 6214 | + sizeof(HeapCTypeObject), |
| 6215 | + 0, |
| 6216 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
| 6217 | + HeapGcCType_slots |
| 6218 | +}; |
| 6219 | + |
| 6220 | +PyDoc_STRVAR(heapctype__doc__, |
| 6221 | +"A heap type without GC, but with overridden dealloc.\n\n" |
| 6222 | +"The 'value' attribute is set to 10 in __init__."); |
| 6223 | + |
| 6224 | +static void |
| 6225 | +heapctype_dealloc(HeapCTypeObject *self) |
| 6226 | +{ |
| 6227 | + PyTypeObject *tp = Py_TYPE(self); |
| 6228 | + PyObject_Del(self); |
| 6229 | + Py_DECREF(tp); |
| 6230 | +} |
| 6231 | + |
| 6232 | +static PyType_Slot HeapCType_slots[] = { |
| 6233 | + {Py_tp_init, heapctype_init}, |
| 6234 | + {Py_tp_members, heapctype_members}, |
| 6235 | + {Py_tp_dealloc, heapctype_dealloc}, |
| 6236 | + {Py_tp_doc, heapctype__doc__}, |
| 6237 | + {0, 0}, |
| 6238 | +}; |
| 6239 | + |
| 6240 | +static PyType_Spec HeapCType_spec = { |
| 6241 | + "_testcapi.HeapCType", |
| 6242 | + sizeof(HeapCTypeObject), |
| 6243 | + 0, |
| 6244 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 6245 | + HeapCType_slots |
| 6246 | +}; |
| 6247 | + |
| 6248 | +PyDoc_STRVAR(heapctypesubclass__doc__, |
| 6249 | +"Subclass of HeapCType, without GC.\n\n" |
| 6250 | +"__init__ sets the 'value' attribute to 10 and 'value2' to 20."); |
| 6251 | + |
| 6252 | +typedef struct { |
| 6253 | + HeapCTypeObject base; |
| 6254 | + int value2; |
| 6255 | +} HeapCTypeSubclassObject; |
| 6256 | + |
| 6257 | +static int |
| 6258 | +heapctypesubclass_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 6259 | +{ |
| 6260 | + /* Call __init__ of the superclass */ |
| 6261 | + if (heapctype_init(self, args, kwargs) < 0) { |
| 6262 | + return -1; |
| 6263 | + } |
| 6264 | + /* Initialize additional element */ |
| 6265 | + ((HeapCTypeSubclassObject *)self)->value2 = 20; |
| 6266 | + return 0; |
| 6267 | +} |
| 6268 | + |
| 6269 | +static struct PyMemberDef heapctypesubclass_members[] = { |
| 6270 | + {"value2", T_INT, offsetof(HeapCTypeSubclassObject, value2)}, |
| 6271 | + {NULL} /* Sentinel */ |
| 6272 | +}; |
| 6273 | + |
| 6274 | +static PyType_Slot HeapCTypeSubclass_slots[] = { |
| 6275 | + {Py_tp_init, heapctypesubclass_init}, |
| 6276 | + {Py_tp_members, heapctypesubclass_members}, |
| 6277 | + {Py_tp_doc, heapctypesubclass__doc__}, |
| 6278 | + {0, 0}, |
| 6279 | +}; |
| 6280 | + |
| 6281 | +static PyType_Spec HeapCTypeSubclass_spec = { |
| 6282 | + "_testcapi.HeapCTypeSubclass", |
| 6283 | + sizeof(HeapCTypeSubclassObject), |
| 6284 | + 0, |
| 6285 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 6286 | + HeapCTypeSubclass_slots |
| 6287 | +}; |
| 6288 | + |
| 6289 | +PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__, |
| 6290 | +"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n" |
| 6291 | +"__class__ is set to plain HeapCTypeSubclass during finalization.\n" |
| 6292 | +"__init__ sets the 'value' attribute to 10 and 'value2' to 20."); |
| 6293 | + |
| 6294 | +static int |
| 6295 | +heapctypesubclasswithfinalizer_init(PyObject *self, PyObject *args, PyObject *kwargs) |
| 6296 | +{ |
| 6297 | + PyTypeObject *base = (PyTypeObject *)PyType_GetSlot(Py_TYPE(self), Py_tp_base); |
| 6298 | + initproc base_init = PyType_GetSlot(base, Py_tp_init); |
| 6299 | + base_init(self, args, kwargs); |
| 6300 | + return 0; |
| 6301 | +} |
| 6302 | + |
| 6303 | +static void |
| 6304 | +heapctypesubclasswithfinalizer_finalize(PyObject *self) |
| 6305 | +{ |
| 6306 | + PyObject *error_type, *error_value, *error_traceback, *m, *oldtype, *newtype; |
| 6307 | + |
| 6308 | + /* Save the current exception, if any. */ |
| 6309 | + PyErr_Fetch(&error_type, &error_value, &error_traceback); |
| 6310 | + |
| 6311 | + m = PyState_FindModule(&_testcapimodule); |
| 6312 | + if (m == NULL) { |
| 6313 | + goto cleanup_finalize; |
| 6314 | + } |
| 6315 | + oldtype = PyObject_GetAttrString(m, "HeapCTypeSubclassWithFinalizer"); |
| 6316 | + newtype = PyObject_GetAttrString(m, "HeapCTypeSubclass"); |
| 6317 | + if (oldtype == NULL || newtype == NULL) { |
| 6318 | + goto cleanup_finalize; |
| 6319 | + } |
| 6320 | + |
| 6321 | + if (PyObject_SetAttrString(self, "__class__", newtype) < 0) { |
| 6322 | + goto cleanup_finalize; |
| 6323 | + } |
| 6324 | + if (PyObject_SetAttrString( |
| 6325 | + oldtype, "refcnt_in_del", PyLong_FromSsize_t(Py_REFCNT(oldtype))) < 0) { |
| 6326 | + goto cleanup_finalize; |
| 6327 | + } |
| 6328 | + if (PyObject_SetAttrString( |
| 6329 | + newtype, "refcnt_in_del", PyLong_FromSsize_t(Py_REFCNT(newtype))) < 0) { |
| 6330 | + goto cleanup_finalize; |
| 6331 | + } |
| 6332 | + |
| 6333 | +cleanup_finalize: |
| 6334 | + Py_XDECREF(oldtype); |
| 6335 | + Py_XDECREF(newtype); |
| 6336 | + |
| 6337 | + /* Restore the saved exception. */ |
| 6338 | + PyErr_Restore(error_type, error_value, error_traceback); |
| 6339 | +} |
| 6340 | + |
| 6341 | +static PyType_Slot HeapCTypeSubclassWithFinalizer_slots[] = { |
| 6342 | + {Py_tp_init, heapctypesubclasswithfinalizer_init}, |
| 6343 | + {Py_tp_members, heapctypesubclass_members}, |
| 6344 | + {Py_tp_finalize, heapctypesubclasswithfinalizer_finalize}, |
| 6345 | + {Py_tp_doc, heapctypesubclasswithfinalizer__doc__}, |
| 6346 | + {0, 0}, |
| 6347 | +}; |
| 6348 | + |
| 6349 | +static PyType_Spec HeapCTypeSubclassWithFinalizer_spec = { |
| 6350 | + "_testcapi.HeapCTypeSubclassWithFinalizer", |
| 6351 | + sizeof(HeapCTypeSubclassObject), |
| 6352 | + 0, |
| 6353 | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, |
| 6354 | + HeapCTypeSubclassWithFinalizer_slots |
| 6355 | +}; |
| 6356 | + |
6172 | 6357 | static PyMethodDef meth_instance_methods[] = {
|
6173 | 6358 | {"meth_varargs", meth_varargs, METH_VARARGS},
|
6174 | 6359 | {"meth_varargs_keywords", (PyCFunction)(void(*)(void))meth_varargs_keywords, METH_VARARGS|METH_KEYWORDS},
|
@@ -6380,5 +6565,40 @@ PyInit__testcapi(void)
|
6380 | 6565 | TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
|
6381 | 6566 | Py_INCREF(TestError);
|
6382 | 6567 | PyModule_AddObject(m, "error", TestError);
|
| 6568 | + |
| 6569 | + PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec); |
| 6570 | + if (HeapGcCType == NULL) { |
| 6571 | + return NULL; |
| 6572 | + } |
| 6573 | + PyModule_AddObject(m, "HeapGcCType", HeapGcCType); |
| 6574 | + |
| 6575 | + PyObject *HeapCType = PyType_FromSpec(&HeapCType_spec); |
| 6576 | + if (HeapCType == NULL) { |
| 6577 | + return NULL; |
| 6578 | + } |
| 6579 | + PyObject *subclass_bases = PyTuple_Pack(1, HeapCType); |
| 6580 | + if (subclass_bases == NULL) { |
| 6581 | + return NULL; |
| 6582 | + } |
| 6583 | + PyObject *HeapCTypeSubclass = PyType_FromSpecWithBases(&HeapCTypeSubclass_spec, subclass_bases); |
| 6584 | + if (HeapCTypeSubclass == NULL) { |
| 6585 | + return NULL; |
| 6586 | + } |
| 6587 | + Py_DECREF(subclass_bases); |
| 6588 | + PyModule_AddObject(m, "HeapCTypeSubclass", HeapCTypeSubclass); |
| 6589 | + |
| 6590 | + PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass); |
| 6591 | + if (subclass_with_finalizer_bases == NULL) { |
| 6592 | + return NULL; |
| 6593 | + } |
| 6594 | + PyObject *HeapCTypeSubclassWithFinalizer = PyType_FromSpecWithBases( |
| 6595 | + &HeapCTypeSubclassWithFinalizer_spec, subclass_with_finalizer_bases); |
| 6596 | + if (HeapCTypeSubclassWithFinalizer == NULL) { |
| 6597 | + return NULL; |
| 6598 | + } |
| 6599 | + Py_DECREF(subclass_with_finalizer_bases); |
| 6600 | + PyModule_AddObject(m, "HeapCTypeSubclassWithFinalizer", HeapCTypeSubclassWithFinalizer); |
| 6601 | + |
| 6602 | + PyState_AddModule(m, &_testcapimodule); |
6383 | 6603 | return m;
|
6384 | 6604 | }
|
0 commit comments