From baace7f115ff8c403dc38059c3898090e1b1af47 Mon Sep 17 00:00:00 2001 From: Carson Jones Date: Thu, 12 Mar 2026 18:01:46 -0400 Subject: [PATCH] gh-145886: Fix e.raw += e.raw typo in UnixConsole.getpending In both variants of getpending(), the raw bytes from queued events were being accumulated incorrectly: e.raw was being added to itself instead of accumulating e2.raw from the dequeued event. This meant the combined event's raw field would always be empty bytes (since it starts as b"" and b"" + b"" is b""). Fix the typo so that e.raw += e2.raw is used, matching the pattern already used for e.data += e2.data on the preceding line. Also add a test that verifies getpending correctly accumulates raw bytes from multiple queued events. --- Lib/_pyrepl/unix_console.py | 4 ++-- Lib/test/test_pyrepl/test_unix_console.py | 27 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Lib/_pyrepl/unix_console.py b/Lib/_pyrepl/unix_console.py index 937b5df6ff7d4c..cb8f51cdc4a67a 100644 --- a/Lib/_pyrepl/unix_console.py +++ b/Lib/_pyrepl/unix_console.py @@ -542,7 +542,7 @@ def getpending(self): while not self.event_queue.empty(): e2 = self.event_queue.get() e.data += e2.data - e.raw += e.raw + e.raw += e2.raw amount = struct.unpack("i", ioctl(self.input_fd, FIONREAD, b"\0\0\0\0"))[0] trace("getpending({a})", a=amount) @@ -566,7 +566,7 @@ def getpending(self): while not self.event_queue.empty(): e2 = self.event_queue.get() e.data += e2.data - e.raw += e.raw + e.raw += e2.raw amount = 10000 raw = self.__read(amount) diff --git a/Lib/test/test_pyrepl/test_unix_console.py b/Lib/test/test_pyrepl/test_unix_console.py index 680adbc2d968f0..38f14fca4ee39a 100644 --- a/Lib/test/test_pyrepl/test_unix_console.py +++ b/Lib/test/test_pyrepl/test_unix_console.py @@ -400,3 +400,30 @@ def test_repl_eio(self): ), f"Expected EIO/ENXIO error message in stderr: {err}", ) + + +@unittest.skipIf(sys.platform == "win32", "No Unix console on Windows") +class TestGetPending(TestCase): + def test_getpending_accumulates_raw_from_queued_events(self): + # gh-145886: getpending was adding e.raw to itself instead of e2.raw + console = UnixConsole.__new__(UnixConsole) + console.encoding = "utf-8" + console.input_fd = 0 + + ev1 = Event("key", "a", b"x") + ev2 = Event("key", "b", b"y") + queue = [ev1, ev2] + + mock_eq = MagicMock() + mock_eq.empty = lambda: len(queue) == 0 + mock_eq.get = lambda: queue.pop(0) + console.event_queue = mock_eq + + # Mock __read to return empty bytes (no additional pending input) + console._UnixConsole__read = lambda n: b"" + + with patch("_pyrepl.unix_console.ioctl", return_value=b"\0\0\0\0"): + result = console.getpending() + + self.assertEqual(result.data, "ab") + self.assertEqual(result.raw, b"xy")