[pypy-commit] pypy py3.5: hg merge default

arigo pypy.commits at gmail.com
Mon Aug 14 13:24:08 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r92149:90985eb27be1
Date: 2017-08-14 19:23 +0200
http://bitbucket.org/pypy/pypy/changeset/90985eb27be1/

Log:	hg merge default

diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -21,24 +21,31 @@
 
         if space.is_none(w_obj_or_type):
             w_type = None  # unbound super object
-            w_obj_or_type = space.w_None
+            w_obj_or_type = None
         else:
             w_type = _super_check(space, w_starttype, w_obj_or_type)
         self.w_starttype = w_starttype
         self.w_objtype = w_type
-        self.w_self = w_obj_or_type
+        self.w_self = w_obj_or_type      # may be None
 
     def descr_repr(self, space):
         if self.w_objtype is not None:
             objtype_name = u"<%s object>" % self.w_objtype.getname(space)
         else:
             objtype_name = u'NULL'
+        if self.w_starttype is not None:
+            starttype_name = self.w_starttype.getname(space)
+        else:
+            starttype_name = u'NULL'
         return space.newunicode(u"<super: <class '%s'>, %s>" % (
-            self.w_starttype.getname(space), objtype_name))
+            starttype_name, objtype_name))
 
     def get(self, space, w_obj, w_type=None):
-        if self.w_self is None or space.is_w(w_obj, space.w_None):
+        if self.w_self is not None or space.is_w(w_obj, space.w_None):
             return self
+        if self.w_starttype is None:
+            raise oefmt(space.w_TypeError,
+                "__get__(x) is invalid on an uninitialized instance of 'super'")
         else:
             # if type(self) is W_Super:
             #     XXX write a fast path for this common case
@@ -50,6 +57,7 @@
         # only use a special logic for bound super objects and not for
         # getting the __class__ of the super object itself.
         if self.w_objtype is not None and name != '__class__':
+            assert self.w_starttype is not None
             w_value = space.lookup_in_type_starting_at(self.w_objtype,
                                                        self.w_starttype,
                                                        name)
@@ -59,10 +67,9 @@
                     return w_value
                 # Only pass 'obj' param if this is instance-mode super
                 # (see CPython sourceforge id #743627)
-                if self.w_self is self.w_objtype:
+                w_obj = self.w_self
+                if w_obj is None or w_obj is self.w_objtype:
                     w_obj = space.w_None
-                else:
-                    w_obj = self.w_self
                 return space.get_and_call_function(w_get, w_value,
                                                    w_obj, self.w_objtype)
         # fallback to object.__getattribute__()
@@ -160,7 +167,11 @@
     _immutable_fields_ = ["w_fget", "w_fset", "w_fdel"]
 
     def __init__(self, space):
-        pass
+        self.w_fget = space.w_None
+        self.w_fset = space.w_None
+        self.w_fdel = space.w_None
+        self.w_doc = space.w_None
+        self.getter_doc = False
 
     @unwrap_spec(w_fget=WrappedDefault(None),
                  w_fset=WrappedDefault(None),
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -333,6 +333,22 @@
         assert repr(A()).endswith('>!')
         assert repr(super(A, A())) == "<super: <class 'A'>, <A object>>"
 
+    def test_super_get_corner_case(self):
+        class A(object):
+            pass
+        s1 = super(A, A())
+        assert s1.__get__(42) is s1
+        assert s1.__get__(42, int) is s1
+        s2 = super(A)
+        assert s2.__get__(None, "anything") is s2
+        #
+        assert s1.__get__(None, "anything") is s1
+        raises(TypeError, s2.__get__, 42)
+        raises(TypeError, s2.__get__, 42, int)
+        a = A()
+        assert s2.__get__(a).__self__ is a
+        assert s1.__get__(a) is s1
+
     def test_property_docstring(self):
         assert property.__doc__.startswith('property')
 
@@ -520,3 +536,35 @@
                 super()
         raises(RuntimeError, X().f)
         """
+
+    def test_uninitialized_property(self):
+        p = property.__new__(property)
+        raises(AttributeError, p.__get__, 42)
+        raises(AttributeError, p.__set__, 42, None)
+        raises(AttributeError, p.__delete__, 42)
+        assert repr(p).startswith("<property object at ")
+        assert p.fget is p.fset is p.fdel is p.__doc__ is None
+        #
+        lst = []
+        p.deleter(lst.append).__delete__(42)
+        assert lst == [42]
+        #
+        lst = []
+        p.getter(lst.append).__get__(43)
+        assert lst == [43]
+        #
+        lst = []
+        p.setter(lambda x, y: lst.append((x, y))).__set__(44, 45)
+        assert lst == [(44, 45)]
+
+    def test_uninitialized_super(self):
+        s = super.__new__(super)
+        assert repr(s) == "<super: <class 'NULL'>, NULL>"
+        assert s.__thisclass__ is s.__self__ is s.__self_class__ is None
+        assert s.__get__(None, "anything") is s
+        raises(TypeError, s.__get__, 42)
+        raises(TypeError, s.__get__, int)
+        raises(TypeError, s.__get__, type(None))
+        raises(AttributeError, "s.abcde")
+        raises(AttributeError, "s.abcde = 42")
+        raises(AttributeError, "del s.abcde")


More information about the pypy-commit mailing list