[Python-checkins] bpo-33138: Change standard error message for non-pickleable and non-copyable types. (GH-6239)

Serhiy Storchaka webhook-mailer at python.org
Tue Oct 30 20:28:10 EDT 2018


https://github.com/python/cpython/commit/0353b4eaaf451ad463ce7eb3074f6b62d332f401
commit: 0353b4eaaf451ad463ce7eb3074f6b62d332f401
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-10-31T02:28:07+02:00
summary:

bpo-33138: Change standard error message for non-pickleable and non-copyable types. (GH-6239)

files:
A Misc/NEWS.d/next/Core and Builtins/2018-03-25-19-25-14.bpo-33138.aSqudH.rst
M Lib/_pyio.py
M Lib/copyreg.py
M Lib/socket.py
M Modules/_bz2module.c
M Modules/_io/bufferedio.c
M Modules/_io/fileio.c
M Modules/_io/textio.c
M Modules/_io/winconsoleio.c
M Modules/_lzmamodule.c
M Objects/typeobject.c

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index b8975ff533d7..e4a879941e1d 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -814,8 +814,7 @@ def mode(self):
         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 @@ def __del__(self):
             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 bbe1af4e2e7e..dfc463c49a38 100644
--- a/Lib/copyreg.py
+++ b/Lib/copyreg.py
@@ -53,7 +53,8 @@ def _reconstructor(cls, base, state):
 
 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 385844b58532..772b9e185bf1 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -189,7 +189,7 @@ def __repr__(self):
         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 000000000000..6f445261843f
--- /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 f0d9588fe55d..b5e5a79d50a5 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 9d3b4466493c..2eb5262f0f7b 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 44d51c9faf5d..ffcb73012953 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 a466d3a03a5b..3a3667b39da8 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 13342ec239d6..148255c354a4 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 bb7a7ec50ce0..b5f9561df2ad 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 8e91e33d2d10..722fe5f94735 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;
     }



More information about the Python-checkins mailing list