diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 92553e3573b..ced25f3fc44 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5236,7 +5236,20 @@ class PicklingTests(unittest.TestCase): import copyreg expected = (copyreg.__newobj__, (A,), (None, {'spam': 42}), None, None) - self.assertEqual(A().__reduce__(2), expected) # Shouldn't crash + self.assertEqual(A().__reduce_ex__(2), expected) # Shouldn't crash + + def test_object_reduce(self): + # Issue #29914 + # __reduce__() takes no arguments + object().__reduce__() + with self.assertRaises(TypeError): + object().__reduce__(0) + # __reduce_ex__() takes one integer argument + object().__reduce_ex__(0) + with self.assertRaises(TypeError): + object().__reduce_ex__() + with self.assertRaises(TypeError): + object().__reduce_ex__(None) class SharedKeyTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 396ada182e1..3caa1eb6e08 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- +- bpo-29914: Fixed default implementations of __reduce__ and __reduce_ex__(). + object.__reduce__() no longer takes arguments, object.__reduce_ex__() now + requires one argument. + - bpo-29949: Fix memory usage regression of set and frozenset object. - bpo-29935: Fixed error messages in the index() method of tuple, list and deque diff --git a/Objects/clinic/typeobject.c.h b/Objects/clinic/typeobject.c.h index 1b19ccf0615..2760065ef33 100644 --- a/Objects/clinic/typeobject.c.h +++ b/Objects/clinic/typeobject.c.h @@ -131,61 +131,42 @@ type___sizeof__(PyTypeObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(object___reduce____doc__, -"__reduce__($self, protocol=0, /)\n" +"__reduce__($self, /)\n" "--\n" "\n" "Helper for pickle."); #define OBJECT___REDUCE___METHODDEF \ - {"__reduce__", (PyCFunction)object___reduce__, METH_FASTCALL, object___reduce____doc__}, + {"__reduce__", (PyCFunction)object___reduce__, METH_NOARGS, object___reduce____doc__}, static PyObject * -object___reduce___impl(PyObject *self, int protocol); +object___reduce___impl(PyObject *self); static PyObject * -object___reduce__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +object___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *return_value = NULL; - int protocol = 0; - - if (!_PyArg_ParseStack(args, nargs, "|i:__reduce__", - &protocol)) { - goto exit; - } - - if (!_PyArg_NoStackKeywords("__reduce__", kwnames)) { - goto exit; - } - return_value = object___reduce___impl(self, protocol); - -exit: - return return_value; + return object___reduce___impl(self); } PyDoc_STRVAR(object___reduce_ex____doc__, -"__reduce_ex__($self, protocol=0, /)\n" +"__reduce_ex__($self, protocol, /)\n" "--\n" "\n" "Helper for pickle."); #define OBJECT___REDUCE_EX___METHODDEF \ - {"__reduce_ex__", (PyCFunction)object___reduce_ex__, METH_FASTCALL, object___reduce_ex____doc__}, + {"__reduce_ex__", (PyCFunction)object___reduce_ex__, METH_O, object___reduce_ex____doc__}, static PyObject * object___reduce_ex___impl(PyObject *self, int protocol); static PyObject * -object___reduce_ex__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +object___reduce_ex__(PyObject *self, PyObject *arg) { PyObject *return_value = NULL; - int protocol = 0; + int protocol; - if (!_PyArg_ParseStack(args, nargs, "|i:__reduce_ex__", - &protocol)) { - goto exit; - } - - if (!_PyArg_NoStackKeywords("__reduce_ex__", kwnames)) { + if (!PyArg_Parse(arg, "i:__reduce_ex__", &protocol)) { goto exit; } return_value = object___reduce_ex___impl(self, protocol); @@ -256,4 +237,4 @@ object___dir__(PyObject *self, PyObject *Py_UNUSED(ignored)) { return object___dir___impl(self); } -/*[clinic end generated code: output=ce354e436e2360a0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8c4c856859564eaa input=a9049054013a1b77]*/ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4a9949e4022..369c72f81d3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4393,23 +4393,20 @@ _common_reduce(PyObject *self, int proto) /*[clinic input] object.__reduce__ - protocol: int = 0 - / - Helper for pickle. [clinic start generated code]*/ static PyObject * -object___reduce___impl(PyObject *self, int protocol) -/*[clinic end generated code: output=5572e699c467dd5b input=227f37ed68bd938a]*/ +object___reduce___impl(PyObject *self) +/*[clinic end generated code: output=d4ca691f891c6e2f input=11562e663947e18b]*/ { - return _common_reduce(self, protocol); + return _common_reduce(self, 0); } /*[clinic input] object.__reduce_ex__ - protocol: int = 0 + protocol: int / Helper for pickle. @@ -4417,7 +4414,7 @@ Helper for pickle. static PyObject * object___reduce_ex___impl(PyObject *self, int protocol) -/*[clinic end generated code: output=2e157766f6b50094 input=8dd6a9602a12749e]*/ +/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/ { static PyObject *objreduce; PyObject *reduce, *res;