Skip to content

Commit 240f0b1

Browse files
committed
Fix: wrap native descriptor get/set functions.
1 parent 49fa1f9 commit 240f0b1

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

graalpython/com.oracle.graal.python.cext/src/typeobject.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ static PyObject* wrap_setattrofunc(setattrofunc f, PyObject* obj, PyObject* key,
9595
return PyLong_FromLong(f(obj, key, item));
9696
}
9797

98+
/* Basically the same as 'wrap_setattrofunc' but has a different function type. */
99+
static PyObject* wrap_descrsetfunc(descrsetfunc f, PyObject* obj, PyObject* key, PyObject* item) {
100+
if(f(obj, key, item) < 0) {
101+
return NULL;
102+
}
103+
return Py_None;
104+
}
105+
106+
static PyObject* wrap_descrgetfunc(descrgetfunc f, PyObject* self, PyObject* obj, PyObject* type) {
107+
return native_to_java(f(self, obj, type));
108+
}
109+
98110
static PyObject* wrap_richcmpfunc(richcmpfunc f, PyObject* a, PyObject* b, PyObject* n) {
99111
return f(a, b, (int)PyLong_AsLong(n));
100112
}
@@ -424,8 +436,8 @@ int PyType_Ready(PyTypeObject* cls) {
424436
}
425437
ADD_SLOT("__iter__", cls->tp_iter, -1);
426438
ADD_SLOT("__next__", cls->tp_iternext, -1);
427-
ADD_SLOT("__get__", cls->tp_descr_get, -3);
428-
ADD_SLOT("__set__", cls->tp_descr_set, -3);
439+
ADD_SLOT_CONV("__get__", wrap_descrgetfunc, cls->tp_descr_get, -3);
440+
ADD_SLOT_CONV("__set__", wrap_descrsetfunc, cls->tp_descr_set, -3);
429441
ADD_SLOT_CONV("__init__", wrap_initproc, cls->tp_init, METH_KEYWORDS | METH_VARARGS);
430442
ADD_SLOT_CONV("__alloc__", wrap_allocfunc, cls->tp_alloc, -2);
431443
ADD_SLOT("__new__", cls->tp_new, METH_KEYWORDS | METH_VARARGS);

graalpython/com.oracle.graal.python.test/src/tests/cpyext/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,8 @@ def CPyExtType(name, code, **kwargs):
505505
0, /* tp_getset */
506506
{tp_base}, /* tp_base */
507507
{tp_dict}, /* tp_dict */
508-
0, /* tp_descr_get */
509-
0, /* tp_descr_set */
508+
{tp_descr_get}, /* tp_descr_get */
509+
{tp_descr_set}, /* tp_descr_set */
510510
{tp_dictoffset}, /* tp_dictoffset */
511511
{tp_init}, /* tp_init */
512512
PyType_GenericAlloc, /* tp_alloc */

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,33 @@ class TestCustomBasicsizeSubclass(TestCustomBasicsize):
315315
assert expected_basicsize == actual_basicsize, "expected = %s, actual = %s" % (expected_basicsize, actual_basicsize)
316316

317317

318+
def test_descrset(self):
319+
TestDescrSet = CPyExtType("TestDescrSet",
320+
'''
321+
int testdescr_set(PyObject* self, PyObject* key, PyObject* value) {
322+
Py_XDECREF(((TestDescrSetObject*)self)->payload);
323+
Py_XINCREF(value);
324+
((TestDescrSetObject*)self)->payload = value;
325+
return 0;
326+
}
327+
328+
PyObject* testdescr_get(PyObject* self, PyObject* key, PyObject* type) {
329+
return ((TestDescrSetObject*)self)->payload;
330+
}
331+
''',
332+
cmembers='PyObject* payload;',
333+
tp_descr_set="(descrsetfunc) testdescr_set",
334+
tp_descr_get="(descrgetfunc) testdescr_get",
335+
)
336+
337+
class Uff:
338+
hello = TestDescrSet()
339+
340+
obj = Uff()
341+
obj.hello = "world"
342+
assert obj.hello == "world", 'expected "world" but was %s' % obj.hello
343+
344+
318345
class TestObjectFunctions(CPyExtTestCase):
319346
def compile_module(self, name):
320347
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)

0 commit comments

Comments
 (0)