Skip to content

Commit ef6f92a

Browse files
chris-eiblambv
andauthored
gh-139262: Prevent swallowing REPL input on Windows (GH-139263)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parent 864c598 commit ef6f92a

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
@@ -554,7 +554,7 @@ def getpending(self) -> Event:
554554
e.data += ch
555555
return e
556556

557-
def wait(self, timeout: float | None) -> bool:
557+
def wait_for_event(self, timeout: float | None) -> bool:
558558
"""Wait for an event."""
559559
if timeout is None:
560560
timeout = INFINITE
@@ -567,6 +567,15 @@ def wait(self, timeout: float | None) -> bool:
567567
return False
568568
return True
569569

570+
def wait(self, timeout: float | None) -> bool:
571+
"""
572+
Wait for events on the console.
573+
"""
574+
return (
575+
not self.event_queue.empty()
576+
or self.wait_for_event(timeout)
577+
)
578+
570579
def repaint(self) -> None:
571580
raise NotImplementedError("No repaint support")
572581

Lib/test/test_pyrepl/test_windows_console.py

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

593+
# All tests above assume that there is always keyboard data to read,
594+
# because for simplicity we just use
595+
# self.console.wait = MagicMock(return_value=True)
596+
def test_wait_empty(self):
597+
console = WindowsConsole(encoding='utf-8')
598+
console.wait_for_event = MagicMock(return_value=True)
599+
self.assertTrue(console.event_queue.empty())
600+
timeout = 2.0
601+
self.assertTrue(console.wait(timeout))
602+
self.assertEqual(console.wait_for_event.call_count, 1)
603+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
604+
605+
timeout = 1.1
606+
console.wait_for_event = MagicMock(return_value=False)
607+
self.assertFalse(console.wait(timeout))
608+
self.assertEqual(console.wait_for_event.call_count, 1)
609+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
610+
611+
def test_wait_not_empty(self):
612+
console = WindowsConsole(encoding='utf-8')
613+
console.wait_for_event = MagicMock(return_value=True)
614+
console.event_queue.push(b"a")
615+
self.assertFalse(console.event_queue.empty())
616+
self.assertTrue(console.wait(0.0))
617+
self.assertEqual(console.wait_for_event.call_count, 0)
618+
593619

594620
if __name__ == "__main__":
595621
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)