[pypy-commit] pypy default: Issue2033: A descriptor with __delete__ and no __get__ is also a data descriptor.

amauryfa noreply at buildbot.pypy.org
Mon Apr 20 00:35:54 CEST 2015


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r76839:e822667de276
Date: 2015-04-20 00:35 +0200
http://bitbucket.org/pypy/pypy/changeset/e822667de276/

Log:	Issue2033: A descriptor with __delete__ and no __get__ is also a
	data descriptor.

	(CPython has only slot for __get__ and __delete__: tp_descr_set)

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -129,7 +129,8 @@
     # This is meant to be a *mixin*.
 
     def is_data_descr(space, w_obj):
-        return space.lookup(w_obj, '__set__') is not None
+        return (space.lookup(w_obj, '__set__') is not None or
+                space.lookup(w_obj, '__delete__') is not None)
 
     def get_and_call_args(space, w_descr, w_obj, args):
         # a special case for performance and to avoid infinite recursion
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -607,6 +607,18 @@
 
         raises(AttributeError, lambda: A().a)
 
+    def test_delete_descriptor(self):
+        class Prop(object):
+            def __get__(self, obj, cls):
+                return 42
+            def __delete__(self, obj):
+                obj.deleted = True
+        class C(object):
+            x = Prop()
+        obj = C()
+        del obj.x
+        assert obj.deleted
+
     def test_non_callable(self):
         meth = classmethod(1).__get__(1)
         raises(TypeError, meth)


More information about the pypy-commit mailing list