summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2022-08-01 13:04:14 (GMT)
committerGitHub <noreply@github.com>2022-08-01 13:04:14 (GMT)
commit664e96a98fcc7572d4b049b70b74cdd63bd736c6 (patch)
tree30d3088575ffab18ae16d8cc8efeee0d81883f33 /Modules
parentbc7c7cd18a4ae015449f95454a762a7276585bb8 (diff)
downloadcpython-664e96a98fcc7572d4b049b70b74cdd63bd736c6.zip
cpython-664e96a98fcc7572d4b049b70b74cdd63bd736c6.tar.gz
cpython-664e96a98fcc7572d4b049b70b74cdd63bd736c6.tar.bz2
gh-93649: Split heaptype tests from _testcapimodule.c (GH-95386)
This removes the unused negative_dictoffset function: the type this function would create is available as _testcapi.HeapCTypeWithNegativeDict
Diffstat (limited to 'Modules')
-rw-r--r--Modules/Setup.stdlib.in2
-rw-r--r--Modules/_testcapi/heaptype.c973
-rw-r--r--Modules/_testcapi/parts.h1
-rw-r--r--Modules/_testcapimodule.c983
4 files changed, 989 insertions, 970 deletions
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 09eca9f..c5dc1e8 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -169,7 +169,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c
# Some testing modules MUST be built as shared libraries.
*shared*
diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c
new file mode 100644
index 0000000..9fb0051
--- /dev/null
+++ b/Modules/_testcapi/heaptype.c
@@ -0,0 +1,973 @@
+#include "parts.h"
+#include "structmember.h" // PyMemberDef
+
+static struct PyModuleDef *_testcapimodule = NULL; // set at initialization
+
+/* Tests for heap types (PyType_From*) */
+
+static PyObject *pytype_fromspec_meta(PyObject* self, PyObject *meta)
+{
+ if (!PyType_Check(meta)) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "pytype_fromspec_meta: must be invoked with a type argument!");
+ return NULL;
+ }
+
+ PyType_Slot HeapCTypeViaMetaclass_slots[] = {
+ {0},
+ };
+
+ PyType_Spec HeapCTypeViaMetaclass_spec = {
+ "_testcapi.HeapCTypeViaMetaclass",
+ sizeof(PyObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ HeapCTypeViaMetaclass_slots
+ };
+
+ return PyType_FromMetaclass(
+ (PyTypeObject *) meta, NULL, &HeapCTypeViaMetaclass_spec, NULL);
+}
+
+
+static PyType_Slot empty_type_slots[] = {
+ {0, 0},
+};
+
+static PyType_Spec MinimalMetaclass_spec = {
+ .name = "_testcapi.MinimalMetaclass",
+ .basicsize = sizeof(PyHeapTypeObject),
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .slots = empty_type_slots,
+};
+
+static PyType_Spec MinimalType_spec = {
+ .name = "_testcapi.MinimalSpecType",
+ .basicsize = 0, // Updated later
+ .flags = Py_TPFLAGS_DEFAULT,
+ .slots = empty_type_slots,
+};
+
+
+static PyObject *
+test_from_spec_metatype_inheritance(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *metaclass = NULL;
+ PyObject *class = NULL;
+ PyObject *new = NULL;
+ PyObject *subclasses = NULL;
+ PyObject *result = NULL;
+ int r;
+
+ metaclass = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
+ if (metaclass == NULL) {
+ goto finally;
+ }
+ class = PyObject_CallFunction(metaclass, "s(){}", "TestClass");
+ if (class == NULL) {
+ goto finally;
+ }
+
+ MinimalType_spec.basicsize = (int)(((PyTypeObject*)class)->tp_basicsize);
+ new = PyType_FromSpecWithBases(&MinimalType_spec, class);
+ if (new == NULL) {
+ goto finally;
+ }
+ if (Py_TYPE(new) != (PyTypeObject*)metaclass) {
+ PyErr_SetString(PyExc_AssertionError,
+ "Metaclass not set properly!");
+ goto finally;
+ }
+
+ /* Assert that __subclasses__ is updated */
+ subclasses = PyObject_CallMethod(class, "__subclasses__", "");
+ if (!subclasses) {
+ goto finally;
+ }
+ r = PySequence_Contains(subclasses, new);
+ if (r < 0) {
+ goto finally;
+ }
+ if (r == 0) {
+ PyErr_SetString(PyExc_AssertionError,
+ "subclasses not set properly!");
+ goto finally;
+ }
+
+ result = Py_NewRef(Py_None);
+
+finally:
+ Py_XDECREF(metaclass);
+ Py_XDECREF(class);
+ Py_XDECREF(new);
+ Py_XDECREF(subclasses);
+ return result;
+}
+
+
+static PyObject *
+test_from_spec_invalid_metatype_inheritance(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *metaclass_a = NULL;
+ PyObject *metaclass_b = NULL;
+ PyObject *class_a = NULL;
+ PyObject *class_b = NULL;
+ PyObject *bases = NULL;
+ PyObject *new = NULL;
+ PyObject *meta_error_string = NULL;
+ PyObject *exc_type = NULL;
+ PyObject *exc_value = NULL;
+ PyObject *exc_traceback = NULL;
+ PyObject *result = NULL;
+
+ metaclass_a = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
+ if (metaclass_a == NULL) {
+ goto finally;
+ }
+ metaclass_b = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
+ if (metaclass_b == NULL) {
+ goto finally;
+ }
+ class_a = PyObject_CallFunction(metaclass_a, "s(){}", "TestClassA");
+ if (class_a == NULL) {
+ goto finally;
+ }
+
+ class_b = PyObject_CallFunction(metaclass_b, "s(){}", "TestClassB");
+ if (class_b == NULL) {
+ goto finally;
+ }
+
+ bases = PyTuple_Pack(2, class_a, class_b);
+ if (bases == NULL) {
+ goto finally;
+ }
+
+ /*
+ * The following should raise a TypeError due to a MetaClass conflict.
+ */
+ new = PyType_FromSpecWithBases(&MinimalType_spec, bases);
+ if (new != NULL) {
+ PyErr_SetString(PyExc_AssertionError,
+ "MetaType conflict not recognized by PyType_FromSpecWithBases");
+ goto finally;
+ }
+
+ // Assert that the correct exception was raised
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+ PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
+
+ meta_error_string = PyUnicode_FromString("metaclass conflict:");
+ if (meta_error_string == NULL) {
+ goto finally;
+ }
+ int res = PyUnicode_Contains(exc_value, meta_error_string);
+ if (res < 0) {
+ goto finally;
+ }
+ if (res == 0) {
+ PyErr_SetString(PyExc_AssertionError,
+ "TypeError did not inlclude expected message.");
+ goto finally;
+ }
+ result = Py_NewRef(Py_None);
+ }
+finally:
+ Py_XDECREF(metaclass_a);
+ Py_XDECREF(metaclass_b);
+ Py_XDECREF(bases);
+ Py_XDECREF(new);
+ Py_XDECREF(meta_error_string);
+ Py_XDECREF(exc_type);
+ Py_XDECREF(exc_value);
+ Py_XDECREF(exc_traceback);
+ Py_XDECREF(class_a);
+ Py_XDECREF(class_b);
+ return result;
+}
+
+
+static PyObject *
+simple_str(PyObject *self) {
+ return PyUnicode_FromString("<test>");
+}
+
+
+static PyObject *
+test_type_from_ephemeral_spec(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ // Test that a heap type can be created from a spec that's later deleted
+ // (along with all its contents).
+ // All necessary data must be copied and held by the class
+ PyType_Spec *spec = NULL;
+ char *name = NULL;
+ char *doc = NULL;
+ PyType_Slot *slots = NULL;
+ PyObject *class = NULL;
+ PyObject *instance = NULL;
+ PyObject *obj = NULL;
+ PyObject *result = NULL;
+
+ /* create a spec (and all its contents) on the heap */
+
+ const char NAME[] = "testcapi._Test";
+ const char DOC[] = "a test class";
+
+ spec = PyMem_New(PyType_Spec, 1);
+ if (spec == NULL) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+ name = PyMem_New(char, sizeof(NAME));
+ if (name == NULL) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+ memcpy(name, NAME, sizeof(NAME));
+
+ doc = PyMem_New(char, sizeof(DOC));
+ if (doc == NULL) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+ memcpy(doc, DOC, sizeof(DOC));
+
+ spec->name = name;
+ spec->basicsize = sizeof(PyObject);
+ spec->itemsize = 0;
+ spec->flags = Py_TPFLAGS_DEFAULT;
+ slots = PyMem_New(PyType_Slot, 3);
+ if (slots == NULL) {
+ PyErr_NoMemory();
+ goto finally;
+ }
+ slots[0].slot = Py_tp_str;
+ slots[0].pfunc = simple_str;
+ slots[1].slot = Py_tp_doc;
+ slots[1].pfunc = doc;
+ slots[2].slot = 0;
+ slots[2].pfunc = NULL;
+ spec->slots = slots;
+
+ /* create the class */
+
+ class = PyType_FromSpec(spec);
+ if (class == NULL) {
+ goto finally;
+ }
+
+ /* deallocate the spec (and all contents) */
+
+ // (Explicitly ovewrite memory before freeing,
+ // so bugs show themselves even without the debug allocator's help.)
+ memset(spec, 0xdd, sizeof(PyType_Spec));
+ PyMem_Del(spec);
+ spec = NULL;
+ memset(name, 0xdd, sizeof(NAME));
+ PyMem_Del(name);
+ name = NULL;
+ memset(doc, 0xdd, sizeof(DOC));
+ PyMem_Del(doc);
+ doc = NULL;
+ memset(slots, 0xdd, 3 * sizeof(PyType_Slot));
+ PyMem_Del(slots);
+ slots = NULL;
+
+ /* check that everything works */
+
+ PyTypeObject *class_tp = (PyTypeObject *)class;
+ PyHeapTypeObject *class_ht = (PyHeapTypeObject *)class;
+ assert(strcmp(class_tp->tp_name, "testcapi._Test") == 0);
+ assert(strcmp(PyUnicode_AsUTF8(class_ht->ht_name), "_Test") == 0);
+ assert(strcmp(PyUnicode_AsUTF8(class_ht->ht_qualname), "_Test") == 0);
+ assert(strcmp(class_tp->tp_doc, "a test class") == 0);
+
+ // call and check __str__
+ instance = PyObject_CallNoArgs(class);
+ if (instance == NULL) {
+ goto finally;
+ }
+ obj = PyObject_Str(instance);
+ if (obj == NULL) {
+ goto finally;
+ }
+ assert(strcmp(PyUnicode_AsUTF8(obj), "<test>") == 0);
+ Py_CLEAR(obj);
+
+ result = Py_NewRef(Py_None);
+ finally:
+ PyMem_Del(spec);
+ PyMem_Del(name);
+ PyMem_Del(doc);
+ PyMem_Del(slots);
+ Py_XDECREF(class);
+ Py_XDECREF(instance);
+ Py_XDECREF(obj);
+ return result;
+}
+
+PyType_Slot repeated_doc_slots[] = {
+ {Py_tp_doc, "A class used for testsĀ·"},
+ {Py_tp_doc, "A class used for tests"},
+ {0, 0},
+};
+
+PyType_Spec repeated_doc_slots_spec = {
+ .name = "RepeatedDocSlotClass",
+ .basicsize = sizeof(PyObject),
+ .slots = repeated_doc_slots,
+};
+
+typedef struct {
+ PyObject_HEAD
+ int data;
+} HeapCTypeWithDataObject;
+
+
+static struct PyMemberDef members_to_repeat[] = {
+ {"T_INT", T_INT, offsetof(HeapCTypeWithDataObject, data), 0, NULL},
+ {NULL}
+};
+
+PyType_Slot repeated_members_slots[] = {
+ {Py_tp_members, members_to_repeat},
+ {Py_tp_members, members_to_repeat},
+ {0, 0},
+};
+
+PyType_Spec repeated_members_slots_spec = {
+ .name = "RepeatedMembersSlotClass",
+ .basicsize = sizeof(HeapCTypeWithDataObject),
+ .slots = repeated_members_slots,
+};
+
+static PyObject *
+create_type_from_repeated_slots(PyObject *self, PyObject *variant_obj)
+{
+ PyObject *class = NULL;
+ int variant = PyLong_AsLong(variant_obj);
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+ switch (variant) {
+ case 0:
+ class = PyType_FromSpec(&repeated_doc_slots_spec);
+ break;
+ case 1:
+ class = PyType_FromSpec(&repeated_members_slots_spec);
+ break;
+ default:
+ PyErr_SetString(PyExc_ValueError, "bad test variant");
+ break;
+ }
+ return class;
+}
+
+
+static PyMethodDef TestMethods[] = {
+ {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O},
+ {"test_type_from_ephemeral_spec", test_type_from_ephemeral_spec, METH_NOARGS},
+ {"create_type_from_repeated_slots",
+ create_type_from_repeated_slots, METH_O},
+ {"test_from_spec_metatype_inheritance", test_from_spec_metatype_inheritance,
+ METH_NOARGS},
+ {"test_from_spec_invalid_metatype_inheritance",
+ test_from_spec_invalid_metatype_inheritance,
+ METH_NOARGS},
+ {NULL},
+};
+
+
+PyDoc_STRVAR(heapdocctype__doc__,
+"HeapDocCType(arg1, arg2)\n"
+"--\n"
+"\n"
+"somedoc");
+
+typedef struct {
+ PyObject_HEAD
+} HeapDocCTypeObject;
+
+static PyType_Slot HeapDocCType_slots[] = {
+ {Py_tp_doc, (char*)heapdocctype__doc__},
+ {0},
+};
+
+static PyType_Spec HeapDocCType_spec = {
+ "_testcapi.HeapDocCType",
+ sizeof(HeapDocCTypeObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ HeapDocCType_slots
+};
+
+typedef struct {
+ PyObject_HEAD
+} NullTpDocTypeObject;
+
+static PyType_Slot NullTpDocType_slots[] = {
+ {Py_tp_doc, NULL},
+ {0, 0},
+};
+
+static PyType_Spec NullTpDocType_spec = {
+ "_testcapi.NullTpDocType",
+ sizeof(NullTpDocTypeObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ NullTpDocType_slots
+};
+
+
+PyDoc_STRVAR(heapgctype__doc__,
+"A heap type with GC, and with overridden dealloc.\n\n"
+"The 'value' attribute is set to 10 in __init__.");
+
+typedef struct {
+ PyObject_HEAD
+ int value;
+} HeapCTypeObject;
+
+static struct PyMemberDef heapctype_members[] = {
+ {"value", T_INT, offsetof(HeapCTypeObject, value)},
+ {NULL} /* Sentinel */
+};
+
+static int
+heapctype_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ ((HeapCTypeObject *)self)->value = 10;
+ return 0;
+}
+
+static int
+heapgcctype_traverse(HeapCTypeObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ return 0;
+}
+
+static void
+heapgcctype_dealloc(HeapCTypeObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
+ PyObject_GC_Del(self);
+ Py_DECREF(tp);
+}
+
+static PyType_Slot HeapGcCType_slots[] = {
+ {Py_tp_init, heapctype_init},
+ {Py_tp_members, heapctype_members},
+ {Py_tp_dealloc, heapgcctype_dealloc},
+ {Py_tp_traverse, heapgcctype_traverse},
+ {Py_tp_doc, (char*)heapgctype__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapGcCType_spec = {
+ "_testcapi.HeapGcCType",
+ sizeof(HeapCTypeObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+ HeapGcCType_slots
+};
+
+PyDoc_STRVAR(heapctype__doc__,
+"A heap type without GC, but with overridden dealloc.\n\n"
+"The 'value' attribute is set to 10 in __init__.");
+
+static void
+heapctype_dealloc(HeapCTypeObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_Free(self);
+ Py_DECREF(tp);
+}
+
+static PyType_Slot HeapCType_slots[] = {
+ {Py_tp_init, heapctype_init},
+ {Py_tp_members, heapctype_members},
+ {Py_tp_dealloc, heapctype_dealloc},
+ {Py_tp_doc, (char*)heapctype__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapCType_spec = {
+ "_testcapi.HeapCType",
+ sizeof(HeapCTypeObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCType_slots
+};
+
+PyDoc_STRVAR(heapctypesubclass__doc__,
+"Subclass of HeapCType, without GC.\n\n"
+"__init__ sets the 'value' attribute to 10 and 'value2' to 20.");
+
+typedef struct {
+ HeapCTypeObject base;
+ int value2;
+} HeapCTypeSubclassObject;
+
+static int
+heapctypesubclass_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ /* Call __init__ of the superclass */
+ if (heapctype_init(self, args, kwargs) < 0) {
+ return -1;
+ }
+ /* Initialize additional element */
+ ((HeapCTypeSubclassObject *)self)->value2 = 20;
+ return 0;
+}
+
+static struct PyMemberDef heapctypesubclass_members[] = {
+ {"value2", T_INT, offsetof(HeapCTypeSubclassObject, value2)},
+ {NULL} /* Sentinel */
+};
+
+static PyType_Slot HeapCTypeSubclass_slots[] = {
+ {Py_tp_init, heapctypesubclass_init},
+ {Py_tp_members, heapctypesubclass_members},
+ {Py_tp_doc, (char*)heapctypesubclass__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeSubclass_spec = {
+ "_testcapi.HeapCTypeSubclass",
+ sizeof(HeapCTypeSubclassObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeSubclass_slots
+};
+
+PyDoc_STRVAR(heapctypewithbuffer__doc__,
+"Heap type with buffer support.\n\n"
+"The buffer is set to [b'1', b'2', b'3', b'4']");
+
+typedef struct {
+ HeapCTypeObject base;
+ char buffer[4];
+} HeapCTypeWithBufferObject;
+
+static int
+heapctypewithbuffer_getbuffer(HeapCTypeWithBufferObject *self, Py_buffer *view, int flags)
+{
+ self->buffer[0] = '1';
+ self->buffer[1] = '2';
+ self->buffer[2] = '3';
+ self->buffer[3] = '4';
+ return PyBuffer_FillInfo(
+ view, (PyObject*)self, (void *)self->buffer, 4, 1, flags);
+}
+
+static void
+heapctypewithbuffer_releasebuffer(HeapCTypeWithBufferObject *self, Py_buffer *view)
+{
+ assert(view->obj == (void*) self);
+}
+
+static PyType_Slot HeapCTypeWithBuffer_slots[] = {
+ {Py_bf_getbuffer, heapctypewithbuffer_getbuffer},
+ {Py_bf_releasebuffer, heapctypewithbuffer_releasebuffer},
+ {Py_tp_doc, (char*)heapctypewithbuffer__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeWithBuffer_spec = {
+ "_testcapi.HeapCTypeWithBuffer",
+ sizeof(HeapCTypeWithBufferObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeWithBuffer_slots
+};
+
+PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__,
+"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n"
+"__class__ is set to plain HeapCTypeSubclass during finalization.\n"
+"__init__ sets the 'value' attribute to 10 and 'value2' to 20.");
+
+static int
+heapctypesubclasswithfinalizer_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyTypeObject *base = (PyTypeObject *)PyType_GetSlot(Py_TYPE(self), Py_tp_base);
+ initproc base_init = PyType_GetSlot(base, Py_tp_init);
+ base_init(self, args, kwargs);
+ return 0;
+}
+
+static void
+heapctypesubclasswithfinalizer_finalize(PyObject *self)
+{
+ PyObject *error_type, *error_value, *error_traceback, *m;
+ PyObject *oldtype = NULL, *newtype = NULL, *refcnt = NULL;
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ if (_testcapimodule == NULL) {
+ goto cleanup_finalize;
+ }
+ m = PyState_FindModule(_testcapimodule);
+ if (m == NULL) {
+ goto cleanup_finalize;
+ }
+ oldtype = PyObject_GetAttrString(m, "HeapCTypeSubclassWithFinalizer");
+ newtype = PyObject_GetAttrString(m, "HeapCTypeSubclass");
+ if (oldtype == NULL || newtype == NULL) {
+ goto cleanup_finalize;
+ }
+
+ if (PyObject_SetAttrString(self, "__class__", newtype) < 0) {
+ goto cleanup_finalize;
+ }
+ refcnt = PyLong_FromSsize_t(Py_REFCNT(oldtype));
+ if (refcnt == NULL) {
+ goto cleanup_finalize;
+ }
+ if (PyObject_SetAttrString(oldtype, "refcnt_in_del", refcnt) < 0) {
+ goto cleanup_finalize;
+ }
+ Py_DECREF(refcnt);
+ refcnt = PyLong_FromSsize_t(Py_REFCNT(newtype));
+ if (refcnt == NULL) {
+ goto cleanup_finalize;
+ }
+ if (PyObject_SetAttrString(newtype, "refcnt_in_del", refcnt) < 0) {
+ goto cleanup_finalize;
+ }
+
+cleanup_finalize:
+ Py_XDECREF(oldtype);
+ Py_XDECREF(newtype);
+ Py_XDECREF(refcnt);
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+static PyType_Slot HeapCTypeSubclassWithFinalizer_slots[] = {
+ {Py_tp_init, heapctypesubclasswithfinalizer_init},
+ {Py_tp_members, heapctypesubclass_members},
+ {Py_tp_finalize, heapctypesubclasswithfinalizer_finalize},
+ {Py_tp_doc, (char*)heapctypesubclasswithfinalizer__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeSubclassWithFinalizer_spec = {
+ "_testcapi.HeapCTypeSubclassWithFinalizer",
+ sizeof(HeapCTypeSubclassObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
+ HeapCTypeSubclassWithFinalizer_slots
+};
+
+static PyType_Slot HeapCTypeMetaclass_slots[] = {
+ {0},
+};
+
+static PyType_Spec HeapCTypeMetaclass_spec = {
+ "_testcapi.HeapCTypeMetaclass",
+ sizeof(PyHeapTypeObject),
+ sizeof(PyMemberDef),
+ Py_TPFLAGS_DEFAULT,
+ HeapCTypeMetaclass_slots
+};
+
+static PyObject *
+heap_ctype_metaclass_custom_tp_new(PyTypeObject *tp, PyObject *args, PyObject *kwargs)
+{
+ return PyType_Type.tp_new(tp, args, kwargs);
+}
+
+static PyType_Slot HeapCTypeMetaclassCustomNew_slots[] = {
+ { Py_tp_new, heap_ctype_metaclass_custom_tp_new },
+ {0},
+};
+
+static PyType_Spec HeapCTypeMetaclassCustomNew_spec = {
+ "_testcapi.HeapCTypeMetaclassCustomNew",
+ sizeof(PyHeapTypeObject),
+ sizeof(PyMemberDef),
+ Py_TPFLAGS_DEFAULT,
+ HeapCTypeMetaclassCustomNew_slots
+};
+
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *dict;
+} HeapCTypeWithDictObject;
+
+static void
+heapctypewithdict_dealloc(HeapCTypeWithDictObject* self)
+{
+
+ PyTypeObject *tp = Py_TYPE(self);
+ Py_XDECREF(self->dict);
+ PyObject_Free(self);
+ Py_DECREF(tp);
+}
+
+static PyGetSetDef heapctypewithdict_getsetlist[] = {
+ {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+ {NULL} /* Sentinel */
+};
+
+static struct PyMemberDef heapctypewithdict_members[] = {
+ {"dictobj", T_OBJECT, offsetof(HeapCTypeWithDictObject, dict)},
+ {"__dictoffset__", T_PYSSIZET, offsetof(HeapCTypeWithDictObject, dict), READONLY},
+ {NULL} /* Sentinel */
+};
+
+static PyType_Slot HeapCTypeWithDict_slots[] = {
+ {Py_tp_members, heapctypewithdict_members},
+ {Py_tp_getset, heapctypewithdict_getsetlist},
+ {Py_tp_dealloc, heapctypewithdict_dealloc},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeWithDict_spec = {
+ "_testcapi.HeapCTypeWithDict",
+ sizeof(HeapCTypeWithDictObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeWithDict_slots
+};
+
+static struct PyMemberDef heapctypewithnegativedict_members[] = {
+ {"dictobj", T_OBJECT, offsetof(HeapCTypeWithDictObject, dict)},
+ {"__dictoffset__", T_PYSSIZET, -(Py_ssize_t)sizeof(void*), READONLY},
+ {NULL} /* Sentinel */
+};
+
+static PyType_Slot HeapCTypeWithNegativeDict_slots[] = {
+ {Py_tp_members, heapctypewithnegativedict_members},
+ {Py_tp_getset, heapctypewithdict_getsetlist},
+ {Py_tp_dealloc, heapctypewithdict_dealloc},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeWithNegativeDict_spec = {
+ "_testcapi.HeapCTypeWithNegativeDict",
+ sizeof(HeapCTypeWithDictObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeWithNegativeDict_slots
+};
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *weakreflist;
+} HeapCTypeWithWeakrefObject;
+
+static struct PyMemberDef heapctypewithweakref_members[] = {
+ {"weakreflist", T_OBJECT, offsetof(HeapCTypeWithWeakrefObject, weakreflist)},
+ {"__weaklistoffset__", T_PYSSIZET,
+ offsetof(HeapCTypeWithWeakrefObject, weakreflist), READONLY},
+ {NULL} /* Sentinel */
+};
+
+static void
+heapctypewithweakref_dealloc(HeapCTypeWithWeakrefObject* self)
+{
+
+ PyTypeObject *tp = Py_TYPE(self);
+ if (self->weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *) self);
+ Py_XDECREF(self->weakreflist);
+ PyObject_Free(self);
+ Py_DECREF(tp);
+}
+
+static PyType_Slot HeapCTypeWithWeakref_slots[] = {
+ {Py_tp_members, heapctypewithweakref_members},
+ {Py_tp_dealloc, heapctypewithweakref_dealloc},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeWithWeakref_spec = {
+ "_testcapi.HeapCTypeWithWeakref",
+ sizeof(HeapCTypeWithWeakrefObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeWithWeakref_slots
+};
+
+PyDoc_STRVAR(heapctypesetattr__doc__,
+"A heap type without GC, but with overridden __setattr__.\n\n"
+"The 'value' attribute is set to 10 in __init__ and updated via attribute setting.");
+
+typedef struct {
+ PyObject_HEAD
+ long value;
+} HeapCTypeSetattrObject;
+
+static struct PyMemberDef heapctypesetattr_members[] = {
+ {"pvalue", T_LONG, offsetof(HeapCTypeSetattrObject, value)},
+ {NULL} /* Sentinel */
+};
+
+static int
+heapctypesetattr_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ ((HeapCTypeSetattrObject *)self)->value = 10;
+ return 0;
+}
+
+static void
+heapctypesetattr_dealloc(HeapCTypeSetattrObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_Free(self);
+ Py_DECREF(tp);
+}
+
+static int
+heapctypesetattr_setattro(HeapCTypeSetattrObject *self, PyObject *attr, PyObject *value)
+{
+ PyObject *svalue = PyUnicode_FromString("value");
+ if (svalue == NULL)
+ return -1;
+ int eq = PyObject_RichCompareBool(svalue, attr, Py_EQ);
+ Py_DECREF(svalue);
+ if (eq < 0)
+ return -1;
+ if (!eq) {
+ return PyObject_GenericSetAttr((PyObject*) self, attr, value);
+ }
+ if (value == NULL) {
+ self->value = 0;
+ return 0;
+ }
+ PyObject *ivalue = PyNumber_Long(value);
+ if (ivalue == NULL)
+ return -1;
+ long v = PyLong_AsLong(ivalue);
+ Py_DECREF(ivalue);
+ if (v == -1 && PyErr_Occurred())
+ return -1;
+ self->value = v;
+ return 0;
+}
+
+static PyType_Slot HeapCTypeSetattr_slots[] = {
+ {Py_tp_init, heapctypesetattr_init},
+ {Py_tp_members, heapctypesetattr_members},
+ {Py_tp_setattro, heapctypesetattr_setattro},
+ {Py_tp_dealloc, heapctypesetattr_dealloc},
+ {Py_tp_doc, (char*)heapctypesetattr__doc__},
+ {0, 0},
+};
+
+static PyType_Spec HeapCTypeSetattr_spec = {
+ "_testcapi.HeapCTypeSetattr",
+ sizeof(HeapCTypeSetattrObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ HeapCTypeSetattr_slots
+};
+
+int
+_PyTestCapi_Init_Heaptype(PyObject *m) {
+ _testcapimodule = PyModule_GetDef(m);
+
+ if (PyModule_AddFunctions(m, TestMethods) < 0) {
+ return -1;
+ }
+
+ PyObject *HeapDocCType = PyType_FromSpec(&HeapDocCType_spec);
+ if (HeapDocCType == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapDocCType", HeapDocCType);
+
+ /* bpo-41832: Add a new type to test PyType_FromSpec()
+ now can accept a NULL tp_doc slot. */
+ PyObject *NullTpDocType = PyType_FromSpec(&NullTpDocType_spec);
+ if (NullTpDocType == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "NullTpDocType", NullTpDocType);
+
+ PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec);
+ if (HeapGcCType == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapGcCType", HeapGcCType);
+
+ PyObject *HeapCType = PyType_FromSpec(&HeapCType_spec);
+ if (HeapCType == NULL) {
+ return -1;
+ }
+ PyObject *subclass_bases = PyTuple_Pack(1, HeapCType);
+ if (subclass_bases == NULL) {
+ return -1;
+ }
+ PyObject *HeapCTypeSubclass = PyType_FromSpecWithBases(&HeapCTypeSubclass_spec, subclass_bases);
+ if (HeapCTypeSubclass == NULL) {
+ return -1;
+ }
+ Py_DECREF(subclass_bases);
+ PyModule_AddObject(m, "HeapCTypeSubclass", HeapCTypeSubclass);
+
+ PyObject *HeapCTypeWithDict = PyType_FromSpec(&HeapCTypeWithDict_spec);
+ if (HeapCTypeWithDict == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeWithDict", HeapCTypeWithDict);
+
+ PyObject *HeapCTypeWithNegativeDict = PyType_FromSpec(&HeapCTypeWithNegativeDict_spec);
+ if (HeapCTypeWithNegativeDict == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeWithNegativeDict", HeapCTypeWithNegativeDict);
+
+ PyObject *HeapCTypeWithWeakref = PyType_FromSpec(&HeapCTypeWithWeakref_spec);
+ if (HeapCTypeWithWeakref == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeWithWeakref", HeapCTypeWithWeakref);
+
+ PyObject *HeapCTypeWithBuffer = PyType_FromSpec(&HeapCTypeWithBuffer_spec);
+ if (HeapCTypeWithBuffer == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeWithBuffer", HeapCTypeWithBuffer);
+
+ PyObject *HeapCTypeSetattr = PyType_FromSpec(&HeapCTypeSetattr_spec);
+ if (HeapCTypeSetattr == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeSetattr", HeapCTypeSetattr);
+
+ PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass);
+ if (subclass_with_finalizer_bases == NULL) {
+ return -1;
+ }
+ PyObject *HeapCTypeSubclassWithFinalizer = PyType_FromSpecWithBases(
+ &HeapCTypeSubclassWithFinalizer_spec, subclass_with_finalizer_bases);
+ if (HeapCTypeSubclassWithFinalizer == NULL) {
+ return -1;
+ }
+ Py_DECREF(subclass_with_finalizer_bases);
+ PyModule_AddObject(m, "HeapCTypeSubclassWithFinalizer", HeapCTypeSubclassWithFinalizer);
+
+ PyObject *HeapCTypeMetaclass = PyType_FromMetaclass(
+ &PyType_Type, m, &HeapCTypeMetaclass_spec, (PyObject *) &PyType_Type);
+ if (HeapCTypeMetaclass == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeMetaclass", HeapCTypeMetaclass);
+
+ PyObject *HeapCTypeMetaclassCustomNew = PyType_FromMetaclass(
+ &PyType_Type, m, &HeapCTypeMetaclassCustomNew_spec, (PyObject *) &PyType_Type);
+ if (HeapCTypeMetaclassCustomNew == NULL) {
+ return -1;
+ }
+ PyModule_AddObject(m, "HeapCTypeMetaclassCustomNew", HeapCTypeMetaclassCustomNew);
+
+ return 0;
+}
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index 54cddf4..e6d2ed2 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -1,3 +1,4 @@
#include "Python.h"
int _PyTestCapi_Init_Vectorcall(PyObject *module);
+int _PyTestCapi_Init_Heaptype(PyObject *module);
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index b9f75d1..f56b36a 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -49,7 +49,6 @@
// Forward declarations
static struct PyModuleDef _testcapimodule;
-static PyType_Spec HeapTypeNameType_Spec;
static PyObject *TestError; /* set to exception object in init */
@@ -311,30 +310,6 @@ test_dict_inner(int count)
}
}
-static PyObject *pytype_fromspec_meta(PyObject* self, PyObject *meta)
-{
- if (!PyType_Check(meta)) {
- PyErr_SetString(
- TestError,
- "pytype_fromspec_meta: must be invoked with a type argument!");
- return NULL;
- }
-
- PyType_Slot HeapCTypeViaMetaclass_slots[] = {
- {0},
- };
-
- PyType_Spec HeapCTypeViaMetaclass_spec = {
- "_testcapi.HeapCTypeViaMetaclass",
- sizeof(PyObject),
- 0,
- Py_TPFLAGS_DEFAULT,
- HeapCTypeViaMetaclass_slots
- };
-
- return PyType_FromMetaclass(
- (PyTypeObject *) meta, NULL, &HeapCTypeViaMetaclass_spec, NULL);
-}
static PyObject*
@@ -1173,6 +1148,17 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored))
}
+static PyType_Slot HeapTypeNameType_slots[] = {
+ {0},
+};
+
+static PyType_Spec HeapTypeNameType_Spec = {
+ .name = "_testcapi.HeapTypeNameType",
+ .basicsize = sizeof(PyObject),
+ .flags = Py_TPFLAGS_DEFAULT,
+ .slots = HeapTypeNameType_slots,
+};
+
static PyObject *
test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored))
{
@@ -1211,339 +1197,6 @@ test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored))
}
-static PyType_Slot empty_type_slots[] = {
- {0, 0},
-};
-
-static PyType_Spec MinimalMetaclass_spec = {
- .name = "_testcapi.MinimalMetaclass",
- .basicsize = sizeof(PyHeapTypeObject),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .slots = empty_type_slots,
-};
-
-static PyType_Spec MinimalType_spec = {
- .name = "_testcapi.MinimalSpecType",
- .basicsize = 0, // Updated later
- .flags = Py_TPFLAGS_DEFAULT,
- .slots = empty_type_slots,
-};
-
-static PyObject *
-test_from_spec_metatype_inheritance(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
- PyObject *metaclass = NULL;
- PyObject *class = NULL;
- PyObject *new = NULL;
- PyObject *subclasses = NULL;
- PyObject *result = NULL;
- int r;
-
- metaclass = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
- if (metaclass == NULL) {
- goto finally;
- }
- class = PyObject_CallFunction(metaclass, "s(){}", "TestClass");
- if (class == NULL) {
- goto finally;
- }
-
- MinimalType_spec.basicsize = (int)(((PyTypeObject*)class)->tp_basicsize);
- new = PyType_FromSpecWithBases(&MinimalType_spec, class);
- if (new == NULL) {
- goto finally;
- }
- if (Py_TYPE(new) != (PyTypeObject*)metaclass) {
- PyErr_SetString(PyExc_AssertionError,
- "Metaclass not set properly!");
- goto finally;
- }
-
- /* Assert that __subclasses__ is updated */
- subclasses = PyObject_CallMethod(class, "__subclasses__", "");
- if (!subclasses) {
- goto finally;
- }
- r = PySequence_Contains(subclasses, new);
- if (r < 0) {
- goto finally;
- }
- if (r == 0) {
- PyErr_SetString(PyExc_AssertionError,
- "subclasses not set properly!");
- goto finally;
- }
-
- result = Py_NewRef(Py_None);
-
-finally:
- Py_XDECREF(metaclass);
- Py_XDECREF(class);
- Py_XDECREF(new);
- Py_XDECREF(subclasses);
- return result;
-}
-
-
-static PyObject *
-test_from_spec_invalid_metatype_inheritance(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
- PyObject *metaclass_a = NULL;
- PyObject *metaclass_b = NULL;
- PyObject *class_a = NULL;
- PyObject *class_b = NULL;
- PyObject *bases = NULL;
- PyObject *new = NULL;
- PyObject *meta_error_string = NULL;
- PyObject *exc_type = NULL;
- PyObject *exc_value = NULL;
- PyObject *exc_traceback = NULL;
- PyObject *result = NULL;
-
- metaclass_a = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
- if (metaclass_a == NULL) {
- goto finally;
- }
- metaclass_b = PyType_FromSpecWithBases(&MinimalMetaclass_spec, (PyObject*)&PyType_Type);
- if (metaclass_b == NULL) {
- goto finally;
- }
- class_a = PyObject_CallFunction(metaclass_a, "s(){}", "TestClassA");
- if (class_a == NULL) {
- goto finally;
- }
-
- class_b = PyObject_CallFunction(metaclass_b, "s(){}", "TestClassB");
- if (class_b == NULL) {
- goto finally;
- }
-
- bases = PyTuple_Pack(2, class_a, class_b);
- if (bases == NULL) {
- goto finally;
- }
-
- /*
- * The following should raise a TypeError due to a MetaClass conflict.
- */
- new = PyType_FromSpecWithBases(&MinimalType_spec, bases);
- if (new != NULL) {
- PyErr_SetString(PyExc_AssertionError,
- "MetaType conflict not recognized by PyType_FromSpecWithBases");
- goto finally;
- }
-
- // Assert that the correct exception was raised
- if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
-
- meta_error_string = PyUnicode_FromString("metaclass conflict:");
- if (meta_error_string == NULL) {
- goto finally;
- }
- int res = PyUnicode_Contains(exc_value, meta_error_string);
- if (res < 0) {
- goto finally;
- }
- if (res == 0) {
- PyErr_SetString(PyExc_AssertionError,
- "TypeError did not inlclude expected message.");
- goto finally;
- }
- result = Py_NewRef(Py_None);
- }
-finally:
- Py_XDECREF(metaclass_a);
- Py_XDECREF(metaclass_b);
- Py_XDECREF(bases);
- Py_XDECREF(new);
- Py_XDECREF(meta_error_string);
- Py_XDECREF(exc_type);
- Py_XDECREF(exc_value);
- Py_XDECREF(exc_traceback);
- Py_XDECREF(class_a);
- Py_XDECREF(class_b);
- return result;
-}
-
-
-static PyObject *
-simple_str(PyObject *self) {
- return PyUnicode_FromString("<test>");
-}
-
-
-static PyObject *
-test_type_from_ephemeral_spec(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
- // Test that a heap type can be created from a spec that's later deleted
- // (along with all its contents).
- // All necessary data must be copied and held by the class
- PyType_Spec *spec = NULL;
- char *name = NULL;
- char *doc = NULL;
- PyType_Slot *slots = NULL;
- PyObject *class = NULL;
- PyObject *instance = NULL;
- PyObject *obj = NULL;
- PyObject *result = NULL;
-
- /* create a spec (and all its contents) on the heap */
-
- const char NAME[] = "testcapi._Test";
- const char DOC[] = "a test class";
-
- spec = PyMem_New(PyType_Spec, 1);
- if (spec == NULL) {
- PyErr_NoMemory();
- goto finally;
- }
- name = PyMem_New(char, sizeof(NAME));
- if (name == NULL) {
- PyErr_NoMemory();
- goto finally;
- }
- memcpy(name, NAME, sizeof(NAME));
-
- doc = PyMem_New(char, sizeof(DOC));
- if (doc == NULL) {
- PyErr_NoMemory();
- goto finally;
- }
- memcpy(doc, DOC, sizeof(DOC));
-
- spec->name = name;
- spec->basicsize = sizeof(PyObject);
- spec->itemsize = 0;
- spec->flags = Py_TPFLAGS_DEFAULT;
- slots = PyMem_New(PyType_Slot, 3);
- if (slots == NULL) {
- PyErr_NoMemory();
- goto finally;
- }
- slots[0].slot = Py_tp_str;
- slots[0].pfunc = simple_str;
- slots[1].slot = Py_tp_doc;
- slots[1].pfunc = doc;
- slots[2].slot = 0;
- slots[2].pfunc = NULL;
- spec->slots = slots;
-
- /* create the class */
-
- class = PyType_FromSpec(spec);
- if (class == NULL) {
- goto finally;
- }
-
- /* deallocate the spec (and all contents) */
-
- // (Explicitly ovewrite memory before freeing,
- // so bugs show themselves even without the debug allocator's help.)
- memset(spec, 0xdd, sizeof(PyType_Spec));
- PyMem_Del(spec);
- spec = NULL;
- memset(name, 0xdd, sizeof(NAME));
- PyMem_Del(name);
- name = NULL;
- memset(doc, 0xdd, sizeof(DOC));
- PyMem_Del(doc);
- doc = NULL;
- memset(slots, 0xdd, 3 * sizeof(PyType_Slot));
- PyMem_Del(slots);
- slots = NULL;
-
- /* check that everything works */
-
- PyTypeObject *class_tp = (PyTypeObject *)class;
- PyHeapTypeObject *class_ht = (PyHeapTypeObject *)class;
- assert(strcmp(class_tp->tp_name, "testcapi._Test") == 0);
- assert(strcmp(PyUnicode_AsUTF8(class_ht->ht_name), "_Test") == 0);
- assert(strcmp(PyUnicode_AsUTF8(class_ht->ht_qualname), "_Test") == 0);
- assert(strcmp(class_tp->tp_doc, "a test class") == 0);
-
- // call and check __str__
- instance = PyObject_CallNoArgs(class);
- if (instance == NULL) {
- goto finally;
- }
- obj = PyObject_Str(instance);
- if (obj == NULL) {
- goto finally;
- }
- assert(strcmp(PyUnicode_AsUTF8(obj), "<test>") == 0);
- Py_CLEAR(obj);
-
- result = Py_NewRef(Py_None);
- finally:
- PyMem_Del(spec);
- PyMem_Del(name);
- PyMem_Del(doc);
- PyMem_Del(slots);
- Py_XDECREF(class);
- Py_XDECREF(instance);
- Py_XDECREF(obj);
- return result;
-}
-
-PyType_Slot repeated_doc_slots[] = {
- {Py_tp_doc, "A class used for testsĀ·"},
- {Py_tp_doc, "A class used for tests"},
- {0, 0},
-};
-
-PyType_Spec repeated_doc_slots_spec = {
- .name = "RepeatedDocSlotClass",
- .basicsize = sizeof(PyObject),
- .slots = repeated_doc_slots,
-};
-
-typedef struct {
- PyObject_HEAD
- int data;
-} HeapCTypeWithDataObject;
-
-
-static struct PyMemberDef members_to_repeat[] = {
- {"T_INT", T_INT, offsetof(HeapCTypeWithDataObject, data), 0, NULL},
- {NULL}
-};
-
-PyType_Slot repeated_members_slots[] = {
- {Py_tp_members, members_to_repeat},
- {Py_tp_members, members_to_repeat},
- {0, 0},
-};
-
-PyType_Spec repeated_members_slots_spec = {
- .name = "RepeatedMembersSlotClass",
- .basicsize = sizeof(HeapCTypeWithDataObject),
- .slots = repeated_members_slots,
-};
-
-static PyObject *
-create_type_from_repeated_slots(PyObject *self, PyObject *variant_obj)
-{
- PyObject *class = NULL;
- int variant = PyLong_AsLong(variant_obj);
- if (PyErr_Occurred()) {
- return NULL;
- }
- switch (variant) {
- case 0:
- class = PyType_FromSpec(&repeated_doc_slots_spec);
- break;
- case 1:
- class = PyType_FromSpec(&repeated_members_slots_spec);
- break;
- default:
- PyErr_SetString(PyExc_ValueError, "bad test variant");
- break;
- }
- return class;
-}
-
-
static PyObject *
test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored))
{
@@ -6054,7 +5707,6 @@ test_macros(PyObject *self, PyObject *Py_UNUSED(args))
}
-static PyObject *negative_dictoffset(PyObject *, PyObject *);
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*);
static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*);
@@ -6109,7 +5761,6 @@ static PyMethodDef TestMethods[] = {
{"test_long_numbits", test_long_numbits, METH_NOARGS},
{"test_k_code", test_k_code, METH_NOARGS},
{"test_empty_argparse", test_empty_argparse, METH_NOARGS},
- {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O},
{"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS},
{"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS},
{"pyobject_str_from_null", pyobject_str_from_null, METH_NOARGS},
@@ -6128,20 +5779,11 @@ static PyMethodDef TestMethods[] = {
{"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
{"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS},
{"test_buildvalue_N", test_buildvalue_N, METH_NOARGS},
- {"negative_dictoffset", negative_dictoffset, METH_NOARGS},
{"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS},
{"get_args", get_args, METH_VARARGS},
{"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS},
{"test_get_type_name", test_get_type_name, METH_NOARGS},
{"test_get_type_qualname", test_get_type_qualname, METH_NOARGS},
- {"test_type_from_ephemeral_spec", test_type_from_ephemeral_spec, METH_NOARGS},
- {"create_type_from_repeated_slots",
- create_type_from_repeated_slots, METH_O},
- {"test_from_spec_metatype_inheritance", test_from_spec_metatype_inheritance,
- METH_NOARGS},
- {"test_from_spec_invalid_metatype_inheritance",
- test_from_spec_invalid_metatype_inheritance,
- METH_NOARGS},
{"get_kwargs", _PyCFunction_CAST(get_kwargs),
METH_VARARGS|METH_KEYWORDS},
{"getargs_tuple", getargs_tuple, METH_VARARGS},
@@ -6914,509 +6556,6 @@ static PyTypeObject Generic_Type = {
.tp_methods = generic_methods,
};
-PyDoc_STRVAR(heapdocctype__doc__,
-"HeapDocCType(arg1, arg2)\n"
-"--\n"
-"\n"
-"somedoc");
-
-typedef struct {
- PyObject_HEAD
-} HeapDocCTypeObject;
-
-static PyType_Slot HeapDocCType_slots[] = {
- {Py_tp_doc, (char*)heapdocctype__doc__},
- {0},
-};
-
-static PyType_Spec HeapDocCType_spec = {
- "_testcapi.HeapDocCType",
- sizeof(HeapDocCTypeObject),
- 0,
- Py_TPFLAGS_DEFAULT,
- HeapDocCType_slots
-};
-
-typedef struct {
- PyObject_HEAD
-} HeapTypeNameObject;
-
-static PyType_Slot HeapTypeNameType_slots[] = {
- {0},
-};
-
-static PyType_Spec HeapTypeNameType_Spec = {
- .name = "_testcapi.HeapTypeNameType",
- .basicsize = sizeof(HeapTypeNameObject),
- .flags = Py_TPFLAGS_DEFAULT,
- .slots = HeapTypeNameType_slots,
-};
-
-typedef struct {
- PyObject_HEAD
-} NullTpDocTypeObject;
-
-static PyType_Slot NullTpDocType_slots[] = {
- {Py_tp_doc, NULL},
- {0, 0},
-};
-
-static PyType_Spec NullTpDocType_spec = {
- "_testcapi.NullTpDocType",
- sizeof(NullTpDocTypeObject),
- 0,
- Py_TPFLAGS_DEFAULT,
- NullTpDocType_slots
-};
-
-
-PyDoc_STRVAR(heapgctype__doc__,
-"A heap type with GC, and with overridden dealloc.\n\n"
-"The 'value' attribute is set to 10 in __init__.");
-
-typedef struct {
- PyObject_HEAD
- int value;
-} HeapCTypeObject;
-
-static struct PyMemberDef heapctype_members[] = {
- {"value", T_INT, offsetof(HeapCTypeObject, value)},
- {NULL} /* Sentinel */
-};
-
-static int
-heapctype_init(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- ((HeapCTypeObject *)self)->value = 10;
- return 0;
-}
-
-static int
-heapgcctype_traverse(HeapCTypeObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(Py_TYPE(self));
- return 0;
-}
-
-static void
-heapgcctype_dealloc(HeapCTypeObject *self)
-{
- PyTypeObject *tp = Py_TYPE(self);
- PyObject_GC_UnTrack(self);
- PyObject_GC_Del(self);
- Py_DECREF(tp);
-}
-
-static PyType_Slot HeapGcCType_slots[] = {
- {Py_tp_init, heapctype_init},
- {Py_tp_members, heapctype_members},
- {Py_tp_dealloc, heapgcctype_dealloc},
- {Py_tp_traverse, heapgcctype_traverse},
- {Py_tp_doc, (char*)heapgctype__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapGcCType_spec = {
- "_testcapi.HeapGcCType",
- sizeof(HeapCTypeObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- HeapGcCType_slots
-};
-
-PyDoc_STRVAR(heapctype__doc__,
-"A heap type without GC, but with overridden dealloc.\n\n"
-"The 'value' attribute is set to 10 in __init__.");
-
-static void
-heapctype_dealloc(HeapCTypeObject *self)
-{
- PyTypeObject *tp = Py_TYPE(self);
- PyObject_Free(self);
- Py_DECREF(tp);
-}
-
-static PyType_Slot HeapCType_slots[] = {
- {Py_tp_init, heapctype_init},
- {Py_tp_members, heapctype_members},
- {Py_tp_dealloc, heapctype_dealloc},
- {Py_tp_doc, (char*)heapctype__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapCType_spec = {
- "_testcapi.HeapCType",
- sizeof(HeapCTypeObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCType_slots
-};
-
-PyDoc_STRVAR(heapctypesubclass__doc__,
-"Subclass of HeapCType, without GC.\n\n"
-"__init__ sets the 'value' attribute to 10 and 'value2' to 20.");
-
-typedef struct {
- HeapCTypeObject base;
- int value2;
-} HeapCTypeSubclassObject;
-
-static int
-heapctypesubclass_init(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- /* Call __init__ of the superclass */
- if (heapctype_init(self, args, kwargs) < 0) {
- return -1;
- }
- /* Initialize additional element */
- ((HeapCTypeSubclassObject *)self)->value2 = 20;
- return 0;
-}
-
-static struct PyMemberDef heapctypesubclass_members[] = {
- {"value2", T_INT, offsetof(HeapCTypeSubclassObject, value2)},
- {NULL} /* Sentinel */
-};
-
-static PyType_Slot HeapCTypeSubclass_slots[] = {
- {Py_tp_init, heapctypesubclass_init},
- {Py_tp_members, heapctypesubclass_members},
- {Py_tp_doc, (char*)heapctypesubclass__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeSubclass_spec = {
- "_testcapi.HeapCTypeSubclass",
- sizeof(HeapCTypeSubclassObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeSubclass_slots
-};
-
-PyDoc_STRVAR(heapctypewithbuffer__doc__,
-"Heap type with buffer support.\n\n"
-"The buffer is set to [b'1', b'2', b'3', b'4']");
-
-typedef struct {
- HeapCTypeObject base;
- char buffer[4];
-} HeapCTypeWithBufferObject;
-
-static int
-heapctypewithbuffer_getbuffer(HeapCTypeWithBufferObject *self, Py_buffer *view, int flags)
-{
- self->buffer[0] = '1';
- self->buffer[1] = '2';
- self->buffer[2] = '3';
- self->buffer[3] = '4';
- return PyBuffer_FillInfo(
- view, (PyObject*)self, (void *)self->buffer, 4, 1, flags);
-}
-
-static void
-heapctypewithbuffer_releasebuffer(HeapCTypeWithBufferObject *self, Py_buffer *view)
-{
- assert(view->obj == (void*) self);
-}
-
-static PyType_Slot HeapCTypeWithBuffer_slots[] = {
- {Py_bf_getbuffer, heapctypewithbuffer_getbuffer},
- {Py_bf_releasebuffer, heapctypewithbuffer_releasebuffer},
- {Py_tp_doc, (char*)heapctypewithbuffer__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeWithBuffer_spec = {
- "_testcapi.HeapCTypeWithBuffer",
- sizeof(HeapCTypeWithBufferObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeWithBuffer_slots
-};
-
-PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__,
-"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n"
-"__class__ is set to plain HeapCTypeSubclass during finalization.\n"
-"__init__ sets the 'value' attribute to 10 and 'value2' to 20.");
-
-static int
-heapctypesubclasswithfinalizer_init(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- PyTypeObject *base = (PyTypeObject *)PyType_GetSlot(Py_TYPE(self), Py_tp_base);
- initproc base_init = PyType_GetSlot(base, Py_tp_init);
- base_init(self, args, kwargs);
- return 0;
-}
-
-static void
-heapctypesubclasswithfinalizer_finalize(PyObject *self)
-{
- PyObject *error_type, *error_value, *error_traceback, *m;
- PyObject *oldtype = NULL, *newtype = NULL, *refcnt = NULL;
-
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- m = PyState_FindModule(&_testcapimodule);
- if (m == NULL) {
- goto cleanup_finalize;
- }
- oldtype = PyObject_GetAttrString(m, "HeapCTypeSubclassWithFinalizer");
- newtype = PyObject_GetAttrString(m, "HeapCTypeSubclass");
- if (oldtype == NULL || newtype == NULL) {
- goto cleanup_finalize;
- }
-
- if (PyObject_SetAttrString(self, "__class__", newtype) < 0) {
- goto cleanup_finalize;
- }
- refcnt = PyLong_FromSsize_t(Py_REFCNT(oldtype));
- if (refcnt == NULL) {
- goto cleanup_finalize;
- }
- if (PyObject_SetAttrString(oldtype, "refcnt_in_del", refcnt) < 0) {
- goto cleanup_finalize;
- }
- Py_DECREF(refcnt);
- refcnt = PyLong_FromSsize_t(Py_REFCNT(newtype));
- if (refcnt == NULL) {
- goto cleanup_finalize;
- }
- if (PyObject_SetAttrString(newtype, "refcnt_in_del", refcnt) < 0) {
- goto cleanup_finalize;
- }
-
-cleanup_finalize:
- Py_XDECREF(oldtype);
- Py_XDECREF(newtype);
- Py_XDECREF(refcnt);
-
- /* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
-}
-
-static PyType_Slot HeapCTypeSubclassWithFinalizer_slots[] = {
- {Py_tp_init, heapctypesubclasswithfinalizer_init},
- {Py_tp_members, heapctypesubclass_members},
- {Py_tp_finalize, heapctypesubclasswithfinalizer_finalize},
- {Py_tp_doc, (char*)heapctypesubclasswithfinalizer__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeSubclassWithFinalizer_spec = {
- "_testcapi.HeapCTypeSubclassWithFinalizer",
- sizeof(HeapCTypeSubclassObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
- HeapCTypeSubclassWithFinalizer_slots
-};
-
-static PyType_Slot HeapCTypeMetaclass_slots[] = {
- {0},
-};
-
-static PyType_Spec HeapCTypeMetaclass_spec = {
- "_testcapi.HeapCTypeMetaclass",
- sizeof(PyHeapTypeObject),
- sizeof(PyMemberDef),
- Py_TPFLAGS_DEFAULT,
- HeapCTypeMetaclass_slots
-};
-
-static PyObject *
-heap_ctype_metaclass_custom_tp_new(PyTypeObject *tp, PyObject *args, PyObject *kwargs)
-{
- return PyType_Type.tp_new(tp, args, kwargs);
-}
-
-static PyType_Slot HeapCTypeMetaclassCustomNew_slots[] = {
- { Py_tp_new, heap_ctype_metaclass_custom_tp_new },
- {0},
-};
-
-static PyType_Spec HeapCTypeMetaclassCustomNew_spec = {
- "_testcapi.HeapCTypeMetaclassCustomNew",
- sizeof(PyHeapTypeObject),
- sizeof(PyMemberDef),
- Py_TPFLAGS_DEFAULT,
- HeapCTypeMetaclassCustomNew_slots
-};
-
-
-typedef struct {
- PyObject_HEAD
- PyObject *dict;
-} HeapCTypeWithDictObject;
-
-static void
-heapctypewithdict_dealloc(HeapCTypeWithDictObject* self)
-{
-
- PyTypeObject *tp = Py_TYPE(self);
- Py_XDECREF(self->dict);
- PyObject_Free(self);
- Py_DECREF(tp);
-}
-
-static PyGetSetDef heapctypewithdict_getsetlist[] = {
- {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
- {NULL} /* Sentinel */
-};
-
-static struct PyMemberDef heapctypewithdict_members[] = {
- {"dictobj", T_OBJECT, offsetof(HeapCTypeWithDictObject, dict)},
- {"__dictoffset__", T_PYSSIZET, offsetof(HeapCTypeWithDictObject, dict), READONLY},
- {NULL} /* Sentinel */
-};
-
-static PyType_Slot HeapCTypeWithDict_slots[] = {
- {Py_tp_members, heapctypewithdict_members},
- {Py_tp_getset, heapctypewithdict_getsetlist},
- {Py_tp_dealloc, heapctypewithdict_dealloc},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeWithDict_spec = {
- "_testcapi.HeapCTypeWithDict",
- sizeof(HeapCTypeWithDictObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeWithDict_slots
-};
-
-static struct PyMemberDef heapctypewithnegativedict_members[] = {
- {"dictobj", T_OBJECT, offsetof(HeapCTypeWithDictObject, dict)},
- {"__dictoffset__", T_PYSSIZET, -(Py_ssize_t)sizeof(void*), READONLY},
- {NULL} /* Sentinel */
-};
-
-static PyType_Slot HeapCTypeWithNegativeDict_slots[] = {
- {Py_tp_members, heapctypewithnegativedict_members},
- {Py_tp_getset, heapctypewithdict_getsetlist},
- {Py_tp_dealloc, heapctypewithdict_dealloc},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeWithNegativeDict_spec = {
- "_testcapi.HeapCTypeWithNegativeDict",
- sizeof(HeapCTypeWithDictObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeWithNegativeDict_slots
-};
-
-typedef struct {
- PyObject_HEAD
- PyObject *weakreflist;
-} HeapCTypeWithWeakrefObject;
-
-static struct PyMemberDef heapctypewithweakref_members[] = {
- {"weakreflist", T_OBJECT, offsetof(HeapCTypeWithWeakrefObject, weakreflist)},
- {"__weaklistoffset__", T_PYSSIZET,
- offsetof(HeapCTypeWithWeakrefObject, weakreflist), READONLY},
- {NULL} /* Sentinel */
-};
-
-static void
-heapctypewithweakref_dealloc(HeapCTypeWithWeakrefObject* self)
-{
-
- PyTypeObject *tp = Py_TYPE(self);
- if (self->weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) self);
- Py_XDECREF(self->weakreflist);
- PyObject_Free(self);
- Py_DECREF(tp);
-}
-
-static PyType_Slot HeapCTypeWithWeakref_slots[] = {
- {Py_tp_members, heapctypewithweakref_members},
- {Py_tp_dealloc, heapctypewithweakref_dealloc},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeWithWeakref_spec = {
- "_testcapi.HeapCTypeWithWeakref",
- sizeof(HeapCTypeWithWeakrefObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeWithWeakref_slots
-};
-
-PyDoc_STRVAR(heapctypesetattr__doc__,
-"A heap type without GC, but with overridden __setattr__.\n\n"
-"The 'value' attribute is set to 10 in __init__ and updated via attribute setting.");
-
-typedef struct {
- PyObject_HEAD
- long value;
-} HeapCTypeSetattrObject;
-
-static struct PyMemberDef heapctypesetattr_members[] = {
- {"pvalue", T_LONG, offsetof(HeapCTypeSetattrObject, value)},
- {NULL} /* Sentinel */
-};
-
-static int
-heapctypesetattr_init(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- ((HeapCTypeSetattrObject *)self)->value = 10;
- return 0;
-}
-
-static void
-heapctypesetattr_dealloc(HeapCTypeSetattrObject *self)
-{
- PyTypeObject *tp = Py_TYPE(self);
- PyObject_Free(self);
- Py_DECREF(tp);
-}
-
-static int
-heapctypesetattr_setattro(HeapCTypeSetattrObject *self, PyObject *attr, PyObject *value)
-{
- PyObject *svalue = PyUnicode_FromString("value");
- if (svalue == NULL)
- return -1;
- int eq = PyObject_RichCompareBool(svalue, attr, Py_EQ);
- Py_DECREF(svalue);
- if (eq < 0)
- return -1;
- if (!eq) {
- return PyObject_GenericSetAttr((PyObject*) self, attr, value);
- }
- if (value == NULL) {
- self->value = 0;
- return 0;
- }
- PyObject *ivalue = PyNumber_Long(value);
- if (ivalue == NULL)
- return -1;
- long v = PyLong_AsLong(ivalue);
- Py_DECREF(ivalue);
- if (v == -1 && PyErr_Occurred())
- return -1;
- self->value = v;
- return 0;
-}
-
-static PyType_Slot HeapCTypeSetattr_slots[] = {
- {Py_tp_init, heapctypesetattr_init},
- {Py_tp_members, heapctypesetattr_members},
- {Py_tp_setattro, heapctypesetattr_setattro},
- {Py_tp_dealloc, heapctypesetattr_dealloc},
- {Py_tp_doc, (char*)heapctypesetattr__doc__},
- {0, 0},
-};
-
-static PyType_Spec HeapCTypeSetattr_spec = {
- "_testcapi.HeapCTypeSetattr",
- sizeof(HeapCTypeSetattrObject),
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- HeapCTypeSetattr_slots
-};
-
static PyMethodDef meth_instance_methods[] = {
{"meth_varargs", meth_varargs, METH_VARARGS},
{"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS},
@@ -7656,97 +6795,6 @@ PyInit__testcapi(void)
Py_INCREF(TestError);
PyModule_AddObject(m, "error", TestError);
- PyObject *HeapDocCType = PyType_FromSpec(&HeapDocCType_spec);
- if (HeapDocCType == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapDocCType", HeapDocCType);
-
- /* bpo-41832: Add a new type to test PyType_FromSpec()
- now can accept a NULL tp_doc slot. */
- PyObject *NullTpDocType = PyType_FromSpec(&NullTpDocType_spec);
- if (NullTpDocType == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "NullTpDocType", NullTpDocType);
-
- PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec);
- if (HeapGcCType == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapGcCType", HeapGcCType);
-
- PyObject *HeapCType = PyType_FromSpec(&HeapCType_spec);
- if (HeapCType == NULL) {
- return NULL;
- }
- PyObject *subclass_bases = PyTuple_Pack(1, HeapCType);
- if (subclass_bases == NULL) {
- return NULL;
- }
- PyObject *HeapCTypeSubclass = PyType_FromSpecWithBases(&HeapCTypeSubclass_spec, subclass_bases);
- if (HeapCTypeSubclass == NULL) {
- return NULL;
- }
- Py_DECREF(subclass_bases);
- PyModule_AddObject(m, "HeapCTypeSubclass", HeapCTypeSubclass);
-
- PyObject *HeapCTypeWithDict = PyType_FromSpec(&HeapCTypeWithDict_spec);
- if (HeapCTypeWithDict == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeWithDict", HeapCTypeWithDict);
-
- PyObject *HeapCTypeWithNegativeDict = PyType_FromSpec(&HeapCTypeWithNegativeDict_spec);
- if (HeapCTypeWithNegativeDict == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeWithNegativeDict", HeapCTypeWithNegativeDict);
-
- PyObject *HeapCTypeWithWeakref = PyType_FromSpec(&HeapCTypeWithWeakref_spec);
- if (HeapCTypeWithWeakref == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeWithWeakref", HeapCTypeWithWeakref);
-
- PyObject *HeapCTypeWithBuffer = PyType_FromSpec(&HeapCTypeWithBuffer_spec);
- if (HeapCTypeWithBuffer == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeWithBuffer", HeapCTypeWithBuffer);
-
- PyObject *HeapCTypeSetattr = PyType_FromSpec(&HeapCTypeSetattr_spec);
- if (HeapCTypeSetattr == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeSetattr", HeapCTypeSetattr);
-
- PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass);
- if (subclass_with_finalizer_bases == NULL) {
- return NULL;
- }
- PyObject *HeapCTypeSubclassWithFinalizer = PyType_FromSpecWithBases(
- &HeapCTypeSubclassWithFinalizer_spec, subclass_with_finalizer_bases);
- if (HeapCTypeSubclassWithFinalizer == NULL) {
- return NULL;
- }
- Py_DECREF(subclass_with_finalizer_bases);
- PyModule_AddObject(m, "HeapCTypeSubclassWithFinalizer", HeapCTypeSubclassWithFinalizer);
-
- PyObject *HeapCTypeMetaclass = PyType_FromMetaclass(
- &PyType_Type, m, &HeapCTypeMetaclass_spec, (PyObject *) &PyType_Type);
- if (HeapCTypeMetaclass == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeMetaclass", HeapCTypeMetaclass);
-
- PyObject *HeapCTypeMetaclassCustomNew = PyType_FromMetaclass(
- &PyType_Type, m, &HeapCTypeMetaclassCustomNew_spec, (PyObject *) &PyType_Type);
- if (HeapCTypeMetaclassCustomNew == NULL) {
- return NULL;
- }
- PyModule_AddObject(m, "HeapCTypeMetaclassCustomNew", HeapCTypeMetaclassCustomNew);
-
if (PyType_Ready(&ContainerNoGC_type) < 0) {
return NULL;
}
@@ -7759,17 +6807,14 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_Vectorcall(m) < 0) {
return NULL;
}
+ if (_PyTestCapi_Init_Heaptype(m) < 0) {
+ return NULL;
+ }
PyState_AddModule(m, &_testcapimodule);
return m;
}
-static PyObject *
-negative_dictoffset(PyObject *self, PyObject *Py_UNUSED(ignored))
-{
- return PyType_FromSpec(&HeapCTypeWithNegativeDict_spec);
-}
-
/* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */
#undef Py_BuildValue