diff -r 031fc0231f3d Lib/socket.py --- a/Lib/socket.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/socket.py Sat Jan 17 18:18:04 2015 +0200 @@ -171,9 +171,6 @@ class socket(_socket.socket): s += '>' return s - def __getstate__(self): - raise TypeError("Cannot serialize socket object") - def dup(self): """dup() -> socket object diff -r 031fc0231f3d Lib/test/test_csv.py --- a/Lib/test/test_csv.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/test/test_csv.py Sat Jan 17 18:18:04 2015 +0200 @@ -9,6 +9,7 @@ from io import StringIO from tempfile import TemporaryFile import csv import gc +import pickle from test import support class Test_Csv(unittest.TestCase): @@ -413,6 +414,12 @@ class TestDialectRegistry(unittest.TestC self.assertRaises(TypeError, csv.reader, [], quoting = -1) self.assertRaises(TypeError, csv.reader, [], quoting = 100) + def test_pickle(self): + for name in csv.list_dialects(): + dialect = csv.get_dialect(name) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + self.assertRaises(TypeError, pickle.dumps, dialect, proto) + class TestCsvBase(unittest.TestCase): def readerAssertEqual(self, input, expected_result): with TemporaryFile("w+", newline='') as fileobj: diff -r 031fc0231f3d Lib/test/test_dictviews.py --- a/Lib/test/test_dictviews.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/test/test_dictviews.py Sat Jan 17 18:18:04 2015 +0200 @@ -1,4 +1,5 @@ import unittest +import pickle from test import support class DictSetTest(unittest.TestCase): @@ -198,6 +199,13 @@ class DictSetTest(unittest.TestCase): d[42] = d.values() self.assertRaises(RuntimeError, repr, d) + def test_pickle(self): + d = {1: 10, "a": "ABC"} + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + self.assertRaises(TypeError, pickle.dumps, d.keys(), proto) + self.assertRaises(TypeError, pickle.dumps, d.values(), proto) + self.assertRaises(TypeError, pickle.dumps, d.items(), proto) + def test_main(): support.run_unittest(DictSetTest) diff -r 031fc0231f3d Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/test/test_zlib.py Sat Jan 17 18:18:04 2015 +0200 @@ -1,6 +1,7 @@ import unittest from test import support import binascii +import pickle import random import sys from test.support import bigmemtest, _1G, _4G @@ -596,6 +597,16 @@ class CompressObjectTestCase(BaseCompres d.flush() self.assertRaises(ValueError, d.copy) + def test_compresspickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.assertRaises(TypeError): + pickle.dumps(zlib.compressobj(zlib.Z_BEST_COMPRESSION), proto) + + def test_decompresspickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.assertRaises(TypeError): + pickle.dumps(zlib.decompressobj(), proto) + # Memory use of the following functions takes into account overallocation @bigmemtest(size=_1G + 1024 * 1024, memuse=3) diff -r 031fc0231f3d Modules/_bz2module.c --- a/Modules/_bz2module.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Modules/_bz2module.c Sat Jan 17 18:18:04 2015 +0200 @@ -264,14 +264,6 @@ static PyObject * 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) { @@ -353,7 +345,6 @@ BZ2Compressor_dealloc(BZ2Compressor *sel static PyMethodDef BZ2Compressor_methods[] = { _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF _BZ2_BZ2COMPRESSOR_FLUSH_METHODDEF - {"__getstate__", (PyCFunction)BZ2Compressor_getstate, METH_NOARGS}, {NULL} }; @@ -497,14 +488,6 @@ static PyObject * 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__ @@ -560,7 +543,6 @@ BZ2Decompressor_dealloc(BZ2Decompressor static PyMethodDef BZ2Decompressor_methods[] = { _BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF - {"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS}, {NULL} }; diff -r 031fc0231f3d Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Modules/_io/bufferedio.c Sat Jan 17 18:18:04 2015 +0200 @@ -641,16 +641,6 @@ buffered_isatty(buffered *self, PyObject return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL); } -/* Serialization */ - -static PyObject * -buffered_getstate(buffered *self, PyObject *args) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - /* Forward decls */ static PyObject * _bufferedwriter_flush_unlocked(buffered *); @@ -1777,7 +1767,6 @@ static PyMethodDef bufferedreader_method {"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}, {"read", (PyCFunction)buffered_read, METH_VARARGS}, {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, @@ -2173,7 +2162,6 @@ static PyMethodDef bufferedwriter_method {"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}, {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, @@ -2466,8 +2454,6 @@ static PyMethodDef bufferedrwpair_method {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS}, {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - {NULL, NULL} }; @@ -2594,7 +2580,6 @@ static PyMethodDef bufferedrandom_method {"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 -r 031fc0231f3d Modules/_io/fileio.c --- a/Modules/_io/fileio.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Modules/_io/fileio.c Sat Jan 17 18:18:04 2015 +0200 @@ -1080,14 +1080,6 @@ fileio_isatty(fileio *self) return PyBool_FromLong(res); } -static PyObject * -fileio_getstate(fileio *self) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - PyDoc_STRVAR(fileio_doc, "file(name: str[, mode: str][, opener: None]) -> file IO object\n" @@ -1190,7 +1182,6 @@ static PyMethodDef fileio_methods[] = { {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, - {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff -r 031fc0231f3d Modules/_io/textio.c --- a/Modules/_io/textio.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Modules/_io/textio.c Sat Jan 17 18:18:04 2015 +0200 @@ -2563,14 +2563,6 @@ textiowrapper_isatty(textio *self, PyObj } static PyObject * -textiowrapper_getstate(textio *self, PyObject *args) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - -static PyObject * textiowrapper_flush(textio *self, PyObject *args) { CHECK_ATTACHED(self); @@ -2739,7 +2731,6 @@ static PyMethodDef textiowrapper_methods {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS}, {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS}, {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS}, - {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS}, {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS}, {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS}, diff -r 031fc0231f3d Modules/_lzmamodule.c --- a/Modules/_lzmamodule.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Modules/_lzmamodule.c Sat Jan 17 18:18:04 2015 +0200 @@ -602,14 +602,6 @@ static PyObject * 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) @@ -812,7 +804,6 @@ Compressor_dealloc(Compressor *self) static PyMethodDef Compressor_methods[] = { _LZMA_LZMACOMPRESSOR_COMPRESS_METHODDEF _LZMA_LZMACOMPRESSOR_FLUSH_METHODDEF - {"__getstate__", (PyCFunction)Compressor_getstate, METH_NOARGS}, {NULL} }; @@ -972,14 +963,6 @@ static PyObject * 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) { @@ -1124,7 +1107,6 @@ Decompressor_dealloc(Decompressor *self) static PyMethodDef Decompressor_methods[] = { _LZMA_LZMADECOMPRESSOR_DECOMPRESS_METHODDEF - {"__getstate__", (PyCFunction)Decompressor_getstate, METH_NOARGS}, {NULL} }; diff -r 031fc0231f3d Objects/typeobject.c --- a/Objects/typeobject.c Thu Jan 15 22:53:21 2015 +0100 +++ b/Objects/typeobject.c Sat Jan 17 18:18:04 2015 +0200 @@ -3885,6 +3885,16 @@ Py_LOCAL(int) return 0; } +/* Returns 1 if all superclasses of t are allocated on the heap. */ +static int +allheaptypes(PyTypeObject *t) +{ + for (; t != &PyBaseObject_Type; t = t->tp_base) + if (!PyType_HasFeature(t, Py_TPFLAGS_HEAPTYPE)) + return 0; + return 1; +} + static PyObject * reduce_newobj(PyObject *obj, int proto) { @@ -3893,10 +3903,28 @@ reduce_newobj(PyObject *obj, int proto) PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *result; + if (Py_TYPE(obj)->tp_new == NULL) { + PyErr_Format(PyExc_TypeError, + "can't pickle %s objects", + Py_TYPE(obj)->tp_name); + return NULL; + } if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0) return NULL; if (args == NULL) { + if (!PyList_Check(obj) && !PyDict_Check(obj) && + !allheaptypes(Py_TYPE(obj))) { + _Py_IDENTIFIER(__getstate__); + PyObject *getstate = _PyObject_LookupSpecial(obj, &PyId___getstate__); + if (getstate == NULL) { + PyErr_Format(PyExc_TypeError, + "can't pickle %s objects", + Py_TYPE(obj)->tp_name); + return NULL; + } + Py_DECREF(getstate); + } args = PyTuple_New(0); if (args == NULL) { Py_XDECREF(kwargs);