Skip to content

Commit 5ad91cd

Browse files
miss-islingtonchris-eiblambv
authored
[3.13] gh-139262: Prevent swallowing REPL input on Windows (GH-139263) (GH-143363)
(cherry picked from commit ef6f92a) Co-authored-by: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parent c09d6a4 commit 5ad91cd

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

Lib/_pyrepl/windows_console.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ def getpending(self) -> Event:
527527
processed."""
528528
return Event("key", "", b"")
529529

530-
def wait(self, timeout: float | None) -> bool:
530+
def wait_for_event(self, timeout: float | None) -> bool:
531531
"""Wait for an event."""
532532
# Poor man's Windows select loop
533533
start_time = time.time()
@@ -538,6 +538,15 @@ def wait(self, timeout: float | None) -> bool:
538538
return False
539539
time.sleep(0.01)
540540

541+
def wait(self, timeout: float | None) -> bool:
542+
"""
543+
Wait for events on the console.
544+
"""
545+
return (
546+
not self.event_queue.empty()
547+
or self.wait_for_event(timeout)
548+
)
549+
541550
def repaint(self) -> None:
542551
raise NotImplementedError("No repaint support")
543552

Lib/test/test_pyrepl/test_windows_console.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,32 @@ def test_up_vt(self):
576576
Event(evt='key', data='up', raw=bytearray(b'\x1b[A')))
577577
self.assertEqual(self.mock.call_count, 3)
578578

579+
# All tests above assume that there is always keyboard data to read,
580+
# because for simplicity we just use
581+
# self.console.wait = MagicMock(return_value=True)
582+
def test_wait_empty(self):
583+
console = WindowsConsole(encoding='utf-8')
584+
console.wait_for_event = MagicMock(return_value=True)
585+
self.assertTrue(console.event_queue.empty())
586+
timeout = 2.0
587+
self.assertTrue(console.wait(timeout))
588+
self.assertEqual(console.wait_for_event.call_count, 1)
589+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
590+
591+
timeout = 1.1
592+
console.wait_for_event = MagicMock(return_value=False)
593+
self.assertFalse(console.wait(timeout))
594+
self.assertEqual(console.wait_for_event.call_count, 1)
595+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
596+
597+
def test_wait_not_empty(self):
598+
console = WindowsConsole(encoding='utf-8')
599+
console.wait_for_event = MagicMock(return_value=True)
600+
console.event_queue.push(b"a")
601+
self.assertFalse(console.event_queue.empty())
602+
self.assertTrue(console.wait(0.0))
603+
self.assertEqual(console.wait_for_event.call_count, 0)
604+
579605

580606
if __name__ == "__main__":
581607
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Some keystrokes can be swallowed in the new ``PyREPL`` on Windows,
2+
especially when used together with the ALT key. Fix by Chris Eibl.

0 commit comments

Comments
 (0)