Author: Maciej Fijalkowski <[email protected]>
Branch:
Changeset: r81432:d5545deb980c
Date: 2015-12-23 09:25 +0200
http://bitbucket.org/pypy/pypy/changeset/d5545deb980c/
Log: Merged in yufeiz/pypy-tp_getattro (pull request #384)
Expose different tp_getattro slots for different builtin types
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -380,6 +380,17 @@
space.call_function(delattr_fn, w_self, w_name)
return 0
api_func = slot_tp_setattro.api_func
+ elif name == 'tp_getattro':
+ getattr_fn = w_type.getdictvalue(space, '__getattribute__')
+ if getattr_fn is None:
+ return
+
+ @cpython_api([PyObject, PyObject], PyObject,
+ error=lltype.nullptr(rffi.VOIDP.TO), external=True)
+ @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
+ def slot_tp_getattro(space, w_self, w_name):
+ return space.call_function(getattr_fn, w_self, w_name)
+ api_func = slot_tp_getattro.api_func
else:
return
diff --git a/pypy/module/cpyext/test/test_typeobject.py
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -385,12 +385,53 @@
PyErr_SetString(PyExc_ValueError, "recursive
tp_setattro");
return NULL;
}
+ if (!args->ob_type->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
+ return NULL;
+ }
+ if (args->ob_type->tp_getattro ==
+ args->ob_type->tp_base->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "recursive
tp_getattro");
+ return NULL;
+ }
Py_RETURN_TRUE;
'''
)
])
assert module.test_type(type(None))
+ def test_tp_getattro(self):
+ module = self.import_extension('foo', [
+ ("test_tp_getattro", "METH_VARARGS",
+ '''
+ PyObject *obj = PyTuple_GET_ITEM(args, 0);
+ PyIntObject *value = PyTuple_GET_ITEM(args, 1);
+ if (!obj->ob_type->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
+ return NULL;
+ }
+ PyObject *name = PyString_FromString("attr1");
+ PyIntObject *attr1 = obj->ob_type->tp_getattro(obj, name);
+ if (attr1->ob_ival != value->ob_ival)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "tp_getattro returned wrong value");
+ return NULL;
+ }
+ Py_DECREF(name);
+ Py_DECREF(attr1);
+ Py_RETURN_TRUE;
+ '''
+ )
+ ])
+ class C:
+ def __init__(self):
+ self.attr1 = 123
+ assert module.test_tp_getattro(C(), 123)
+
def test_nb_int(self):
module = self.import_extension('foo', [
("nb_int", "METH_O",
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -582,6 +582,8 @@
pto.c_tp_free = base.c_tp_free
if not pto.c_tp_setattro:
pto.c_tp_setattro = base.c_tp_setattro
+ if not pto.c_tp_getattro:
+ pto.c_tp_getattro = base.c_tp_getattro
finally:
Py_DecRef(space, base_pyo)
@@ -651,6 +653,12 @@
PyObject_GenericSetAttr.api_func.functype,
PyObject_GenericSetAttr.api_func.get_wrapper(space))
+ if not pto.c_tp_getattro:
+ from pypy.module.cpyext.object import PyObject_GenericGetAttr
+ pto.c_tp_getattro = llhelper(
+ PyObject_GenericGetAttr.api_func.functype,
+ PyObject_GenericGetAttr.api_func.get_wrapper(space))
+
if w_obj.is_cpytype():
Py_DecRef(space, pto.c_tp_dict)
w_dict = w_obj.getdict(space)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit