From 20da301237edbcdf6f962b586ae4330de20a5c9e Mon Sep 17 00:00:00 2001 From: Luke Zhang Date: Fri, 2 Jun 2023 16:34:17 +0800 Subject: [PATCH 1/7] add BufferedReader.read() return value check for non-blocking stream mode --- Lib/_pyio.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 32698abac78d25..8679ddd2bf5bfa 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2511,8 +2511,11 @@ def read(self, size=None): decoder = self._decoder or self._get_decoder() if size < 0: # Read everything. + if input_chunk := self.buffer.read() is None and isinstance(self.buffer, BufferedReader): + raise BlockingIOError( + "BufferedReader.read() return None, stream opened in non-blocking mode and not data is available") result = (self._get_decoded_chars() + - decoder.decode(self.buffer.read(), final=True)) + decoder.decode(input_chunk, final=True)) self._set_decoded_chars('') self._snapshot = None return result From 696119e0d596dbd43b6ba8c65c25196f48a6e92d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:40:33 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2023-06-02-08-40-32.gh-issue-57531.425aq5.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst new file mode 100644 index 00000000000000..d2c4fa08dca85b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst @@ -0,0 +1 @@ +add BufferedReader.read() return value check for non-blocking stream mode, raise BlockingIOError instead of TypeError with more context for the caller. From 8c430f3270f982878261908da3031c274ac8d28f Mon Sep 17 00:00:00 2001 From: Luke Zhang Date: Fri, 2 Jun 2023 17:00:59 +0800 Subject: [PATCH 3/7] fix input_chunk assignment error --- Lib/_pyio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 8679ddd2bf5bfa..a0af616849d889 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2511,7 +2511,7 @@ def read(self, size=None): decoder = self._decoder or self._get_decoder() if size < 0: # Read everything. - if input_chunk := self.buffer.read() is None and isinstance(self.buffer, BufferedReader): + if (input_chunk := self.buffer.read()) is None and isinstance(self.buffer, BufferedReader): raise BlockingIOError( "BufferedReader.read() return None, stream opened in non-blocking mode and not data is available") result = (self._get_decoded_chars() + From d13f29c89cce9622ee17e113cee1b5aa6f73a09a Mon Sep 17 00:00:00 2001 From: Luccccifer Date: Thu, 18 Jan 2024 16:24:48 +0800 Subject: [PATCH 4/7] Capitalize the first letter of the sentence in the NEWS entry --- .../2023-06-02-08-40-32.gh-issue-57531.425aq5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst index d2c4fa08dca85b..bb336317272396 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-02-08-40-32.gh-issue-57531.425aq5.rst @@ -1 +1 @@ -add BufferedReader.read() return value check for non-blocking stream mode, raise BlockingIOError instead of TypeError with more context for the caller. +Add BufferedReader.read() return value check for non-blocking stream mode, raise BlockingIOError instead of TypeError with more context for the caller. From 68741edc6b9686c9ecd0121582daf94d924d309b Mon Sep 17 00:00:00 2001 From: Luccccifer Date: Thu, 18 Jan 2024 16:41:58 +0800 Subject: [PATCH 5/7] Fix error by manual resolution --- Lib/_pyio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 293397b8d7ff0e..379de83ae5482f 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2516,7 +2516,7 @@ def read(self, size=None): raise BlockingIOError( "BufferedReader.read() return None, stream opened in non-blocking mode and not data is available") result = (self._get_decoded_chars() + - decoder.decode(self.buffer.read(), final=True)) + decoder.decode(input_chunk, final=True)) if self._snapshot is not None: self._set_decoded_chars('') self._snapshot = None From 2c98129b42dffb7556294235602acb67aa980064 Mon Sep 17 00:00:00 2001 From: Luke Zhang Date: Fri, 19 Jan 2024 17:26:51 +0800 Subject: [PATCH 6/7] add simple error raising test in test_io.py --- Lib/test/test_io.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 936edea3cad70c..a77a220de4b81a 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -3592,6 +3592,14 @@ def test_read_nonbytes(self): t = self.TextIOWrapper(self.StringIO('a'), encoding="utf-8") self.assertRaises(TypeError, t.read) + def test_read_non_blocking_stream(self): + # Issue #57531 + # io module doesn't support non-blocking files + r = self.MockRawIO((None,)) + b = self.BufferedReader(r, 1000) + t = self.TextIOWrapper(b, encoding="utf-8") + self.assertRaises(BlockingIOError, t.read) + def test_illegal_encoder(self): # Issue 31271: Calling write() while the return value of encoder's # encode() is invalid shouldn't cause an assertion failure. From 9d191d80aca4d85fa81bb4f415e17bc494757fa6 Mon Sep 17 00:00:00 2001 From: Luke Zhang Date: Fri, 19 Jan 2024 17:53:39 +0800 Subject: [PATCH 7/7] move test_read_non_blocking_stream test case to PyTextIOWrapperTest --- Lib/test/test_io.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index a77a220de4b81a..a08daad13843f7 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -3592,14 +3592,6 @@ def test_read_nonbytes(self): t = self.TextIOWrapper(self.StringIO('a'), encoding="utf-8") self.assertRaises(TypeError, t.read) - def test_read_non_blocking_stream(self): - # Issue #57531 - # io module doesn't support non-blocking files - r = self.MockRawIO((None,)) - b = self.BufferedReader(r, 1000) - t = self.TextIOWrapper(b, encoding="utf-8") - self.assertRaises(BlockingIOError, t.read) - def test_illegal_encoder(self): # Issue 31271: Calling write() while the return value of encoder's # encode() is invalid shouldn't cause an assertion failure. @@ -4005,6 +3997,14 @@ class PyTextIOWrapperTest(TextIOWrapperTest): io = pyio shutdown_error = "LookupError: unknown encoding: ascii" + def test_read_non_blocking_stream(self): + # Issue #57531 + # io module doesn't support non-blocking files + r = self.MockRawIO((None,)) + b = self.BufferedReader(r, 1000) + t = self.TextIOWrapper(b, encoding="utf-8") + self.assertRaises(BlockingIOError, t.read) + class IncrementalNewlineDecoderTest(unittest.TestCase):