1515from trio ._util import final
1616
1717
18+ class SuppressDecorator (contextlib .ContextDecorator , contextlib .suppress ):
19+ pass
20+
21+
1822@final
1923class TrioInteractiveConsole (InteractiveConsole ):
2024 # code.InteractiveInterpreter defines locals as Mapping[str, Any]
@@ -24,6 +28,7 @@ class TrioInteractiveConsole(InteractiveConsole):
2428
2529 def __init__ (self , repl_locals : dict [str , object ] | None = None ) -> None :
2630 super ().__init__ (locals = repl_locals )
31+ self .token : trio .lowlevel .TrioToken | None = None
2732 self .compile .compiler .flags |= ast .PyCF_ALLOW_TOP_LEVEL_AWAIT
2833
2934 def runcode (self , code : types .CodeType ) -> None :
@@ -70,17 +75,27 @@ def raw_input(self, prompt: str = "") -> str:
7075 else :
7176
7277 def raw_input (self , prompt : str = "" ) -> str :
73- import fcntl
74- import termios
7578 from signal import SIGINT , signal
7679
7780 interrupted = False
81+
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
90+
91+ # Fake up a newline char as if user had typed it at
92+ # os.write(sys.stdin.buffer.fileno(), b"\n")
93+ fcntl .ioctl (sys .stdin , termios .TIOCSTI , b"\n " )
7894
7995 def handler (sig : int , frame : types .FrameType | None ) -> None :
8096 nonlocal interrupted
8197 interrupted = True
82- # Fake up a newline char as if user had typed it at terminal
83- fcntl .ioctl (sys .stdin , termios .TIOCSTI , b"\n " )
98+ self .token .run_sync_soon (newline , idempotent = True )
8499
85100 prev_handler = trio .from_thread .run_sync (signal , SIGINT , handler )
86101 try :
0 commit comments