Author: Maciej Fijalkowski <fij...@gmail.com>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to