From 2eaecd5ce7343b8df44f2cee6ae7a256e3ed64de Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Sat, 16 Mar 2019 18:00:08 +0100 Subject: [PATCH] bpo-31062: Allow socket.makefile to handle line buffering properly Line buffering is enabled by using the argument `buffering=1` as defined in `io.open`. --- Lib/socket.py | 7 ++++- Lib/test/test_socket.py | 29 ++++++++++++++----- .../2021-09-09-10-15-54.bpo-31062.tLeTkn.rst | 2 ++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-09-09-10-15-54.bpo-31062.tLeTkn.rst diff --git a/Lib/socket.py b/Lib/socket.py index ef82c496cb85a4..a4a96977657ff5 100755 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -320,8 +320,12 @@ def makefile(self, mode="r", buffering=None, *, rawmode += "w" raw = SocketIO(self, rawmode) self._io_refs += 1 + line_buffering = False if buffering is None: buffering = -1 + if buffering == 1: + buffering = -1 + line_buffering = True if buffering < 0: buffering = io.DEFAULT_BUFFER_SIZE if buffering == 0: @@ -338,7 +342,8 @@ def makefile(self, mode="r", buffering=None, *, if binary: return buffer encoding = io.text_encoding(encoding) - text = io.TextIOWrapper(buffer, encoding, errors, newline) + text = io.TextIOWrapper( + buffer, encoding, errors, newline, line_buffering) text.mode = mode return text diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 7ac92608f7ce80..31b768e66bbe78 100755 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -4913,10 +4913,20 @@ def testReadline(self): # Performing file readline test line = self.read_file.readline() self.assertEqual(line, self.read_msg) + # Readline mode + if self.bufsize == 1 and self.read_mode == "r": + self.assertTrue(self.read_file.line_buffering) def _testReadline(self): self.write_file.write(self.write_msg) - self.write_file.flush() + # Readline mode: no need to flush + if self.bufsize == 1 and self.write_mode == "w": + self.assertTrue(self.write_file.line_buffering) + else: + self.write_file.flush() + # Prevent garbage collection from flushing + # until the server has finished + self.assertTrue(self.serv_finished.wait(5.0)) def testCloseAfterMakefile(self): # The file returned by makefile should keep the socket open. @@ -5072,11 +5082,6 @@ def _testWriteNonBlocking(self): self.serv_skipped = "failed to saturate the socket buffer" -class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase): - - bufsize = 1 # Default-buffered for reading; line-buffered for writing - - class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase): bufsize = 2 # Exercise the buffering code @@ -5112,6 +5117,16 @@ class UnicodeReadWriteFileObjectClassTestCase(FileObjectClassTestCase): newline = '' +class UnicodeLineBufferedFileObjectClassTestCase(FileObjectClassTestCase): + + bufsize = 1 # Default-buffered for reading; line-buffered for writing + read_mode = 'r' + read_msg = MSG.decode('utf-8') + write_mode = 'w' + write_msg = MSG.decode('utf-8') + newline = '' + + class NetworkConnectionTest(object): """Prove network connection.""" @@ -6649,11 +6664,11 @@ def test_main(): NonBlockingTCPTests, FileObjectClassTestCase, UnbufferedFileObjectClassTestCase, - LineBufferedFileObjectClassTestCase, SmallBufferedFileObjectClassTestCase, UnicodeReadFileObjectClassTestCase, UnicodeWriteFileObjectClassTestCase, UnicodeReadWriteFileObjectClassTestCase, + UnicodeLineBufferedFileObjectClassTestCase, NetworkConnectionNoServer, NetworkConnectionAttributesTest, NetworkConnectionBehaviourTest, diff --git a/Misc/NEWS.d/next/Library/2021-09-09-10-15-54.bpo-31062.tLeTkn.rst b/Misc/NEWS.d/next/Library/2021-09-09-10-15-54.bpo-31062.tLeTkn.rst new file mode 100644 index 00000000000000..ef6421b957bd6a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-09-10-15-54.bpo-31062.tLeTkn.rst @@ -0,0 +1,2 @@ +Allow :meth:`socket.socket.makefile` to handle line buffering properly +(``buffering=1``). This is done by mimicking the behavior of :func:`open`.