22import  ast 
33import  asyncio 
44import  asyncio .tools 
5- import  concurrent .futures 
65import  contextvars 
76import  inspect 
87import  os 
98import  site 
109import  sys 
11- import  threading 
1210import  types 
1311import  warnings 
1412
1513from  _colorize  import  get_theme 
1614from  _pyrepl .console  import  InteractiveColoredConsole 
1715
18- from  . import  futures 
19- 
2016
2117class  AsyncIOInteractiveConsole (InteractiveColoredConsole ):
2218
@@ -29,122 +25,83 @@ def __init__(self, locals, loop):
2925
3026    def  runcode (self , code ):
3127        global  return_code 
32-         future  =  concurrent .futures .Future ()
33- 
34-         def  callback ():
35-             global  return_code 
36-             global  repl_future 
37-             global  keyboard_interrupted 
38- 
39-             repl_future  =  None 
40-             keyboard_interrupted  =  False 
4128
29+         async  def  callback ():
4230            func  =  types .FunctionType (code , self .locals )
43-             try :
44-                 coro  =  func ()
45-             except  SystemExit  as  se :
46-                 return_code  =  se .code 
47-                 self .loop .stop ()
48-                 return 
49-             except  KeyboardInterrupt  as  ex :
50-                 keyboard_interrupted  =  True 
51-                 future .set_exception (ex )
52-                 return 
53-             except  BaseException  as  ex :
54-                 future .set_exception (ex )
55-                 return 
31+             coro  =  func ()
5632
5733            if  not  inspect .iscoroutine (coro ):
58-                 future .set_result (coro )
59-                 return 
60- 
61-             try :
62-                 repl_future  =  self .loop .create_task (coro , context = self .context )
63-                 futures ._chain_future (repl_future , future )
64-             except  BaseException  as  exc :
65-                 future .set_exception (exc )
34+                 return  coro 
35+             return  await  coro 
6636
67-         self .loop .call_soon_threadsafe (callback , context = self .context )
6837
38+         task  =  self .loop .create_task (callback (), context = self .context )
6939        try :
70-             return  future .result ()
71-         except  SystemExit  as  se :
72-             return_code  =  se .code 
73-             self .loop .stop ()
74-             return 
40+             return  self .loop .run_until_complete (task )
41+         except  SystemExit :
42+             raise 
7543        except  BaseException :
76-             if  keyboard_interrupted :
77-                 if  not  CAN_USE_PYREPL :
78-                     self .write ("\n KeyboardInterrupt\n " )
79-             else :
80-                 self .showtraceback ()
44+             self .showtraceback ()
8145            return  self .STATEMENT_FAILED 
8246
83- class  REPLThread (threading .Thread ):
8447
85-      def  run ( self ):
86-          global  return_code 
48+ def  interact ( ):
49+     global  return_code 
8750
88-         try :
89-             banner  =  (
90-                 f'asyncio REPL { sys .version }   on { sys .platform } \n ' 
91-                 f'Use "await" directly instead of "asyncio.run()".\n ' 
92-                 f'Type "help", "copyright", "credits" or "license" ' 
93-                 f'for more information.\n ' 
94-             )
51+     try :
52+         banner  =  (
53+             f'asyncio REPL { sys .version }   on { sys .platform } \n ' 
54+             f'Use "await" directly instead of "asyncio.run()".\n ' 
55+             f'Type "help", "copyright", "credits" or "license" ' 
56+             f'for more information.\n ' 
57+         )
58+ 
59+         console .write (banner )
60+ 
61+         if  startup_path  :=  os .getenv ("PYTHONSTARTUP" ):
62+             sys .audit ("cpython.run_startup" , startup_path )
63+ 
64+             import  tokenize 
65+             with  tokenize .open (startup_path ) as  f :
66+                 startup_code  =  compile (f .read (), startup_path , "exec" )
67+                 exec (startup_code , console .locals )
68+ 
69+         ps1  =  getattr (sys , "ps1" , ">>> " )
70+         if  CAN_USE_PYREPL :
71+             theme  =  get_theme ().syntax 
72+             ps1  =  f"{ theme .prompt } { ps1 } { theme .reset }  " 
73+             import_line  =  f'{ theme .keyword }  import{ theme .reset }   asyncio' 
74+         else :
75+             import_line  =  "import asyncio" 
76+         console .write (f"{ ps1 } { import_line } \n " )
9577
96-             console .write (banner )
97- 
98-             if  startup_path  :=  os .getenv ("PYTHONSTARTUP" ):
99-                 sys .audit ("cpython.run_startup" , startup_path )
100- 
101-                 import  tokenize 
102-                 with  tokenize .open (startup_path ) as  f :
103-                     startup_code  =  compile (f .read (), startup_path , "exec" )
104-                     exec (startup_code , console .locals )
105- 
106-             ps1  =  getattr (sys , "ps1" , ">>> " )
107-             if  CAN_USE_PYREPL :
108-                 theme  =  get_theme ().syntax 
109-                 ps1  =  f"{ theme .prompt } { ps1 } { theme .reset }  " 
110-                 import_line  =  f'{ theme .keyword }  import{ theme .reset }   asyncio' 
111-             else :
112-                 import_line  =  "import asyncio" 
113-             console .write (f"{ ps1 } { import_line } \n " )
114- 
115-             if  CAN_USE_PYREPL :
116-                 from  _pyrepl .simple_interact  import  (
117-                     run_multiline_interactive_console ,
118-                 )
119-                 try :
120-                     sys .ps1  =  ps1 
121-                     run_multiline_interactive_console (console )
122-                 except  SystemExit :
123-                     # expected via the `exit` and `quit` commands 
124-                     pass 
125-                 except  BaseException :
126-                     # unexpected issue 
127-                     console .showtraceback ()
128-                     console .write ("Internal error, " )
129-                     return_code  =  1 
130-             else :
78+         if  CAN_USE_PYREPL :
79+             from  _pyrepl .simple_interact  import  (
80+                 run_multiline_interactive_console ,
81+             )
82+             try :
83+                 sys .ps1  =  ps1 
84+                 run_multiline_interactive_console (console )
85+             except  SystemExit  as  se :
86+                 # expected via the `exit` and `quit` commands 
87+                 return_code  =  se .code 
88+             except  BaseException :
89+                 # unexpected issue 
90+                 console .showtraceback ()
91+                 console .write ("Internal error, " )
92+                 return_code  =  1 
93+         else :
94+             try :
13195                console .interact (banner = "" , exitmsg = "" )
132-         finally :
133-             warnings .filterwarnings (
134-                 'ignore' ,
135-                 message = r'^coroutine .* was never awaited$' ,
136-                 category = RuntimeWarning )
137- 
138-             loop .call_soon_threadsafe (loop .stop )
139- 
140-     def  interrupt (self ) ->  None :
141-         if  not  CAN_USE_PYREPL :
142-             return 
96+             except  SystemExit  as  se :
97+                 return_code  =  se .code 
98+     finally :
99+         warnings .filterwarnings (
100+             'ignore' ,
101+             message = r'^coroutine .* was never awaited$' ,
102+             category = RuntimeWarning )
143103
144-         from  _pyrepl .simple_interact  import  _get_reader 
145-         r  =  _get_reader ()
146-         if  r .threading_hook  is  not   None :
147-             r .threading_hook .add ("" )  # type: ignore 
104+         loop .call_soon_threadsafe (loop .stop )
148105
149106
150107if  __name__  ==  '__main__' :
@@ -198,9 +155,6 @@ def interrupt(self) -> None:
198155
199156    console  =  AsyncIOInteractiveConsole (repl_locals , loop )
200157
201-     repl_future  =  None 
202-     keyboard_interrupted  =  False 
203- 
204158    try :
205159        import  readline   # NoQA 
206160    except  ImportError :
@@ -223,21 +177,6 @@ def interrupt(self) -> None:
223177                completer  =  rlcompleter .Completer (console .locals )
224178                readline .set_completer (completer .complete )
225179
226-     repl_thread  =  REPLThread (name = "Interactive thread" )
227-     repl_thread .daemon  =  True 
228-     repl_thread .start ()
229- 
230-     while  True :
231-         try :
232-             loop .run_forever ()
233-         except  KeyboardInterrupt :
234-             keyboard_interrupted  =  True 
235-             if  repl_future  and  not  repl_future .done ():
236-                 repl_future .cancel ()
237-             repl_thread .interrupt ()
238-             continue 
239-         else :
240-             break 
241- 
180+     interact ()
242181    console .write ('exiting asyncio REPL...\n ' )
243182    sys .exit (return_code )
0 commit comments