gh-120221: Support KeyboardInterrupt in asyncio REPL (#123795)

This switches the main pyrepl event loop to always be non-blocking so that it
can listen to incoming interruptions from other threads.

This also resolves invalid display of exceptions from other threads
(gh-123178).

This also fixes freezes with pasting and an active input hook.
This commit is contained in:
Łukasz Langa 2024-09-06 21:28:29 +02:00 committed by GitHub
parent 0c080d7c77
commit 033510e11d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 133 additions and 21 deletions

View file

@ -199,8 +199,14 @@ class UnixConsole(Console):
self.event_queue = EventQueue(self.input_fd, self.encoding)
self.cursor_visible = 1
def more_in_buffer(self) -> bool:
return bool(
self.input_buffer
and self.input_buffer_pos < len(self.input_buffer)
)
def __read(self, n: int) -> bytes:
if not self.input_buffer or self.input_buffer_pos >= len(self.input_buffer):
if not self.more_in_buffer():
self.input_buffer = os.read(self.input_fd, 10000)
ret = self.input_buffer[self.input_buffer_pos : self.input_buffer_pos + n]
@ -393,6 +399,7 @@ class UnixConsole(Console):
"""
if not block and not self.wait(timeout=0):
return None
while self.event_queue.empty():
while True:
try:
@ -413,7 +420,11 @@ class UnixConsole(Console):
"""
Wait for events on the console.
"""
return bool(self.pollob.poll(timeout))
return (
not self.event_queue.empty()
or self.more_in_buffer()
or bool(self.pollob.poll(timeout))
)
def set_cursor_vis(self, visible):
"""