Commit 4d939f25 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now

rejects builtin types with not defined __new__.
Added tests for non-pickleable types.
parents b39f53cb 5bc51d04
import contextlib import contextlib
import copy
import inspect import inspect
import pickle
import sys import sys
import types import types
import unittest import unittest
...@@ -1318,6 +1320,34 @@ class CoroutineTest(unittest.TestCase): ...@@ -1318,6 +1320,34 @@ class CoroutineTest(unittest.TestCase):
run_async(foo()) run_async(foo())
self.assertEqual(CNT, 0) self.assertEqual(CNT, 0)
def test_copy(self):
async def func(): pass
coro = func()
with self.assertRaises(TypeError):
copy.copy(coro)
aw = coro.__await__()
try:
with self.assertRaises(TypeError):
copy.copy(aw)
finally:
aw.close()
def test_pickle(self):
async def func(): pass
coro = func()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(coro, proto)
aw = coro.__await__()
try:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(aw, proto)
finally:
aw.close()
class CoroAsyncIOCompatTest(unittest.TestCase): class CoroAsyncIOCompatTest(unittest.TestCase):
......
import copy
import pickle
import unittest import unittest
class DictSetTest(unittest.TestCase): class DictSetTest(unittest.TestCase):
...@@ -197,6 +199,22 @@ class DictSetTest(unittest.TestCase): ...@@ -197,6 +199,22 @@ class DictSetTest(unittest.TestCase):
d[42] = d.values() d[42] = d.values()
self.assertRaises(RecursionError, repr, d) self.assertRaises(RecursionError, repr, d)
def test_copy(self):
d = {1: 10, "a": "ABC"}
self.assertRaises(TypeError, copy.copy, d.keys())
self.assertRaises(TypeError, copy.copy, d.values())
self.assertRaises(TypeError, copy.copy, d.items())
def test_pickle(self):
d = {1: 10, "a": "ABC"}
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.keys(), proto)
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.values(), proto)
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.items(), proto)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
import copy
import gc import gc
import pickle
import sys import sys
import unittest import unittest
import warnings import warnings
...@@ -111,6 +113,21 @@ class GeneratorTest(unittest.TestCase): ...@@ -111,6 +113,21 @@ class GeneratorTest(unittest.TestCase):
self.assertEqual(gen.__qualname__, self.assertEqual(gen.__qualname__,
"GeneratorTest.test_name.<locals>.<genexpr>") "GeneratorTest.test_name.<locals>.<genexpr>")
def test_copy(self):
def f():
yield 1
g = f()
with self.assertRaises(TypeError):
copy.copy(g)
def test_pickle(self):
def f():
yield 1
g = f()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(g, proto)
class ExceptionTest(unittest.TestCase): class ExceptionTest(unittest.TestCase):
# Tests for the issue #23353: check that the currently handled exception # Tests for the issue #23353: check that the currently handled exception
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# For this purpose, the module-level "ET" symbol is temporarily # For this purpose, the module-level "ET" symbol is temporarily
# monkey-patched when running the "test_xml_etree_c" test suite. # monkey-patched when running the "test_xml_etree_c" test suite.
import copy
import html import html
import io import io
import operator import operator
...@@ -2082,6 +2083,19 @@ class ElementIterTest(unittest.TestCase): ...@@ -2082,6 +2083,19 @@ class ElementIterTest(unittest.TestCase):
self.assertEqual(self._ilist(doc), all_tags) self.assertEqual(self._ilist(doc), all_tags)
self.assertEqual(self._ilist(doc, '*'), all_tags) self.assertEqual(self._ilist(doc, '*'), all_tags)
def test_copy(self):
a = ET.Element('a')
it = a.iter()
with self.assertRaises(TypeError):
copy.copy(it)
def test_pickle(self):
a = ET.Element('a')
it = a.iter()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(it, proto)
class TreeBuilderTest(unittest.TestCase): class TreeBuilderTest(unittest.TestCase):
sample1 = ('<!DOCTYPE html PUBLIC' sample1 = ('<!DOCTYPE html PUBLIC'
......
import unittest import unittest
from test import support from test import support
import binascii import binascii
import pickle
import random import random
import sys import sys
from test.support import bigmemtest, _1G, _4G from test.support import bigmemtest, _1G, _4G
...@@ -600,6 +601,16 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -600,6 +601,16 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
d.flush() d.flush()
self.assertRaises(ValueError, d.copy) self.assertRaises(ValueError, d.copy)
def test_compresspickle(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
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.PicklingError)):
pickle.dumps(zlib.decompressobj(), proto)
# Memory use of the following functions takes into account overallocation # Memory use of the following functions takes into account overallocation
@bigmemtest(size=_1G + 1024 * 1024, memuse=3) @bigmemtest(size=_1G + 1024 * 1024, memuse=3)
......
...@@ -11,6 +11,9 @@ Release date: TBA ...@@ -11,6 +11,9 @@ Release date: TBA
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now
rejects builtin types with not defined __new__.
- Issue #25555: Fix parser and AST: fill lineno and col_offset of "arg" node - Issue #25555: Fix parser and AST: fill lineno and col_offset of "arg" node
when compiling AST from Python objects. when compiling AST from Python objects.
......
...@@ -4100,6 +4100,12 @@ reduce_newobj(PyObject *obj, int proto) ...@@ -4100,6 +4100,12 @@ reduce_newobj(PyObject *obj, int proto)
PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *newobj, *newargs, *state, *listitems, *dictitems;
PyObject *result; 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) if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0)
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment