]> granicus.if.org Git - python/commitdiff
look up __getnewargs__ and __getnewargs_ex__ on the object type (#16251)
authorBenjamin Peterson <benjamin@python.org>
Sun, 16 Feb 2014 18:49:16 +0000 (13:49 -0500)
committerBenjamin Peterson <benjamin@python.org>
Sun, 16 Feb 2014 18:49:16 +0000 (13:49 -0500)
Lib/test/test_descr.py
Misc/NEWS
Objects/typeobject.c

index 508e02bdaece61dbf3871b88c14ced5609e8af26..2a9e329633ed1ef8932b500bc0f88642948dd376 100644 (file)
@@ -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.
         """
index c23c35e679468736ddc72cf9d1570df45c57936a..ac082555c789dd5c777aafc3418e749781510188 100644 (file)
--- 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.
 
index 449b6d6895290f685d3778aa939253224f50668d..f58960d28cb4dcf7696788f5cde363a385bc203d 100644 (file)
@@ -3719,7 +3719,7 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
 
     /* 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 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
             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 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
         }
         *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