[pypy-commit] pypy default: tp_descr_set on built-in types
arigo
pypy.commits at gmail.com
Mon Jun 5 05:51:25 EDT 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r91521:7ca42aeab616
Date: 2017-06-05 11:42 +0200
http://bitbucket.org/pypy/pypy/changeset/7ca42aeab616/
Log: tp_descr_set 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
@@ -827,11 +827,32 @@
@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)
+ def slot_tp_descr_get(space, w_self, w_obj, w_value):
+ if w_obj is None:
+ w_obj = space.w_None
+ return space.call_function(get_fn, w_self, w_obj, w_value)
slot_func = slot_tp_descr_get
+ elif name == 'tp_descr_set':
+ set_fn = w_type.getdictvalue(space, '__set__')
+ delete_fn = w_type.getdictvalue(space, '__delete__')
+ if set_fn is None and delete_fn is None:
+ return
+
+ @slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
+ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+ def slot_tp_descr_set(space, w_self, w_obj, w_value):
+ if w_value is not None:
+ if set_fn is None:
+ raise oefmt(space.w_TypeError,
+ "%s object has no __set__", typedef.name)
+ space.call_function(set_fn, w_self, w_obj, w_value)
+ else:
+ if delete_fn is None:
+ raise oefmt(space.w_TypeError,
+ "%s object has no __delete__", typedef.name)
+ space.call_function(delete_fn, w_self, w_obj)
+ return 0
+ slot_func = slot_tp_descr_set
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
@@ -423,6 +423,42 @@
assert type(ubm) is type(Y.unbound_method_example)
assert ubm(42) == 43
+ def test_tp_descr_set(self):
+ module = self.import_extension('foo', [
+ ("tp_descr_set", "METH_O",
+ '''
+ if (args->ob_type->tp_descr_set == NULL) {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+ if (args->ob_type->tp_descr_set(args, Py_False, Py_True) != 0)
+ return NULL;
+ if (args->ob_type->tp_descr_set(args, Py_Ellipsis, NULL) != 0)
+ return NULL;
+
+ Py_INCREF(Py_True);
+ return Py_True;
+ '''
+ )
+ ])
+ assert module.tp_descr_set(42) is False
+
+ class Y(object):
+ def __set__(self, obj, value):
+ assert obj is False
+ assert value is True
+ def __delete__(self, obj):
+ assert obj is Ellipsis
+ assert module.tp_descr_set(Y()) is True
+ #
+ def pset(obj, value):
+ assert obj is False
+ assert value is True
+ def pdel(obj):
+ assert obj is Ellipsis
+ p = property(lambda: "never used", pset, pdel)
+ assert module.tp_descr_set(p) is True
+
class TestTypes(BaseApiTest):
def test_type_attributes(self, space, api):
More information about the pypy-commit
mailing list