From 0353b4eaaf451ad463ce7eb3074f6b62d332f401 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 31 Oct 2018 02:28:07 +0200 Subject: [PATCH] bpo-33138: Change standard error message for non-pickleable and non-copyable types. (GH-6239) --- Lib/_pyio.py | 5 ++--- Lib/copyreg.py | 15 +++++++++------ Lib/socket.py | 2 +- .../2018-03-25-19-25-14.bpo-33138.aSqudH.rst | 2 ++ Modules/_bz2module.c | 18 ------------------ Modules/_io/bufferedio.c | 15 --------------- Modules/_io/fileio.c | 9 --------- Modules/_io/textio.c | 9 --------- Modules/_io/winconsoleio.c | 9 --------- Modules/_lzmamodule.c | 18 ------------------ Objects/typeobject.c | 6 +++--- 11 files changed, 17 insertions(+), 91 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-03-25-19-25-14.bpo-33138.aSqudH.rst diff --git a/Lib/_pyio.py b/Lib/_pyio.py index b8975ff533d..e4a879941e1 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -814,8 +814,7 @@ class _BufferedIOMixin(BufferedIOBase): return self.raw.mode def __getstate__(self): - raise TypeError("can not serialize a '{0}' object" - .format(self.__class__.__name__)) + raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") def __repr__(self): modname = self.__class__.__module__ @@ -1554,7 +1553,7 @@ class FileIO(RawIOBase): self.close() def __getstate__(self): - raise TypeError("cannot serialize '%s' object", self.__class__.__name__) + raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") def __repr__(self): class_name = '%s.%s' % (self.__class__.__module__, diff --git a/Lib/copyreg.py b/Lib/copyreg.py index bbe1af4e2e7..dfc463c49a3 100644 --- a/Lib/copyreg.py +++ b/Lib/copyreg.py @@ -53,7 +53,8 @@ _HEAPTYPE = 1<<9 def _reduce_ex(self, proto): assert proto < 2 - for base in self.__class__.__mro__: + cls = self.__class__ + for base in cls.__mro__: if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: break else: @@ -61,16 +62,18 @@ def _reduce_ex(self, proto): if base is object: state = None else: - if base is self.__class__: - raise TypeError("can't pickle %s objects" % base.__name__) + if base is cls: + raise TypeError(f"cannot pickle {cls.__name__!r} object") state = base(self) - args = (self.__class__, base, state) + args = (cls, base, state) try: getstate = self.__getstate__ except AttributeError: if getattr(self, "__slots__", None): - raise TypeError("a class that defines __slots__ without " - "defining __getstate__ cannot be pickled") from None + raise TypeError(f"cannot pickle {cls.__name__!r} object: " + f"a class that defines __slots__ without " + f"defining __getstate__ cannot be pickled " + f"with protocol {proto}") from None try: dict = self.__dict__ except AttributeError: diff --git a/Lib/socket.py b/Lib/socket.py index 385844b5853..772b9e185bf 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -189,7 +189,7 @@ class socket(_socket.socket): return s def __getstate__(self): - raise TypeError("Cannot serialize socket object") + raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") def dup(self): """dup() -> socket object diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-03-25-19-25-14.bpo-33138.aSqudH.rst b/Misc/NEWS.d/next/Core and Builtins/2018-03-25-19-25-14.bpo-33138.aSqudH.rst new file mode 100644 index 00000000000..6f445261843 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-03-25-19-25-14.bpo-33138.aSqudH.rst @@ -0,0 +1,2 @@ +Changed standard error message for non-pickleable and non-copyable types. It +now says "cannot pickle" instead of "can't pickle" or "cannot serialize". diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index f0d9588fe55..b5e5a79d50a 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -264,14 +264,6 @@ _bz2_BZ2Compressor_flush_impl(BZ2Compressor *self) return result; } -static PyObject * -BZ2Compressor_getstate(BZ2Compressor *self, PyObject *noargs) -{ - PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object", - Py_TYPE(self)->tp_name); - return NULL; -} - static void* BZ2_Malloc(void* ctx, int items, int size) { @@ -347,7 +339,6 @@ BZ2Compressor_dealloc(BZ2Compressor *self) static PyMethodDef BZ2Compressor_methods[] = { _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF _BZ2_BZ2COMPRESSOR_FLUSH_METHODDEF - {"__getstate__", (PyCFunction)BZ2Compressor_getstate, METH_NOARGS}, {NULL} }; @@ -612,14 +603,6 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, return result; } -static PyObject * -BZ2Decompressor_getstate(BZ2Decompressor *self, PyObject *noargs) -{ - PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object", - Py_TYPE(self)->tp_name); - return NULL; -} - /*[clinic input] _bz2.BZ2Decompressor.__init__ @@ -679,7 +662,6 @@ BZ2Decompressor_dealloc(BZ2Decompressor *self) static PyMethodDef BZ2Decompressor_methods[] = { _BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF - {"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS}, {NULL} }; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 9d3b4466493..2eb5262f0f7 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -608,16 +608,6 @@ buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored)) return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL); } -/* Serialization */ - -static PyObject * -buffered_getstate(buffered *self, PyObject *Py_UNUSED(ignored)) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - /* Forward decls */ static PyObject * _bufferedwriter_flush_unlocked(buffered *); @@ -2394,7 +2384,6 @@ static PyMethodDef bufferedreader_methods[] = { {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, _IO__BUFFERED_READ_METHODDEF _IO__BUFFERED_PEEK_METHODDEF @@ -2485,7 +2474,6 @@ static PyMethodDef bufferedwriter_methods[] = { {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, _IO_BUFFEREDWRITER_WRITE_METHODDEF _IO__BUFFERED_TRUNCATE_METHODDEF @@ -2579,8 +2567,6 @@ static PyMethodDef bufferedrwpair_methods[] = { {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS}, {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - {NULL, NULL} }; @@ -2652,7 +2638,6 @@ static PyMethodDef bufferedrandom_methods[] = { {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 44d51c9faf5..ffcb7301295 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1120,14 +1120,6 @@ _io_FileIO_isatty_impl(fileio *self) return PyBool_FromLong(res); } -static PyObject * -fileio_getstate(fileio *self, PyObject *Py_UNUSED(ignored)) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - #include "clinic/fileio.c.h" static PyMethodDef fileio_methods[] = { @@ -1145,7 +1137,6 @@ static PyMethodDef fileio_methods[] = { _IO_FILEIO_FILENO_METHODDEF _IO_FILEIO_ISATTY_METHODDEF {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, - {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index a466d3a03a5..3a3667b39da 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2891,14 +2891,6 @@ _io_TextIOWrapper_isatty_impl(textio *self) return _PyObject_CallMethodId(self->buffer, &PyId_isatty, NULL); } -static PyObject * -textiowrapper_getstate(textio *self, PyObject *args) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - /*[clinic input] _io.TextIOWrapper.flush [clinic start generated code]*/ @@ -3132,7 +3124,6 @@ static PyMethodDef textiowrapper_methods[] = { _IO_TEXTIOWRAPPER_READABLE_METHODDEF _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF _IO_TEXTIOWRAPPER_ISATTY_METHODDEF - {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS}, _IO_TEXTIOWRAPPER_SEEK_METHODDEF _IO_TEXTIOWRAPPER_TELL_METHODDEF diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 13342ec239d..148255c354a 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -1060,14 +1060,6 @@ _io__WindowsConsoleIO_isatty_impl(winconsoleio *self) Py_RETURN_TRUE; } -static PyObject * -winconsoleio_getstate(winconsoleio *self, PyObject *Py_UNUSED(ignored)) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - #include "clinic/winconsoleio.c.h" static PyMethodDef winconsoleio_methods[] = { @@ -1080,7 +1072,6 @@ static PyMethodDef winconsoleio_methods[] = { _IO__WINDOWSCONSOLEIO_WRITABLE_METHODDEF _IO__WINDOWSCONSOLEIO_FILENO_METHODDEF _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF - {"__getstate__", (PyCFunction)winconsoleio_getstate, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index bb7a7ec50ce..b5f9561df2a 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -591,14 +591,6 @@ _lzma_LZMACompressor_flush_impl(Compressor *self) return result; } -static PyObject * -Compressor_getstate(Compressor *self, PyObject *noargs) -{ - PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object", - Py_TYPE(self)->tp_name); - return NULL; -} - static int Compressor_init_xz(lzma_stream *lzs, int check, uint32_t preset, PyObject *filterspecs) @@ -794,7 +786,6 @@ Compressor_dealloc(Compressor *self) static PyMethodDef Compressor_methods[] = { _LZMA_LZMACOMPRESSOR_COMPRESS_METHODDEF _LZMA_LZMACOMPRESSOR_FLUSH_METHODDEF - {"__getstate__", (PyCFunction)Compressor_getstate, METH_NOARGS}, {NULL} }; @@ -1078,14 +1069,6 @@ _lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, return result; } -static PyObject * -Decompressor_getstate(Decompressor *self, PyObject *noargs) -{ - PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object", - Py_TYPE(self)->tp_name); - return NULL; -} - static int Decompressor_init_raw(lzma_stream *lzs, PyObject *filterspecs) { @@ -1235,7 +1218,6 @@ Decompressor_dealloc(Decompressor *self) static PyMethodDef Decompressor_methods[] = { _LZMA_LZMADECOMPRESSOR_DECOMPRESS_METHODDEF - {"__getstate__", (PyCFunction)Decompressor_getstate, METH_NOARGS}, {NULL} }; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8e91e33d2d1..722fe5f9473 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4122,7 +4122,7 @@ _PyObject_GetState(PyObject *obj, int required) if (required && obj->ob_type->tp_itemsize) { PyErr_Format(PyExc_TypeError, - "can't pickle %.200s objects", + "cannot pickle '%.200s' object", Py_TYPE(obj)->tp_name); return NULL; } @@ -4163,7 +4163,7 @@ _PyObject_GetState(PyObject *obj, int required) Py_DECREF(slotnames); Py_DECREF(state); PyErr_Format(PyExc_TypeError, - "can't pickle %.200s objects", + "cannot pickle '%.200s' object", Py_TYPE(obj)->tp_name); return NULL; } @@ -4400,7 +4400,7 @@ reduce_newobj(PyObject *obj) if (Py_TYPE(obj)->tp_new == NULL) { PyErr_Format(PyExc_TypeError, - "can't pickle %.200s objects", + "cannot pickle '%.200s' object", Py_TYPE(obj)->tp_name); return NULL; }