Skip to content

Commit 039bad1

Browse files
grab token and install handler in one go
1 parent a5dcdbf commit 039bad1

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

src/trio/_repl.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import contextlib
55
import inspect
66
import sys
7-
import types
87
import warnings
98
from code import InteractiveConsole
9+
from types import CodeType, FunctionType, FrameType
10+
from typing import Callable
1011

1112
import outcome
1213

@@ -19,6 +20,16 @@ class SuppressDecorator(contextlib.ContextDecorator, contextlib.suppress):
1920
pass
2021

2122

23+
@SuppressDecorator(KeyboardInterrupt)
24+
@trio.lowlevel.disable_ki_protection
25+
def terminal_newline() -> None:
26+
import fcntl
27+
import termios
28+
29+
# Fake up a newline char as if user had typed it at the terminal
30+
fcntl.ioctl(sys.stdin, termios.TIOCSTI, b"\n")
31+
32+
2233
@final
2334
class TrioInteractiveConsole(InteractiveConsole):
2435
# code.InteractiveInterpreter defines locals as Mapping[str, Any]
@@ -31,8 +42,8 @@ def __init__(self, repl_locals: dict[str, object] | None = None) -> None:
3142
self.token: trio.lowlevel.TrioToken | None = None
3243
self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
3344

34-
def runcode(self, code: types.CodeType) -> None:
35-
func = types.FunctionType(code, self.locals)
45+
def runcode(self, code: CodeType) -> None:
46+
func = FunctionType(code, self.locals)
3647
if inspect.iscoroutinefunction(func):
3748
result = trio.from_thread.run(outcome.acapture, func)
3849
else:
@@ -79,24 +90,19 @@ def raw_input(self, prompt: str = "") -> str:
7990

8091
interrupted = False
8192

82-
if self.token is None:
83-
self.token = trio.from_thread.run_sync(trio.lowlevel.current_trio_token)
84-
85-
@SuppressDecorator(KeyboardInterrupt)
86-
@trio.lowlevel.disable_ki_protection
87-
def newline():
88-
import fcntl
89-
import termios
93+
def install_handler() -> (
94+
Callable[[int, FrameType | None], None] | int | None
95+
):
96+
def handler(sig: int, frame: FrameType | None) -> None:
97+
nonlocal interrupted
98+
interrupted = True
99+
token.run_sync_soon(terminal_newline, idempotent=True)
90100

91-
# Fake up a newline char as if user had typed it at
92-
fcntl.ioctl(sys.stdin, termios.TIOCSTI, b"\n")
101+
token = trio.lowlevel.current_trio_token()
93102

94-
def handler(sig: int, frame: types.FrameType | None) -> None:
95-
nonlocal interrupted
96-
interrupted = True
97-
self.token.run_sync_soon(newline, idempotent=True)
103+
return signal(SIGINT, handler)
98104

99-
prev_handler = trio.from_thread.run_sync(signal, SIGINT, handler)
105+
prev_handler = trio.from_thread.run_sync(install_handler)
100106
try:
101107
return input(prompt)
102108
finally:

0 commit comments

Comments
 (0)