Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Lib/_pyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down Expand Up @@ -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__,
Expand Down
15 changes: 9 additions & 6 deletions Lib/copyreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,27 @@ 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:
base = object # not really reachable
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:
Expand Down
2 changes: 1 addition & 1 deletion Lib/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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".
18 changes: 0 additions & 18 deletions Modules/_bz2module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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}
};

Expand Down Expand Up @@ -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__

Expand Down Expand Up @@ -679,7 +662,6 @@ BZ2Decompressor_dealloc(BZ2Decompressor *self)

static PyMethodDef BZ2Decompressor_methods[] = {
_BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF
{"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS},
{NULL}
};

Expand Down
15 changes: 0 additions & 15 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
};

Expand Down Expand Up @@ -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},

Expand Down
9 changes: 0 additions & 9 deletions Modules/_io/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand All @@ -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 */
};

Expand Down
9 changes: 0 additions & 9 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]*/
Expand Down Expand Up @@ -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
Expand Down
9 changes: 0 additions & 9 deletions Modules/_io/winconsoleio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand All @@ -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 */
};

Expand Down
18 changes: 0 additions & 18 deletions Modules/_lzmamodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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}
};

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -1235,7 +1218,6 @@ Decompressor_dealloc(Decompressor *self)

static PyMethodDef Decompressor_methods[] = {
_LZMA_LZMADECOMPRESSOR_DECOMPRESS_METHODDEF
{"__getstate__", (PyCFunction)Decompressor_getstate, METH_NOARGS},
{NULL}
};

Expand Down
6 changes: 3 additions & 3 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down