Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e9253eb

Browse filesBrowse files
gh-122559: Synchronize C and Python implementation of the io module about pickling (GH-122628)
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.
1 parent a247dd3 commit e9253eb
Copy full SHA for e9253eb

File tree

5 files changed

+55
-10
lines changed
Filter options

5 files changed

+55
-10
lines changed

‎Lib/test/test_io.py

Copy file name to clipboardExpand all lines: Lib/test/test_io.py
+44Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,28 @@ def test_readonly_attributes(self):
13731373
with self.assertRaises(AttributeError):
13741374
buf.raw = x
13751375

1376+
def test_pickling_subclass(self):
1377+
global MyBufferedIO
1378+
class MyBufferedIO(self.tp):
1379+
def __init__(self, raw, tag):
1380+
super().__init__(raw)
1381+
self.tag = tag
1382+
def __getstate__(self):
1383+
return self.tag, self.raw.getvalue()
1384+
def __setstate__(slf, state):
1385+
tag, value = state
1386+
slf.__init__(self.BytesIO(value), tag)
1387+
1388+
raw = self.BytesIO(b'data')
1389+
buf = MyBufferedIO(raw, tag='ham')
1390+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1391+
with self.subTest(protocol=proto):
1392+
pickled = pickle.dumps(buf, proto)
1393+
newbuf = pickle.loads(pickled)
1394+
self.assertEqual(newbuf.raw.getvalue(), b'data')
1395+
self.assertEqual(newbuf.tag, 'ham')
1396+
del MyBufferedIO
1397+
13761398

13771399
class SizeofTest:
13781400

@@ -3950,6 +3972,28 @@ def test_issue35928(self):
39503972
f.write(res)
39513973
self.assertEqual(res + f.readline(), 'foo\nbar\n')
39523974

3975+
def test_pickling_subclass(self):
3976+
global MyTextIO
3977+
class MyTextIO(self.TextIOWrapper):
3978+
def __init__(self, raw, tag):
3979+
super().__init__(raw)
3980+
self.tag = tag
3981+
def __getstate__(self):
3982+
return self.tag, self.buffer.getvalue()
3983+
def __setstate__(slf, state):
3984+
tag, value = state
3985+
slf.__init__(self.BytesIO(value), tag)
3986+
3987+
raw = self.BytesIO(b'data')
3988+
txt = MyTextIO(raw, 'ham')
3989+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
3990+
with self.subTest(protocol=proto):
3991+
pickled = pickle.dumps(txt, proto)
3992+
newtxt = pickle.loads(pickled)
3993+
self.assertEqual(newtxt.buffer.getvalue(), b'data')
3994+
self.assertEqual(newtxt.tag, 'ham')
3995+
del MyTextIO
3996+
39533997
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
39543998
def test_read_non_blocking(self):
39553999
import os
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Remove :meth:`!__reduce__` and :meth:`!__reduce_ex__` methods that always
2+
raise :exc:`TypeError` in the C implementation of :class:`io.FileIO`,
3+
:class:`io.BufferedReader`, :class:`io.BufferedWriter` and
4+
:class:`io.BufferedRandom` and replace them with default
5+
:meth:`!__getstate__` methods that raise :exc:`!TypeError`.
6+
This restores fine details of behavior of Python 3.11 and older versions.

‎Modules/_io/bufferedio.c

Copy file name to clipboardExpand all lines: Modules/_io/bufferedio.c
+3-6Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,8 +2555,7 @@ static PyMethodDef bufferedreader_methods[] = {
25552555
_IO__BUFFERED_TRUNCATE_METHODDEF
25562556
_IO__BUFFERED___SIZEOF___METHODDEF
25572557

2558-
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
2559-
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
2558+
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
25602559
{NULL, NULL}
25612560
};
25622561

@@ -2615,8 +2614,7 @@ static PyMethodDef bufferedwriter_methods[] = {
26152614
_IO__BUFFERED_TELL_METHODDEF
26162615
_IO__BUFFERED___SIZEOF___METHODDEF
26172616

2618-
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
2619-
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
2617+
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
26202618
{NULL, NULL}
26212619
};
26222620

@@ -2733,8 +2731,7 @@ static PyMethodDef bufferedrandom_methods[] = {
27332731
_IO_BUFFEREDWRITER_WRITE_METHODDEF
27342732
_IO__BUFFERED___SIZEOF___METHODDEF
27352733

2736-
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
2737-
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
2734+
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
27382735
{NULL, NULL}
27392736
};
27402737

‎Modules/_io/fileio.c

Copy file name to clipboardExpand all lines: Modules/_io/fileio.c
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,8 +1262,7 @@ static PyMethodDef fileio_methods[] = {
12621262
_IO_FILEIO_ISATTY_METHODDEF
12631263
{"_isatty_open_only", _io_FileIO_isatty_open_only, METH_NOARGS},
12641264
{"_dealloc_warn", fileio_dealloc_warn, METH_O, NULL},
1265-
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
1266-
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
1265+
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
12671266
{NULL, NULL} /* sentinel */
12681267
};
12691268

‎Modules/_io/textio.c

Copy file name to clipboardExpand all lines: Modules/_io/textio.c
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3366,8 +3366,7 @@ static PyMethodDef textiowrapper_methods[] = {
33663366
_IO_TEXTIOWRAPPER_TELL_METHODDEF
33673367
_IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
33683368

3369-
{"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS},
3370-
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O},
3369+
{"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
33713370
{NULL, NULL}
33723371
};
33733372

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.