mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
[3.13] gh-122559: Synchronize C and Python implementation of the io module about pickling (GH-122628) (GH-133381)
In the C implementation, remove __reduce__ and __reduce_ex__ methods
that always raise TypeError and restore __getstate__ methods that always
raise TypeErrori.
This restores fine details of the pre-3.12 behavior and unifies
both implementations.
(cherry picked from commit e9253ebf74
)
This commit is contained in:
parent
3c9d1778ef
commit
973e2d3e29
5 changed files with 55 additions and 10 deletions
|
@ -1349,6 +1349,28 @@ class CommonBufferedTests:
|
|||
with self.assertRaises(AttributeError):
|
||||
buf.raw = x
|
||||
|
||||
def test_pickling_subclass(self):
|
||||
global MyBufferedIO
|
||||
class MyBufferedIO(self.tp):
|
||||
def __init__(self, raw, tag):
|
||||
super().__init__(raw)
|
||||
self.tag = tag
|
||||
def __getstate__(self):
|
||||
return self.tag, self.raw.getvalue()
|
||||
def __setstate__(slf, state):
|
||||
tag, value = state
|
||||
slf.__init__(self.BytesIO(value), tag)
|
||||
|
||||
raw = self.BytesIO(b'data')
|
||||
buf = MyBufferedIO(raw, tag='ham')
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
pickled = pickle.dumps(buf, proto)
|
||||
newbuf = pickle.loads(pickled)
|
||||
self.assertEqual(newbuf.raw.getvalue(), b'data')
|
||||
self.assertEqual(newbuf.tag, 'ham')
|
||||
del MyBufferedIO
|
||||
|
||||
|
||||
class SizeofTest:
|
||||
|
||||
|
@ -3932,6 +3954,28 @@ class TextIOWrapperTest(unittest.TestCase):
|
|||
f.write(res)
|
||||
self.assertEqual(res + f.readline(), 'foo\nbar\n')
|
||||
|
||||
def test_pickling_subclass(self):
|
||||
global MyTextIO
|
||||
class MyTextIO(self.TextIOWrapper):
|
||||
def __init__(self, raw, tag):
|
||||
super().__init__(raw)
|
||||
self.tag = tag
|
||||
def __getstate__(self):
|
||||
return self.tag, self.buffer.getvalue()
|
||||
def __setstate__(slf, state):
|
||||
tag, value = state
|
||||
slf.__init__(self.BytesIO(value), tag)
|
||||
|
||||
raw = self.BytesIO(b'data')
|
||||
txt = MyTextIO(raw, 'ham')
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
pickled = pickle.dumps(txt, proto)
|
||||
newtxt = pickle.loads(pickled)
|
||||
self.assertEqual(newtxt.buffer.getvalue(), b'data')
|
||||
self.assertEqual(newtxt.tag, 'ham')
|
||||
del MyTextIO
|
||||
|
||||
|
||||
class MemviewBytesIO(io.BytesIO):
|
||||
'''A BytesIO object whose read method returns memoryviews
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Remove :meth:`!__reduce__` and :meth:`!__reduce_ex__` methods that always
|
||||
raise :exc:`TypeError` in the C implementation of :class:`io.FileIO`,
|
||||
:class:`io.BufferedReader`, :class:`io.BufferedWriter` and
|
||||
:class:`io.BufferedRandom` and replace them with default
|
||||
:meth:`!__getstate__` methods that raise :exc:`!TypeError`.
|
||||
This restores fine details of behavior of Python 3.11 and older versions.
|
|
@ -2530,8 +2530,7 @@ static PyMethodDef bufferedreader_methods[] = {
|
|||
_IO__BUFFERED_TRUNCATE_METHODDEF
|
||||
_IO__BUFFERED___SIZEOF___METHODDEF
|
||||
|
||||
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
|
||||
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -2590,8 +2589,7 @@ static PyMethodDef bufferedwriter_methods[] = {
|
|||
_IO__BUFFERED_TELL_METHODDEF
|
||||
_IO__BUFFERED___SIZEOF___METHODDEF
|
||||
|
||||
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
|
||||
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -2708,8 +2706,7 @@ static PyMethodDef bufferedrandom_methods[] = {
|
|||
_IO_BUFFEREDWRITER_WRITE_METHODDEF
|
||||
_IO__BUFFERED___SIZEOF___METHODDEF
|
||||
|
||||
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
|
||||
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -1178,8 +1178,7 @@ static PyMethodDef fileio_methods[] = {
|
|||
_IO_FILEIO_FILENO_METHODDEF
|
||||
_IO_FILEIO_ISATTY_METHODDEF
|
||||
{"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
|
||||
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
|
||||
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -3350,8 +3350,7 @@ static PyMethodDef textiowrapper_methods[] = {
|
|||
_IO_TEXTIOWRAPPER_TELL_METHODDEF
|
||||
_IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
|
||||
|
||||
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
|
||||
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue