Skip to content

Commit 98ba0f2

Browse files
chris-eiblambv
authored andcommitted
gh-139262: Prevent swallowing REPL input on Windows (GH-139263)
(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 4a47751 commit 98ba0f2

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

Lib/_pyrepl/windows_console.py

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

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

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

Lib/test/test_pyrepl/test_windows_console.py

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

565+
# All tests above assume that there is always keyboard data to read,
566+
# because for simplicity we just use
567+
# self.console.wait = MagicMock(return_value=True)
568+
def test_wait_empty(self):
569+
console = WindowsConsole(encoding='utf-8')
570+
console.wait_for_event = MagicMock(return_value=True)
571+
self.assertTrue(console.event_queue.empty())
572+
timeout = 2.0
573+
self.assertTrue(console.wait(timeout))
574+
self.assertEqual(console.wait_for_event.call_count, 1)
575+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
576+
577+
timeout = 1.1
578+
console.wait_for_event = MagicMock(return_value=False)
579+
self.assertFalse(console.wait(timeout))
580+
self.assertEqual(console.wait_for_event.call_count, 1)
581+
self.assertEqual(console.wait_for_event.mock_calls[0], call(timeout))
582+
583+
def test_wait_not_empty(self):
584+
console = WindowsConsole(encoding='utf-8')
585+
console.wait_for_event = MagicMock(return_value=True)
586+
console.event_queue.push(b"a")
587+
self.assertFalse(console.event_queue.empty())
588+
self.assertTrue(console.wait(0.0))
589+
self.assertEqual(console.wait_for_event.call_count, 0)
590+
565591

566592
if __name__ == "__main__":
567593
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)