From e9a5fc6809c679b4c4d542ea90b552d60188c4f3 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Tue, 23 Sep 2025 16:36:20 +0200 Subject: [PATCH 1/2] fix occasionally swalled keystrokes on Windows --- Lib/_pyrepl/windows_console.py | 11 ++++++++- Lib/test/test_pyrepl/test_windows_console.py | 26 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py index c56dcd6d7dd434..893cc0580d1608 100644 --- a/Lib/_pyrepl/windows_console.py +++ b/Lib/_pyrepl/windows_console.py @@ -566,7 +566,7 @@ def getpending(self) -> Event: e.data += ch return e - def wait(self, timeout: float | None) -> bool: + def wait_for_event(self, timeout: float | None) -> bool: """Wait for an event.""" if timeout is None: timeout = INFINITE @@ -579,6 +579,15 @@ def wait(self, timeout: float | None) -> bool: return False return True + def wait(self, timeout: float | None) -> bool: + """ + Wait for events on the console. + """ + return ( + not self.event_queue.empty() + or self.wait_for_event(timeout) + ) + def repaint(self) -> None: raise NotImplementedError("No repaint support") diff --git a/Lib/test/test_pyrepl/test_windows_console.py b/Lib/test/test_pyrepl/test_windows_console.py index f9607e02c604ff..e36d3259a889b8 100644 --- a/Lib/test/test_pyrepl/test_windows_console.py +++ b/Lib/test/test_pyrepl/test_windows_console.py @@ -576,6 +576,32 @@ def test_up_vt(self): Event(evt='key', data='up', raw=bytearray(b'\x1b[A'))) self.assertEqual(self.mock.call_count, 3) + # All tests above assume that there is always keyboard data to read, + # because for simplicity we just use + # self.console.wait = MagicMock(return_value=True) + def test_wait_empty(self): + console = WindowsConsole(encoding='utf-8') + console.wait_for_event = MagicMock(return_value=True) + self.assertTrue(console.event_queue.empty()) + timeout = 2.0 + self.assertTrue(console.wait(timeout)) + self.assertEqual(console.wait_for_event.call_count, 1) + self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout)) + + timeout = 1.1 + console.wait_for_event = MagicMock(return_value=False) + self.assertFalse(console.wait(timeout)) + self.assertEqual(console.wait_for_event.call_count, 1) + self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout)) + + def test_wait_not_empty(self): + console = WindowsConsole(encoding='utf-8') + console.wait_for_event = MagicMock(return_value=True) + console.event_queue.push(b"a") + self.assertFalse(console.event_queue.empty()) + self.assertTrue(console.wait(0.0)) + self.assertEqual(console.wait_for_event.call_count, 0) + if __name__ == "__main__": unittest.main() From 71ec85a8761077780a6adb751df666c2b5ad0b05 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Tue, 23 Sep 2025 16:41:46 +0200 Subject: [PATCH 2/2] blurb it --- .../next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst diff --git a/Misc/NEWS.d/next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst b/Misc/NEWS.d/next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst new file mode 100644 index 00000000000000..628fa0e0d53c3e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst @@ -0,0 +1,2 @@ +Some keystrokes can be swallowed in the new ``PyREPL`` on Windows, +especially when used together with the ALT key. Fix by Chris Eibl.