[pypy-commit] pypy default: tp_descr_get on built-in types

arigo pypy.commits at gmail.com
Mon Jun 5 05:51:23 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r91520:4a138a88b24a
Date: 2017-06-05 11:26 +0200
http://bitbucket.org/pypy/pypy/changeset/4a138a88b24a/

Log:	tp_descr_get on built-in 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
@@ -820,6 +820,18 @@
         else:
             return
         slot_func = buff_w
+    elif name == 'tp_descr_get':
+        get_fn = w_type.getdictvalue(space, '__get__')
+        if get_fn is None:
+            return
+
+        @slot_function([PyObject, PyObject, PyObject], PyObject)
+        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+        def slot_tp_descr_get(space, w_self, w_arg1, w_arg2):
+            if w_arg1 is None:
+                w_arg1 = space.w_None
+            return space.call_function(get_fn, w_self, w_arg1, w_arg2)
+        slot_func = slot_tp_descr_get
     else:
         # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
         # tp_as_sequence.c_sq_contains, tp_as_sequence.c_sq_length
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
@@ -392,6 +392,37 @@
         obj = foo.new()
         assert module.hack_tp_dict(obj) == 2
 
+    def test_tp_descr_get(self):
+        module = self.import_extension('foo', [
+           ("tp_descr_get", "METH_O",
+            '''
+                if (args->ob_type->tp_descr_get == NULL) {
+                    Py_INCREF(Py_False);
+                    return Py_False;
+                }
+                return args->ob_type->tp_descr_get(args, NULL,
+                                                   (PyObject *)&PyInt_Type);
+             '''
+             )
+            ])
+        assert module.tp_descr_get(42) is False
+
+        class Y(object):
+            def __get__(self, *args):
+                return 42
+            def unbound_method_example(self):
+                pass
+        assert module.tp_descr_get(Y()) == 42
+        #
+        p = property(lambda self: 42)
+        result = module.tp_descr_get(p)
+        assert result is p
+        #
+        f = lambda x: x + 1
+        ubm = module.tp_descr_get(f)
+        assert type(ubm) is type(Y.unbound_method_example)
+        assert ubm(42) == 43
+
 
 class TestTypes(BaseApiTest):
     def test_type_attributes(self, space, api):


More information about the pypy-commit mailing list