summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapimodule.c
diff options
context:
space:
mode:
authorscoder <stefan_ml@behnel.de>2020-07-03 00:09:28 (GMT)
committerGitHub <noreply@github.com>2020-07-03 00:09:28 (GMT)
commit148f32913573c29250dfb3f0d079eb8847633621 (patch)
treec13dbb1fa7eb316f45374b3972396619a2a7145c /Modules/_testcapimodule.c
parent67673b08ea302174ca9c6559c04311550ae9f189 (diff)
downloadcpython-148f32913573c29250dfb3f0d079eb8847633621.zip
cpython-148f32913573c29250dfb3f0d079eb8847633621.tar.gz
cpython-148f32913573c29250dfb3f0d079eb8847633621.tar.bz2
bpo-39960: Allow heap types in the "Carlo Verre" hack check that override "tp_setattro()" (GH-21092)
Automerge-Triggered-By: @gvanrossum
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r--Modules/_testcapimodule.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index aafbc39..629102b 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -6528,6 +6528,80 @@ static PyType_Spec HeapCTypeWithWeakref_spec = {
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_Del(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)(void(*)(void))meth_varargs_keywords, METH_VARARGS|METH_KEYWORDS},
@@ -6834,6 +6908,12 @@ PyInit__testcapi(void)
}
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;