https://github.com/python/cpython/commit/80d8a7ef10e356b8f0cb25ad46e44090757b01b2
commit: 80d8a7ef10e356b8f0cb25ad46e44090757b01b2
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: ambv <[email protected]>
date: 2026-01-02T16:43:46+01:00
summary:

[3.14] gh-139262: Prevent swallowing REPL input on Windows (GH-139263) 
(GH-143362)

(cherry picked from commit ef6f92a2a63fd83d62d9a431b2c3133a9a069ea0)

Co-authored-by: Chris Eibl <[email protected]>
Co-authored-by: Ɓukasz Langa <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-09-23-16-41-21.gh-issue-139262.RO0E98.rst
M Lib/_pyrepl/windows_console.py
M Lib/test/test_pyrepl/test_windows_console.py

diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index 1c4c7d434afc80..bc137ead41dd6b 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -567,7 +567,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
@@ -580,6 +580,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 065706472e52be..3587b834f3cd07 100644
--- a/Lib/test/test_pyrepl/test_windows_console.py
+++ b/Lib/test/test_pyrepl/test_windows_console.py
@@ -590,6 +590,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()
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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to