From aad3337eeeaa90b4a2268ff590a4ff274c4bd7f9 Mon Sep 17 00:00:00 2001 From: DarioDaF Date: Tue, 6 Dec 2022 09:55:24 +0100 Subject: [PATCH 1/4] Moving transport data_read to bytes through memoryview --- Lib/asyncio/proactor_events.py | 3 ++- Lib/asyncio/streams.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index c6aab408fc7410..1e2a730cf368a9 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -288,7 +288,8 @@ def _loop_reading(self, fut=None): # we got end-of-file so no need to reschedule a new read return - data = self._data[:length] + # It's a new slice so make it immutable so protocols upstream don't have problems + data = bytes(memoryview(self._data)[:length]) else: # the future will be replaced by next proactor.recv call fut.cancel() diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index c4d837a1170819..dcc1c359c26547 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -688,7 +688,7 @@ async def read(self, n=-1): await self._wait_for_data('read') # This will work right even if buffer is less than n bytes - data = bytes(self._buffer[:n]) + data = bytes(memoryview(self._buffer)[:n]) del self._buffer[:n] self._maybe_resume_transport() @@ -730,7 +730,7 @@ async def readexactly(self, n): data = bytes(self._buffer) self._buffer.clear() else: - data = bytes(self._buffer[:n]) + data = bytes(memoryview(self._buffer)[:n]) del self._buffer[:n] self._maybe_resume_transport() return data From 1a5af35f3667d5961869662e08f882fe9c3f0e95 Mon Sep 17 00:00:00 2001 From: DarioDaF Date: Tue, 6 Dec 2022 11:04:44 +0100 Subject: [PATCH 2/4] Added test case for #99941 --- Lib/test/test_asyncio/test_proactor_events.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index ae30185cef776a..6cb7dc300c5331 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -75,7 +75,10 @@ def test_loop_reading_data(self): called_buf = bytearray(self.buffer_size) called_buf[:len(buf)] = buf self.loop._proactor.recv_into.assert_called_with(self.sock, called_buf) - self.protocol.data_received.assert_called_with(bytearray(buf)) + self.protocol.data_received.assert_called_with(buf) + # assert_called_with maps bytearray and bytes to the same thing so check manually + # regression test for https://github.com/python/cpython/issues/99941 + self.assertIsInstance(self.protocol.data_received.call_args.args[0], bytes) @unittest.skipIf(sys.flags.optimize, "Assertions are disabled in optimized mode") def test_loop_reading_no_data(self): From d9e22f78b30941499545eb705da5b3e515e0f503 Mon Sep 17 00:00:00 2001 From: DarioDaF Date: Tue, 6 Dec 2022 11:17:02 +0100 Subject: [PATCH 3/4] Added blurb --- .../Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst diff --git a/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst b/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst new file mode 100644 index 00000000000000..8a6a35c426702c --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst @@ -0,0 +1,6 @@ +Made :func:`asyncio.Protocol.data_received` receive immutable object +``bytes`` instead of ``bytearrays`` with regression tests added and opted to +use ``memoryview`` to take the slices for performance on big buffers. +Performance test from ``gh-issue:21442`` done on my machine with 10 +repetitions on release build with timings 0.043 (delta: 0.019) before patch +and 0.041 (delta: 0.010) after so no noticable change in performance. From e101911355177b6aac3fb4f07159f2c5b1c3854b Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sat, 10 Dec 2022 14:04:00 -0800 Subject: [PATCH 4/4] Simplify news entry --- .../Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst b/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst index 8a6a35c426702c..a019d7287207d8 100644 --- a/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst +++ b/Misc/NEWS.d/next/Windows/2022-12-06-11-16-46.gh-issue-99941.GmUQ6o.rst @@ -1,6 +1,2 @@ -Made :func:`asyncio.Protocol.data_received` receive immutable object -``bytes`` instead of ``bytearrays`` with regression tests added and opted to -use ``memoryview`` to take the slices for performance on big buffers. -Performance test from ``gh-issue:21442`` done on my machine with 10 -repetitions on release build with timings 0.043 (delta: 0.019) before patch -and 0.041 (delta: 0.010) after so no noticable change in performance. +Ensure that :func:`asyncio.Protocol.data_received` receives an immutable +:class:`bytes` object (as documented), instead of :class:`bytearray`.