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