##// END OF EJS Templates
Update IPython/terminal/debugger.py...
Matthias Bussonnier -
Show More
@@ -1,166 +1,166 b''
1 import asyncio
1 import asyncio
2 import sys
2 import sys
3 import threading
3 import threading
4
4
5 from IPython.core.debugger import Pdb
5 from IPython.core.debugger import Pdb
6
6
7 from IPython.core.completer import IPCompleter
7 from IPython.core.completer import IPCompleter
8 from .ptutils import IPythonPTCompleter
8 from .ptutils import IPythonPTCompleter
9 from .shortcuts import create_ipython_shortcuts
9 from .shortcuts import create_ipython_shortcuts
10 from . import embed
10 from . import embed
11
11
12 from pygments.token import Token
12 from pygments.token import Token
13 from prompt_toolkit.shortcuts.prompt import PromptSession
13 from prompt_toolkit.shortcuts.prompt import PromptSession
14 from prompt_toolkit.enums import EditingMode
14 from prompt_toolkit.enums import EditingMode
15 from prompt_toolkit.formatted_text import PygmentsTokens
15 from prompt_toolkit.formatted_text import PygmentsTokens
16
16
17 from prompt_toolkit import __version__ as ptk_version
17 from prompt_toolkit import __version__ as ptk_version
18 PTK3 = ptk_version.startswith('3.')
18 PTK3 = ptk_version.startswith('3.')
19
19
20
20
21 class TerminalPdb(Pdb):
21 class TerminalPdb(Pdb):
22 """Standalone IPython debugger."""
22 """Standalone IPython debugger."""
23
23
24 def __init__(self, *args, pt_session_options=None, **kwargs):
24 def __init__(self, *args, pt_session_options=None, **kwargs):
25 Pdb.__init__(self, *args, **kwargs)
25 Pdb.__init__(self, *args, **kwargs)
26 self._ptcomp = None
26 self._ptcomp = None
27 self.pt_init(pt_session_options)
27 self.pt_init(pt_session_options)
28
28
29 def pt_init(self, pt_session_options=None):
29 def pt_init(self, pt_session_options=None):
30 """Initialize the prompt session and the prompt loop
30 """Initialize the prompt session and the prompt loop
31 and store them in self.pt_app and self.pt_loop.
31 and store them in self.pt_app and self.pt_loop.
32
32
33 Additional keyword arguments for the PromptSession class
33 Additional keyword arguments for the PromptSession class
34 can be specified in pt_session_options.
34 can be specified in pt_session_options.
35 """
35 """
36 if pt_session_options is None:
36 if pt_session_options is None:
37 pt_session_options = {}
37 pt_session_options = {}
38
38
39 def get_prompt_tokens():
39 def get_prompt_tokens():
40 return [(Token.Prompt, self.prompt)]
40 return [(Token.Prompt, self.prompt)]
41
41
42 if self._ptcomp is None:
42 if self._ptcomp is None:
43 compl = IPCompleter(
43 compl = IPCompleter(
44 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
44 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
45 )
45 )
46 # add a completer for all the do_ methods
46 # add a completer for all the do_ methods
47 methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
47 methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
48
48
49 def gen_comp(self, text):
49 def gen_comp(self, text):
50 return [m for m in methods_names if m.startswith(text)]
50 return [m for m in methods_names if m.startswith(text)]
51 import types
51 import types
52 newcomp = types.MethodType(gen_comp, compl)
52 newcomp = types.MethodType(gen_comp, compl)
53 compl.custom_matchers.insert(0, newcomp)
53 compl.custom_matchers.insert(0, newcomp)
54 # end add completer.
54 # end add completer.
55
55
56 self._ptcomp = IPythonPTCompleter(compl)
56 self._ptcomp = IPythonPTCompleter(compl)
57
57
58 options = dict(
58 options = dict(
59 message=(lambda: PygmentsTokens(get_prompt_tokens())),
59 message=(lambda: PygmentsTokens(get_prompt_tokens())),
60 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
60 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
61 key_bindings=create_ipython_shortcuts(self.shell),
61 key_bindings=create_ipython_shortcuts(self.shell),
62 history=self.shell.debugger_history,
62 history=self.shell.debugger_history,
63 completer=self._ptcomp,
63 completer=self._ptcomp,
64 enable_history_search=True,
64 enable_history_search=True,
65 mouse_support=self.shell.mouse_support,
65 mouse_support=self.shell.mouse_support,
66 complete_style=self.shell.pt_complete_style,
66 complete_style=self.shell.pt_complete_style,
67 style=self.shell.style,
67 style=self.shell.style,
68 color_depth=self.shell.color_depth,
68 color_depth=self.shell.color_depth,
69 )
69 )
70
70
71 if not PTK3:
71 if not PTK3:
72 options['inputhook'] = self.shell.inputhook
72 options['inputhook'] = self.shell.inputhook
73 options.update(pt_session_options)
73 options.update(pt_session_options)
74 self.pt_loop = asyncio.new_event_loop()
74 self.pt_loop = asyncio.new_event_loop()
75 self.pt_app = PromptSession(**options)
75 self.pt_app = PromptSession(**options)
76
76
77 def cmdloop(self, intro=None):
77 def cmdloop(self, intro=None):
78 """Repeatedly issue a prompt, accept input, parse an initial prefix
78 """Repeatedly issue a prompt, accept input, parse an initial prefix
79 off the received input, and dispatch to action methods, passing them
79 off the received input, and dispatch to action methods, passing them
80 the remainder of the line as argument.
80 the remainder of the line as argument.
81
81
82 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
82 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
83 """
83 """
84 if not self.use_rawinput:
84 if not self.use_rawinput:
85 raise ValueError('Sorry ipdb does not support use_rawinput=False')
85 raise ValueError('Sorry ipdb does not support use_rawinput=False')
86
86
87 # In order to make sure that prompt, which uses asyncio doesn't
87 # In order to make sure that prompt, which uses asyncio doesn't
88 # interfere with applications in which it's used, we always run the
88 # interfere with applications in which it's used, we always run the
89 # prompt itself in a different thread (we can't start an event loop
89 # prompt itself in a different thread (we can't start an event loop
90 # within an event loop). This new thread won't have any event loop
90 # within an event loop). This new thread won't have any event loop
91 # running, and here we run our prompt-loop.
91 # running, and here we run our prompt-loop.
92
92
93 self.preloop()
93 self.preloop()
94
94
95 try:
95 try:
96 if intro is not None:
96 if intro is not None:
97 self.intro = intro
97 self.intro = intro
98 if self.intro:
98 if self.intro:
99 self.stdout.write(str(self.intro)+"\n")
99 self.stdout.write(str(self.intro)+"\n")
100 stop = None
100 stop = None
101 while not stop:
101 while not stop:
102 if self.cmdqueue:
102 if self.cmdqueue:
103 line = self.cmdqueue.pop(0)
103 line = self.cmdqueue.pop(0)
104 else:
104 else:
105 self._ptcomp.ipy_completer.namespace = self.curframe_locals
105 self._ptcomp.ipy_completer.namespace = self.curframe_locals
106 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
106 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
107
107
108 # Run the prompt in a different thread.
108 # Run the prompt in a different thread.
109 line = ''
109 line = ''
110 keyboard_interrupt = False
110 keyboard_interrupt = False
111
111
112 def in_thread():
112 def in_thread():
113 nonlocal line, keyboard_interrupt
113 nonlocal line, keyboard_interrupt
114 try:
114 try:
115 line = self.pt_app.prompt()
115 line = self.pt_app.prompt()
116 except EOFError:
116 except EOFError:
117 line = 'EOF'
117 line = 'EOF'
118 except KeyboardInterrupt:
118 except KeyboardInterrupt:
119 keyboard_interrupt = True
119 keyboard_interrupt = True
120
120
121 th = threading.Thread(target=in_thread)
121 th = threading.Thread(target=in_thread)
122 th.start()
122 th.start()
123 th.join()
123 th.join()
124
124
125 if keyboard_interrupt:
125 if keyboard_interrupt:
126 raise KeyboardInterrupt
126 raise KeyboardInterrupt
127
127
128 line = self.precmd(line)
128 line = self.precmd(line)
129 stop = self.onecmd(line)
129 stop = self.onecmd(line)
130 stop = self.postcmd(stop, line)
130 stop = self.postcmd(stop, line)
131 self.postloop()
131 self.postloop()
132 except Exception:
132 except Exception:
133 raise
133 raise
134
134
135 def do_interact(self, arg):
135 def do_interact(self, arg):
136 ipshell = embed.InteractiveShellEmbed(
136 ipshell = embed.InteractiveShellEmbed(
137 config=self.shell.config,
137 config=self.shell.config,
138 banner1="*interactive*",
138 banner1="*interactive*",
139 exit_msg="now exiting InteractiveConsole...",
139 exit_msg="*exiting interactive console...*",
140 )
140 )
141 global_ns = self.curframe.f_globals
141 global_ns = self.curframe.f_globals
142 ipshell(
142 ipshell(
143 module=sys.modules.get(global_ns["__name__"], None),
143 module=sys.modules.get(global_ns["__name__"], None),
144 local_ns=self.curframe_locals,
144 local_ns=self.curframe_locals,
145 )
145 )
146
146
147
147
148 def set_trace(frame=None):
148 def set_trace(frame=None):
149 """
149 """
150 Start debugging from `frame`.
150 Start debugging from `frame`.
151
151
152 If frame is not specified, debugging starts from caller's frame.
152 If frame is not specified, debugging starts from caller's frame.
153 """
153 """
154 TerminalPdb().set_trace(frame or sys._getframe().f_back)
154 TerminalPdb().set_trace(frame or sys._getframe().f_back)
155
155
156
156
157 if __name__ == '__main__':
157 if __name__ == '__main__':
158 import pdb
158 import pdb
159 # IPython.core.debugger.Pdb.trace_dispatch shall not catch
159 # IPython.core.debugger.Pdb.trace_dispatch shall not catch
160 # bdb.BdbQuit. When started through __main__ and an exception
160 # bdb.BdbQuit. When started through __main__ and an exception
161 # happened after hitting "c", this is needed in order to
161 # happened after hitting "c", this is needed in order to
162 # be able to quit the debugging session (see #9950).
162 # be able to quit the debugging session (see #9950).
163 old_trace_dispatch = pdb.Pdb.trace_dispatch
163 old_trace_dispatch = pdb.Pdb.trace_dispatch
164 pdb.Pdb = TerminalPdb
164 pdb.Pdb = TerminalPdb
165 pdb.Pdb.trace_dispatch = old_trace_dispatch
165 pdb.Pdb.trace_dispatch = old_trace_dispatch
166 pdb.main()
166 pdb.main()
General Comments 0
You need to be logged in to leave comments. Login now