Author: Armin Rigo <ar...@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): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit