##// 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.
113 try:
107 line = ''
114 line = self.pt_app.prompt()
108 keyboard_interrupt = False
115 except EOFError:
109
116 line = 'EOF'
110 def in_thread():
117 finally:
111 nonlocal line, keyboard_interrupt
118 # Restore the original event loop.
112 try:
119 asyncio.set_event_loop(old_loop)
113 line = self.pt_app.prompt()
114 except EOFError:
115 line = 'EOF'
116 except KeyboardInterrupt:
117 keyboard_interrupt = True
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