cpython: b8d108a2a38e (original) (raw)
Mercurial > cpython
changeset 99677:b8d108a2a38e
Issue #22995: Instances of extension types with a state that aren't subclasses of list or dict and haven't implemented any pickle-related methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__, or __getstate__), can no longer be pickled. Including memoryview. [#22995]
Serhiy Storchaka storchaka@gmail.com | |
---|---|
date | Fri, 25 Dec 2015 21:05:35 +0200 |
parents | 80d1faa9735d(current diff)0cd2de69fb66(diff) |
children | d0a84d0c5ceb |
files | Lib/test/test_csv.py Misc/NEWS Objects/typeobject.c |
diffstat | 4 files changed, 67 insertions(+), 15 deletions(-)[+] [-] Lib/test/test_csv.py 13 Lib/test/test_memoryview.py 13 Misc/NEWS 5 Objects/typeobject.c 51 |
line wrap: on
line diff
--- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1,6 +1,7 @@
Copyright (C) 2001,2002 Python Software Foundation
csv package unit tests
+import copy import io import sys import os @@ -9,6 +10,7 @@ from io import StringIO from tempfile import TemporaryFile import csv import gc +import pickle from test import support class Test_Csv(unittest.TestCase): @@ -424,6 +426,17 @@ class TestDialectRegistry(unittest.TestC self.assertRaises(TypeError, csv.reader, [], quoting = -1) self.assertRaises(TypeError, csv.reader, [], quoting = 100)
- def test_copy(self):
for name in csv.list_dialects():[](#l1.24)
dialect = csv.get_dialect(name)[](#l1.25)
self.assertRaises(TypeError, copy.copy, dialect)[](#l1.26)
- def test_pickle(self):
for name in csv.list_dialects():[](#l1.29)
dialect = csv.get_dialect(name)[](#l1.30)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):[](#l1.31)
self.assertRaises(TypeError, pickle.dumps, dialect, proto)[](#l1.32)
+ class TestCsvBase(unittest.TestCase): def readerAssertEqual(self, input, expected_result): with TemporaryFile("w+", newline='') as fileobj:
--- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -11,6 +11,8 @@ import gc import weakref import array import io +import copy +import pickle class AbstractMemoryTests: @@ -519,6 +521,17 @@ class OtherTest(unittest.TestCase): m2 = m1[::-1] self.assertEqual(m2.hex(), '30' * 200000)
- def test_copy(self):
m = memoryview(b'abc')[](#l2.17)
with self.assertRaises(TypeError):[](#l2.18)
copy.copy(m)[](#l2.19)
- def test_pickle(self):
m = memoryview(b'abc')[](#l2.22)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):[](#l2.23)
with self.assertRaises(TypeError):[](#l2.24)
pickle.dumps(m, proto)[](#l2.25)
+ if name == "main": unittest.main()
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Release date: tba Core and Builtins ----------------- +- Issue #22995: Instances of extension types with a state that aren't
- subclasses of list or dict and haven't implemented any pickle-related
- methods (reduce, reduce_ex, getnewargs, getnewargs_ex,
- or getstate), can no longer be pickled. Including memoryview. +
--- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3839,7 +3839,7 @@ Py_LOCAL(PyObject *) } Py_LOCAL(PyObject *) -_PyObject_GetState(PyObject *obj) +_PyObject_GetState(PyObject *obj, int required) { PyObject *state; PyObject *getstate; @@ -3854,6 +3854,13 @@ Py_LOCAL(PyObject *) } PyErr_Clear();
if (required && obj->ob_type->tp_itemsize) {[](#l4.16)
PyErr_Format(PyExc_TypeError,[](#l4.17)
"can't pickle %.200s objects",[](#l4.18)
Py_TYPE(obj)->tp_name);[](#l4.19)
return NULL;[](#l4.20)
}[](#l4.21)
+ { PyObject **dict; dict = _PyObject_GetDictPtr(obj); @@ -3878,6 +3885,24 @@ Py_LOCAL(PyObject *) } assert(slotnames == Py_None || PyList_Check(slotnames));
if (required) {[](#l4.30)
Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize;[](#l4.31)
if (obj->ob_type->tp_dictoffset)[](#l4.32)
basicsize += sizeof(PyObject *);[](#l4.33)
if (obj->ob_type->tp_weaklistoffset)[](#l4.34)
basicsize += sizeof(PyObject *);[](#l4.35)
if (slotnames != Py_None)[](#l4.36)
basicsize += sizeof(PyObject *) * Py_SIZE(slotnames);[](#l4.37)
if (obj->ob_type->tp_basicsize > basicsize) {[](#l4.38)
Py_DECREF(slotnames);[](#l4.39)
Py_DECREF(state);[](#l4.40)
PyErr_Format(PyExc_TypeError,[](#l4.41)
"can't pickle %.200s objects",[](#l4.42)
Py_TYPE(obj)->tp_name);[](#l4.43)
return NULL;[](#l4.44)
}[](#l4.45)
}[](#l4.46)
+ if (slotnames != Py_None && Py_SIZE(slotnames) > 0) { PyObject *slots; Py_ssize_t slotnames_size, i; @@ -4107,29 +4132,24 @@ reduce_newobj(PyObject *obj) PyObject *copyreg; PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *result;
if (Py_TYPE(obj)->tp_new == NULL) { PyErr_Format(PyExc_TypeError,
"can't pickle %s objects",[](#l4.59)
} if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0) return NULL;"can't pickle %.200s objects",[](#l4.60) Py_TYPE(obj)->tp_name);[](#l4.61) return NULL;[](#l4.62)
- if (args == NULL) {
args = PyTuple_New(0);[](#l4.68)
if (args == NULL) {[](#l4.69)
Py_XDECREF(kwargs);[](#l4.70)
return NULL;[](#l4.71)
}[](#l4.72)
- } copyreg = import_copyreg(); if (copyreg == NULL) {
Py_DECREF(args);[](#l4.76)
}Py_XDECREF(args);[](#l4.77) Py_XDECREF(kwargs);[](#l4.78) return NULL;[](#l4.79)
- hasargs = (args != NULL); if (kwargs == NULL || PyDict_Size(kwargs) == 0) { _Py_IDENTIFIER(newobj); PyObject *cls;
@@ -4139,13 +4159,13 @@ reduce_newobj(PyObject *obj) newobj = PyObject_GetAttrId(copyreg, &PyId___newobj_); Py_DECREF(copyreg); if (newobj == NULL) {
Py_DECREF(args);[](#l4.89)
Py_XDECREF(args);[](#l4.90) return NULL;[](#l4.91) }[](#l4.92)
n = PyTuple_GET_SIZE(args);[](#l4.93)
n = args ? PyTuple_GET_SIZE(args) : 0;[](#l4.94) newargs = PyTuple_New(n+1);[](#l4.95) if (newargs == NULL) {[](#l4.96)
Py_DECREF(args);[](#l4.97)
Py_XDECREF(args);[](#l4.98) Py_DECREF(newobj);[](#l4.99) return NULL;[](#l4.100) }[](#l4.101)
@@ -4157,7 +4177,7 @@ reduce_newobj(PyObject *obj) Py_INCREF(v); PyTuple_SET_ITEM(newargs, i+1, v); }
Py_DECREF(args);[](#l4.106)