##// END OF EJS Templates
Run ipdb in separate thread (required when using within asyncio applications).
Jonathan Slenders -
Show More
@@ -1,6 +1,7 b''
1 import asyncio
1 import asyncio
2 import signal
2 import signal
3 import sys
3 import sys
4 import threading
4
5
5 from IPython.core.debugger import Pdb
6 from IPython.core.debugger import Pdb
6
7
@@ -81,18 +82,11 b' class TerminalPdb(Pdb):'
81 if not self.use_rawinput:
82 if not self.use_rawinput:
82 raise ValueError('Sorry ipdb does not support use_rawinput=False')
83 raise ValueError('Sorry ipdb does not support use_rawinput=False')
83
84
84 # In order to make sure that asyncio code written in the
85 # In order to make sure that prompt, which uses asyncio doesn't
85 # interactive shell doesn't interfere with the prompt, we run the
86 # interfere with applications in which it's used, we always run the
86 # prompt in a different event loop.
87 # prompt itself in a different thread (we can't start an event loop
87 # If we don't do this, people could spawn coroutine with a
88 # within an event loop). This new thread won't have any event loop
88 # while/true inside which will freeze the prompt.
89 # running, and here we run our prompt-loop.
89
90 try:
91 old_loop = asyncio.get_event_loop()
92 except RuntimeError:
93 # This happens when the user used `asyncio.run()`.
94 old_loop = None
95
96
90
97 self.preloop()
91 self.preloop()
98
92
@@ -109,14 +103,25 b' class TerminalPdb(Pdb):'
109 self._ptcomp.ipy_completer.namespace = self.curframe_locals
103 self._ptcomp.ipy_completer.namespace = self.curframe_locals
110 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
104 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
111
105
112 asyncio.set_event_loop(self.pt_loop)
106 # Run the prompt in a different thread.
107 line = ''
108 keyboard_interrupt = False
109
110 def in_thread():
111 nonlocal line, keyboard_interrupt
113 try:
112 try:
114 line = self.pt_app.prompt()
113 line = self.pt_app.prompt()
115 except EOFError:
114 except EOFError:
116 line = 'EOF'
115 line = 'EOF'
117 finally:
116 except KeyboardInterrupt:
118 # Restore the original event loop.
117 keyboard_interrupt = True
119 asyncio.set_event_loop(old_loop)
118
119 th = threading.Thread(target=in_thread)
120 th.start()
121 th.join()
122
123 if keyboard_interrupt:
124 raise KeyboardInterrupt
120
125
121 line = self.precmd(line)
126 line = self.precmd(line)
122 stop = self.onecmd(line)
127 stop = self.onecmd(line)
General Comments 0
You need to be logged in to leave comments. Login now