Mercurial > cpython
changeset 89219:b328f8ccbccf
look up __getnewargs__ and __getnewargs_ex__ on the object type (#16251) [#16251]
| author | Benjamin Peterson <benjamin@python.org> |
|---|---|
| date | Sun, 16 Feb 2014 13:49:16 -0500 |
| parents | fb5f4cfc3230 |
| children | 52ab9e1ff46a |
| files | Lib/test/test_descr.py Misc/NEWS Objects/typeobject.c |
| diffstat | 3 files changed, 23 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4701,6 +4701,20 @@ class PicklingTests(unittest.TestCase): for proto in protocols: self._check_reduce(proto, obj, listitems=list(obj)) + def test_special_method_lookup(self): + protocols = range(pickle.HIGHEST_PROTOCOL + 1) + class Picky: + def __getstate__(self): + return {} + + def __getattr__(self, attr): + if attr in ("__getnewargs__", "__getnewargs_ex__"): + raise AssertionError(attr) + return None + for protocol in protocols: + state = {} if protocol >= 2 else None + self._check_reduce(protocol, Picky(), state=state) + def _assert_is_copy(self, obj, objcopy, msg=None): """Utility method to verify if two objects are copies of each others. """
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: 2014-02-23 Core and Builtins ----------------- +- Issue #20261: In pickle, lookup __getnewargs__ and __getnewargs_ex__ on the + type of the object. + - Issue #20619: Give the AST nodes of keyword-only arguments a column and line number.
--- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3719,7 +3719,7 @@ Py_LOCAL(int) /* We first attempt to fetch the arguments for __new__ by calling __getnewargs_ex__ on the object. */ - getnewargs_ex = _PyObject_GetAttrId(obj, &PyId___getnewargs_ex__); + getnewargs_ex = _PyObject_LookupSpecial(obj, &PyId___getnewargs_ex__); if (getnewargs_ex != NULL) { PyObject *newargs = PyObject_CallObject(getnewargs_ex, NULL); Py_DECREF(getnewargs_ex); @@ -3766,16 +3766,13 @@ Py_LOCAL(int) return -1; } return 0; - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return -1; - } - PyErr_Clear(); + } else if (PyErr_Occurred()) { + return -1; } /* The object does not have __getnewargs_ex__ so we fallback on using __getnewargs__ instead. */ - getnewargs = _PyObject_GetAttrId(obj, &PyId___getnewargs__); + getnewargs = _PyObject_LookupSpecial(obj, &PyId___getnewargs__); if (getnewargs != NULL) { *args = PyObject_CallObject(getnewargs, NULL); Py_DECREF(getnewargs); @@ -3791,11 +3788,8 @@ Py_LOCAL(int) } *kwargs = NULL; return 0; - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return -1; - } - PyErr_Clear(); + } else if (PyErr_Occurred()) { + return -1; } /* The object does not have __getnewargs_ex__ and __getnewargs__. This may
