From f6e66a6faf689a2f2d6ea1f65d70dafe6eaabc77 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 2 Aug 2024 19:25:06 +0300 Subject: [PATCH 1/2] gh-122559: Synchronize C and Python implementation of the io module about pickling 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. --- Lib/test/test_io.py | 44 +++++++++++++++++++ ...-08-02-20-01-36.gh-issue-122559.2JlJr3.rst | 6 +++ Modules/_io/bufferedio.c | 9 ++-- Modules/_io/fileio.c | 3 +- Modules/_io/textio.c | 3 +- 5 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 1ca3edac8c8dc9..b381fee945c7d1 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1336,6 +1336,28 @@ def test_readonly_attributes(self): 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: @@ -3919,6 +3941,28 @@ def test_issue35928(self): 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 diff --git a/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst b/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst new file mode 100644 index 00000000000000..f2e2a6f2520916 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst @@ -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 :meth:`!__getstatus__` +methods that always raise :exc:`!TypeError`. This restores fine details of +behavior of Python 3.11 and older versions. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index e45323c93a17ef..050878c6da6ec3 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -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} }; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 5d9d87d6118a75..144d8cac890bf0 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1204,8 +1204,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 */ }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index c162d8106ec1fd..e10689d05a8400 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -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} }; From 5203270e2f3cd8d820690d8f2839e7d992ccebdc Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 3 Aug 2024 11:50:31 +0300 Subject: [PATCH 2/2] Update Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst b/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst index f2e2a6f2520916..4ef9daa1bac26f 100644 --- a/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst +++ b/Misc/NEWS.d/next/Library/2024-08-02-20-01-36.gh-issue-122559.2JlJr3.rst @@ -1,6 +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 :meth:`!__getstatus__` -methods that always raise :exc:`!TypeError`. This restores fine details of -behavior of Python 3.11 and older versions. +: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. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy