[pypy-commit] pypy py3.5: test and fix

arigo pypy.commits at gmail.com
Tue Jan 10 04:57:24 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r89466:9124eb47aa9d
Date: 2017-01-10 10:56 +0100
http://bitbucket.org/pypy/pypy/changeset/9124eb47aa9d/

Log:	test and fix

diff --git a/pypy/objspace/std/objectobject.py b/pypy/objspace/std/objectobject.py
--- a/pypy/objspace/std/objectobject.py
+++ b/pypy/objspace/std/objectobject.py
@@ -18,25 +18,6 @@
     import copyreg
     return copyreg._reduce_ex(obj, proto)
 
-def _getnewargs(obj):
-
-    try:
-        getnewargs = obj.__getnewargs_ex__
-    except AttributeError:
-        try:
-            getnewargs = obj.__getnewargs__
-        except AttributeError:
-            args = ()
-        else:
-            args = getnewargs()
-        kwargs = None
-    else:
-        args, kwargs = getnewargs()
-
-    if not isinstance(args, tuple):
-        raise TypeError("__getnewargs__ should return a tuple")
-    return args, kwargs
-
 def _getstate(obj):
     cls = obj.__class__
 
@@ -60,13 +41,13 @@
         state = getstate()
     return state
 
-def reduce_2(obj, proto):
+def reduce_2(obj, proto, args, kwargs):
     cls = obj.__class__
 
     import copyreg
 
-    args, kwargs = _getnewargs(obj)
-
+    if not isinstance(args, tuple):
+        raise TypeError("__getnewargs__ should return a tuple")
     if not kwargs:
        newobj = copyreg.__newobj__
        args2 = (cls,) + args
@@ -187,7 +168,18 @@
 def descr__reduce__(space, w_obj, proto=0):
     w_proto = space.wrap(proto)
     if proto >= 2:
-        return reduce_2(space, w_obj, w_proto)
+        w_descr = space.lookup(w_obj, '__getnewargs_ex__')
+        if w_descr is not None:
+            w_result = space.get_and_call_function(w_descr, w_obj)
+            w_args, w_kwargs = space.fixedview(w_result, 2)
+        else:
+            w_descr = space.lookup(w_obj, '__getnewargs__')
+            if w_descr is not None:
+                w_args = space.get_and_call_function(w_descr, w_obj)
+            else:
+                w_args = space.newtuple([])
+            w_kwargs = space.w_None
+        return reduce_2(space, w_obj, w_proto, w_args, w_kwargs)
     return reduce_1(space, w_obj, w_proto)
 
 @unwrap_spec(proto=int)
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -75,6 +75,20 @@
             (NamedInt, ('Name',), dict(value=42)),
             dict(_name='Name'), None, None)
 
+    def test_reduce_ex_does_getattr(self):
+        seen = []
+        class X:
+            def __getattribute__(self, name):
+                seen.append(name)
+                return object.__getattribute__(self, name)
+        X().__reduce_ex__(2)
+        # it is the case at least on CPython 3.5.2, like PyPy:
+        assert '__reduce__' in seen
+        # but these methods, which are also called, are not looked up
+        # with getattr:
+        assert '__getnewargs__' not in seen
+        assert '__getnewargs_ex__' not in seen
+
     def test_default_format(self):
         class x(object):
             def __str__(self):


More information about the pypy-commit mailing list