##// END OF EJS Templates
Use python-prompt-toolkit for ipdb....
Matthias Bussonnier -
Show More
@@ -1,602 +1,637 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 http://www.python.org/2.2.3/license.html"""
16 http://www.python.org/2.2.3/license.html"""
17
17
18 #*****************************************************************************
18 #*****************************************************************************
19 #
19 #
20 # This file is licensed under the PSF license.
20 # This file is licensed under the PSF license.
21 #
21 #
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 #
24 #
25 #
25 #
26 #*****************************************************************************
26 #*****************************************************************************
27 from __future__ import print_function
27 from __future__ import print_function
28
28
29 import bdb
29 import bdb
30 import functools
30 import functools
31 import inspect
31 import inspect
32 import sys
32 import sys
33
33
34 from IPython import get_ipython
34 from IPython import get_ipython
35 from IPython.utils import PyColorize, ulinecache
35 from IPython.utils import PyColorize, ulinecache
36 from IPython.utils import coloransi, py3compat
36 from IPython.utils import coloransi, py3compat
37 from IPython.core.excolors import exception_colors
37 from IPython.core.excolors import exception_colors
38 from IPython.testing.skipdoctest import skip_doctest
38 from IPython.testing.skipdoctest import skip_doctest
39
39
40 from prompt_toolkit import prompt as ptk_prompt
41
40 prompt = 'ipdb> '
42 prompt = 'ipdb> '
41
43
42 #We have to check this directly from sys.argv, config struct not yet available
44 #We have to check this directly from sys.argv, config struct not yet available
43 from pdb import Pdb as OldPdb
45 from pdb import Pdb as OldPdb
44
46
45 # Allow the set_trace code to operate outside of an ipython instance, even if
47 # Allow the set_trace code to operate outside of an ipython instance, even if
46 # it does so with some limitations. The rest of this support is implemented in
48 # it does so with some limitations. The rest of this support is implemented in
47 # the Tracer constructor.
49 # the Tracer constructor.
48
50
49 def make_arrow(pad):
51 def make_arrow(pad):
50 """generate the leading arrow in front of traceback or debugger"""
52 """generate the leading arrow in front of traceback or debugger"""
51 if pad >= 2:
53 if pad >= 2:
52 return '-'*(pad-2) + '> '
54 return '-'*(pad-2) + '> '
53 elif pad == 1:
55 elif pad == 1:
54 return '>'
56 return '>'
55 return ''
57 return ''
56
58
57
59
58 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
60 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
59 """Exception hook which handles `BdbQuit` exceptions.
61 """Exception hook which handles `BdbQuit` exceptions.
60
62
61 All other exceptions are processed using the `excepthook`
63 All other exceptions are processed using the `excepthook`
62 parameter.
64 parameter.
63 """
65 """
64 if et==bdb.BdbQuit:
66 if et==bdb.BdbQuit:
65 print('Exiting Debugger.')
67 print('Exiting Debugger.')
66 elif excepthook is not None:
68 elif excepthook is not None:
67 excepthook(et, ev, tb)
69 excepthook(et, ev, tb)
68 else:
70 else:
69 # Backwards compatibility. Raise deprecation warning?
71 # Backwards compatibility. Raise deprecation warning?
70 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
72 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
71
73
72 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
74 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
73 print('Exiting Debugger.')
75 print('Exiting Debugger.')
74
76
75
77
76 class Tracer(object):
78 class Tracer(object):
77 """Class for local debugging, similar to pdb.set_trace.
79 """Class for local debugging, similar to pdb.set_trace.
78
80
79 Instances of this class, when called, behave like pdb.set_trace, but
81 Instances of this class, when called, behave like pdb.set_trace, but
80 providing IPython's enhanced capabilities.
82 providing IPython's enhanced capabilities.
81
83
82 This is implemented as a class which must be initialized in your own code
84 This is implemented as a class which must be initialized in your own code
83 and not as a standalone function because we need to detect at runtime
85 and not as a standalone function because we need to detect at runtime
84 whether IPython is already active or not. That detection is done in the
86 whether IPython is already active or not. That detection is done in the
85 constructor, ensuring that this code plays nicely with a running IPython,
87 constructor, ensuring that this code plays nicely with a running IPython,
86 while functioning acceptably (though with limitations) if outside of it.
88 while functioning acceptably (though with limitations) if outside of it.
87 """
89 """
88
90
89 @skip_doctest
91 @skip_doctest
90 def __init__(self, colors=None):
92 def __init__(self, colors=None):
91 """Create a local debugger instance.
93 """Create a local debugger instance.
92
94
93 Parameters
95 Parameters
94 ----------
96 ----------
95
97
96 colors : str, optional
98 colors : str, optional
97 The name of the color scheme to use, it must be one of IPython's
99 The name of the color scheme to use, it must be one of IPython's
98 valid color schemes. If not given, the function will default to
100 valid color schemes. If not given, the function will default to
99 the current IPython scheme when running inside IPython, and to
101 the current IPython scheme when running inside IPython, and to
100 'NoColor' otherwise.
102 'NoColor' otherwise.
101
103
102 Examples
104 Examples
103 --------
105 --------
104 ::
106 ::
105
107
106 from IPython.core.debugger import Tracer; debug_here = Tracer()
108 from IPython.core.debugger import Tracer; debug_here = Tracer()
107
109
108 Later in your code::
110 Later in your code::
109
111
110 debug_here() # -> will open up the debugger at that point.
112 debug_here() # -> will open up the debugger at that point.
111
113
112 Once the debugger activates, you can use all of its regular commands to
114 Once the debugger activates, you can use all of its regular commands to
113 step through code, set breakpoints, etc. See the pdb documentation
115 step through code, set breakpoints, etc. See the pdb documentation
114 from the Python standard library for usage details.
116 from the Python standard library for usage details.
115 """
117 """
116
118
117 ip = get_ipython()
119 ip = get_ipython()
118 if ip is None:
120 if ip is None:
119 # Outside of ipython, we set our own exception hook manually
121 # Outside of ipython, we set our own exception hook manually
120 sys.excepthook = functools.partial(BdbQuit_excepthook,
122 sys.excepthook = functools.partial(BdbQuit_excepthook,
121 excepthook=sys.excepthook)
123 excepthook=sys.excepthook)
122 def_colors = 'NoColor'
124 def_colors = 'NoColor'
123 try:
125 try:
124 # Limited tab completion support
126 # Limited tab completion support
125 import readline
127 import readline
126 readline.parse_and_bind('tab: complete')
128 readline.parse_and_bind('tab: complete')
127 except ImportError:
129 except ImportError:
128 pass
130 pass
129 else:
131 else:
130 # In ipython, we use its custom exception handler mechanism
132 # In ipython, we use its custom exception handler mechanism
131 def_colors = ip.colors
133 def_colors = ip.colors
132 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
134 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
133
135
134 if colors is None:
136 if colors is None:
135 colors = def_colors
137 colors = def_colors
136
138
137 # The stdlib debugger internally uses a modified repr from the `repr`
139 # The stdlib debugger internally uses a modified repr from the `repr`
138 # module, that limits the length of printed strings to a hardcoded
140 # module, that limits the length of printed strings to a hardcoded
139 # limit of 30 characters. That much trimming is too aggressive, let's
141 # limit of 30 characters. That much trimming is too aggressive, let's
140 # at least raise that limit to 80 chars, which should be enough for
142 # at least raise that limit to 80 chars, which should be enough for
141 # most interactive uses.
143 # most interactive uses.
142 try:
144 try:
143 try:
145 try:
144 from reprlib import aRepr # Py 3
146 from reprlib import aRepr # Py 3
145 except ImportError:
147 except ImportError:
146 from repr import aRepr # Py 2
148 from repr import aRepr # Py 2
147 aRepr.maxstring = 80
149 aRepr.maxstring = 80
148 except:
150 except:
149 # This is only a user-facing convenience, so any error we encounter
151 # This is only a user-facing convenience, so any error we encounter
150 # here can be warned about but can be otherwise ignored. These
152 # here can be warned about but can be otherwise ignored. These
151 # printouts will tell us about problems if this API changes
153 # printouts will tell us about problems if this API changes
152 import traceback
154 import traceback
153 traceback.print_exc()
155 traceback.print_exc()
154
156
155 self.debugger = Pdb(colors)
157 self.debugger = Pdb(colors)
156
158
157 def __call__(self):
159 def __call__(self):
158 """Starts an interactive debugger at the point where called.
160 """Starts an interactive debugger at the point where called.
159
161
160 This is similar to the pdb.set_trace() function from the std lib, but
162 This is similar to the pdb.set_trace() function from the std lib, but
161 using IPython's enhanced debugger."""
163 using IPython's enhanced debugger."""
162
164
163 self.debugger.set_trace(sys._getframe().f_back)
165 self.debugger.set_trace(sys._getframe().f_back)
164
166
165
167
166 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
168 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
167 """Make new_fn have old_fn's doc string. This is particularly useful
169 """Make new_fn have old_fn's doc string. This is particularly useful
168 for the ``do_...`` commands that hook into the help system.
170 for the ``do_...`` commands that hook into the help system.
169 Adapted from from a comp.lang.python posting
171 Adapted from from a comp.lang.python posting
170 by Duncan Booth."""
172 by Duncan Booth."""
171 def wrapper(*args, **kw):
173 def wrapper(*args, **kw):
172 return new_fn(*args, **kw)
174 return new_fn(*args, **kw)
173 if old_fn.__doc__:
175 if old_fn.__doc__:
174 wrapper.__doc__ = old_fn.__doc__ + additional_text
176 wrapper.__doc__ = old_fn.__doc__ + additional_text
175 return wrapper
177 return wrapper
176
178
177
179
178 def _file_lines(fname):
180 def _file_lines(fname):
179 """Return the contents of a named file as a list of lines.
181 """Return the contents of a named file as a list of lines.
180
182
181 This function never raises an IOError exception: if the file can't be
183 This function never raises an IOError exception: if the file can't be
182 read, it simply returns an empty list."""
184 read, it simply returns an empty list."""
183
185
184 try:
186 try:
185 outfile = open(fname)
187 outfile = open(fname)
186 except IOError:
188 except IOError:
187 return []
189 return []
188 else:
190 else:
189 out = outfile.readlines()
191 out = outfile.readlines()
190 outfile.close()
192 outfile.close()
191 return out
193 return out
192
194
193
195
194 class Pdb(OldPdb, object):
196 class Pdb(OldPdb, object):
195 """Modified Pdb class, does not load readline."""
197 """Modified Pdb class, does not load readline."""
196
198
197 def __init__(self,color_scheme='NoColor',completekey=None,
199 def __init__(self,color_scheme='NoColor',completekey=None,
198 stdin=None, stdout=None, context=5):
200 stdin=None, stdout=None, context=5):
199
201
200 # Parent constructor:
202 # Parent constructor:
201 try:
203 try:
202 self.context=int(context)
204 self.context=int(context)
203 if self.context <= 0:
205 if self.context <= 0:
204 raise ValueError("Context must be a positive integer")
206 raise ValueError("Context must be a positive integer")
205 except (TypeError, ValueError):
207 except (TypeError, ValueError):
206 raise ValueError("Context must be a positive integer")
208 raise ValueError("Context must be a positive integer")
207
209
208 OldPdb.__init__(self,completekey,stdin,stdout)
210 OldPdb.__init__(self,completekey,stdin,stdout)
209
211
210 # IPython changes...
212 # IPython changes...
211 self.shell = get_ipython()
213 self.shell = get_ipython()
212
214
213 if self.shell is None:
215 if self.shell is None:
214 # No IPython instance running, we must create one
216 # No IPython instance running, we must create one
215 from IPython.terminal.interactiveshell import \
217 from IPython.terminal.interactiveshell import \
216 TerminalInteractiveShell
218 TerminalInteractiveShell
217 self.shell = TerminalInteractiveShell.instance()
219 self.shell = TerminalInteractiveShell.instance()
218
220
219 self.aliases = {}
221 self.aliases = {}
220
222
221 # Create color table: we copy the default one from the traceback
223 # Create color table: we copy the default one from the traceback
222 # module and add a few attributes needed for debugging
224 # module and add a few attributes needed for debugging
223 self.color_scheme_table = exception_colors()
225 self.color_scheme_table = exception_colors()
224
226
225 # shorthands
227 # shorthands
226 C = coloransi.TermColors
228 C = coloransi.TermColors
227 cst = self.color_scheme_table
229 cst = self.color_scheme_table
228
230
229 cst['NoColor'].colors.prompt = C.NoColor
231 cst['NoColor'].colors.prompt = C.NoColor
230 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
232 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
231 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
233 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
232
234
233 cst['Linux'].colors.prompt = C.Green
235 cst['Linux'].colors.prompt = C.Green
234 cst['Linux'].colors.breakpoint_enabled = C.LightRed
236 cst['Linux'].colors.breakpoint_enabled = C.LightRed
235 cst['Linux'].colors.breakpoint_disabled = C.Red
237 cst['Linux'].colors.breakpoint_disabled = C.Red
236
238
237 cst['LightBG'].colors.prompt = C.Blue
239 cst['LightBG'].colors.prompt = C.Blue
238 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
240 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
239 cst['LightBG'].colors.breakpoint_disabled = C.Red
241 cst['LightBG'].colors.breakpoint_disabled = C.Red
240
242
241 self.set_colors(color_scheme)
243 self.set_colors(color_scheme)
242
244
243 # Add a python parser so we can syntax highlight source while
245 # Add a python parser so we can syntax highlight source while
244 # debugging.
246 # debugging.
245 self.parser = PyColorize.Parser()
247 self.parser = PyColorize.Parser()
246
248
247 # Set the prompt - the default prompt is '(Pdb)'
249 # Set the prompt - the default prompt is '(Pdb)'
248 Colors = cst.active_colors
250 self.prompt = prompt
249 if color_scheme == 'NoColor':
251
250 self.prompt = prompt
252
251 else:
253 def cmdloop(self, intro=None):
252 # The colour markers are wrapped by bytes 01 and 02 so that readline
254 """Repeatedly issue a prompt, accept input, parse an initial prefix
253 # can calculate the width.
255 off the received input, and dispatch to action methods, passing them
254 self.prompt = u'\x01%s\x02%s\x01%s\x02' % (Colors.prompt, prompt, Colors.Normal)
256 the remainder of the line as argument.
257
258 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
259 """
260 if not self.use_rawinput:
261 raise ValueError('Sorry ipdb does not support raw_input=False')
262
263 def get_prompt_tokens(cli):
264 from pygments.token import Token
265 return [(Token.Prompt, self.prompt)]
266
267 self.preloop()
268 try:
269 if intro is not None:
270 self.intro = intro
271 if self.intro:
272 self.stdout.write(str(self.intro)+"\n")
273 stop = None
274 while not stop:
275 if self.cmdqueue:
276 line = self.cmdqueue.pop(0)
277 else:
278 try:
279 line = ptk_prompt(get_prompt_tokens=get_prompt_tokens)
280 except EOFError:
281 line = 'EOF'
282 line = self.precmd(line)
283 stop = self.onecmd(line)
284 stop = self.postcmd(stop, line)
285 self.postloop()
286 except Exception:
287 pass
288
289
255
290
256 def set_colors(self, scheme):
291 def set_colors(self, scheme):
257 """Shorthand access to the color table scheme selector method."""
292 """Shorthand access to the color table scheme selector method."""
258 self.color_scheme_table.set_active_scheme(scheme)
293 self.color_scheme_table.set_active_scheme(scheme)
259
294
260 def interaction(self, frame, traceback):
295 def interaction(self, frame, traceback):
261 self.shell.set_completer_frame(frame)
296 self.shell.set_completer_frame(frame)
262 while True:
297 while True:
263 try:
298 try:
264 OldPdb.interaction(self, frame, traceback)
299 OldPdb.interaction(self, frame, traceback)
265 break
300 break
266 except KeyboardInterrupt:
301 except KeyboardInterrupt:
267 self.shell.write('\n' + self.shell.get_exception_only())
302 self.shell.write('\n' + self.shell.get_exception_only())
268 break
303 break
269 finally:
304 finally:
270 # Pdb sets readline delimiters, so set them back to our own
305 # Pdb sets readline delimiters, so set them back to our own
271 if self.shell.readline is not None:
306 if self.shell.readline is not None:
272 self.shell.readline.set_completer_delims(self.shell.readline_delims)
307 self.shell.readline.set_completer_delims(self.shell.readline_delims)
273
308
274 def parseline(self, line):
309 def parseline(self, line):
275 if line.startswith("!!"):
310 if line.startswith("!!"):
276 # Force standard behavior.
311 # Force standard behavior.
277 return super(Pdb, self).parseline(line[2:])
312 return super(Pdb, self).parseline(line[2:])
278 # "Smart command mode" from pdb++: don't execute commands if a variable
313 # "Smart command mode" from pdb++: don't execute commands if a variable
279 # with the same name exists.
314 # with the same name exists.
280 cmd, arg, newline = super(Pdb, self).parseline(line)
315 cmd, arg, newline = super(Pdb, self).parseline(line)
281 if cmd in self.curframe.f_globals or cmd in self.curframe.f_locals:
316 if cmd in self.curframe.f_globals or cmd in self.curframe.f_locals:
282 return super(Pdb, self).parseline("!" + line)
317 return super(Pdb, self).parseline("!" + line)
283 return super(Pdb, self).parseline(line)
318 return super(Pdb, self).parseline(line)
284
319
285 def new_do_up(self, arg):
320 def new_do_up(self, arg):
286 OldPdb.do_up(self, arg)
321 OldPdb.do_up(self, arg)
287 self.shell.set_completer_frame(self.curframe)
322 self.shell.set_completer_frame(self.curframe)
288 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
323 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
289
324
290 def new_do_down(self, arg):
325 def new_do_down(self, arg):
291 OldPdb.do_down(self, arg)
326 OldPdb.do_down(self, arg)
292 self.shell.set_completer_frame(self.curframe)
327 self.shell.set_completer_frame(self.curframe)
293
328
294 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
329 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
295
330
296 def new_do_frame(self, arg):
331 def new_do_frame(self, arg):
297 OldPdb.do_frame(self, arg)
332 OldPdb.do_frame(self, arg)
298 self.shell.set_completer_frame(self.curframe)
333 self.shell.set_completer_frame(self.curframe)
299
334
300 def new_do_quit(self, arg):
335 def new_do_quit(self, arg):
301
336
302 if hasattr(self, 'old_all_completions'):
337 if hasattr(self, 'old_all_completions'):
303 self.shell.Completer.all_completions=self.old_all_completions
338 self.shell.Completer.all_completions=self.old_all_completions
304
339
305 return OldPdb.do_quit(self, arg)
340 return OldPdb.do_quit(self, arg)
306
341
307 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
342 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
308
343
309 def new_do_restart(self, arg):
344 def new_do_restart(self, arg):
310 """Restart command. In the context of ipython this is exactly the same
345 """Restart command. In the context of ipython this is exactly the same
311 thing as 'quit'."""
346 thing as 'quit'."""
312 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
347 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
313 return self.do_quit(arg)
348 return self.do_quit(arg)
314
349
315 def postloop(self):
350 def postloop(self):
316 self.shell.set_completer_frame(None)
351 self.shell.set_completer_frame(None)
317
352
318 def print_stack_trace(self, context=None):
353 def print_stack_trace(self, context=None):
319 if context is None:
354 if context is None:
320 context = self.context
355 context = self.context
321 try:
356 try:
322 context=int(context)
357 context=int(context)
323 if context <= 0:
358 if context <= 0:
324 raise ValueError("Context must be a positive integer")
359 raise ValueError("Context must be a positive integer")
325 except (TypeError, ValueError):
360 except (TypeError, ValueError):
326 raise ValueError("Context must be a positive integer")
361 raise ValueError("Context must be a positive integer")
327 try:
362 try:
328 for frame_lineno in self.stack:
363 for frame_lineno in self.stack:
329 self.print_stack_entry(frame_lineno, context=context)
364 self.print_stack_entry(frame_lineno, context=context)
330 except KeyboardInterrupt:
365 except KeyboardInterrupt:
331 pass
366 pass
332
367
333 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
368 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
334 context=None):
369 context=None):
335 if context is None:
370 if context is None:
336 context = self.context
371 context = self.context
337 try:
372 try:
338 context=int(context)
373 context=int(context)
339 if context <= 0:
374 if context <= 0:
340 raise ValueError("Context must be a positive integer")
375 raise ValueError("Context must be a positive integer")
341 except (TypeError, ValueError):
376 except (TypeError, ValueError):
342 raise ValueError("Context must be a positive integer")
377 raise ValueError("Context must be a positive integer")
343 print(self.format_stack_entry(frame_lineno, '', context))
378 print(self.format_stack_entry(frame_lineno, '', context))
344
379
345 # vds: >>
380 # vds: >>
346 frame, lineno = frame_lineno
381 frame, lineno = frame_lineno
347 filename = frame.f_code.co_filename
382 filename = frame.f_code.co_filename
348 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
383 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
349 # vds: <<
384 # vds: <<
350
385
351 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
386 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
352 if context is None:
387 if context is None:
353 context = self.context
388 context = self.context
354 try:
389 try:
355 context=int(context)
390 context=int(context)
356 if context <= 0:
391 if context <= 0:
357 print("Context must be a positive integer")
392 print("Context must be a positive integer")
358 except (TypeError, ValueError):
393 except (TypeError, ValueError):
359 print("Context must be a positive integer")
394 print("Context must be a positive integer")
360 try:
395 try:
361 import reprlib # Py 3
396 import reprlib # Py 3
362 except ImportError:
397 except ImportError:
363 import repr as reprlib # Py 2
398 import repr as reprlib # Py 2
364
399
365 ret = []
400 ret = []
366
401
367 Colors = self.color_scheme_table.active_colors
402 Colors = self.color_scheme_table.active_colors
368 ColorsNormal = Colors.Normal
403 ColorsNormal = Colors.Normal
369 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
404 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
370 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
405 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
371 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
406 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
372 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
407 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
373 ColorsNormal)
408 ColorsNormal)
374
409
375 frame, lineno = frame_lineno
410 frame, lineno = frame_lineno
376
411
377 return_value = ''
412 return_value = ''
378 if '__return__' in frame.f_locals:
413 if '__return__' in frame.f_locals:
379 rv = frame.f_locals['__return__']
414 rv = frame.f_locals['__return__']
380 #return_value += '->'
415 #return_value += '->'
381 return_value += reprlib.repr(rv) + '\n'
416 return_value += reprlib.repr(rv) + '\n'
382 ret.append(return_value)
417 ret.append(return_value)
383
418
384 #s = filename + '(' + `lineno` + ')'
419 #s = filename + '(' + `lineno` + ')'
385 filename = self.canonic(frame.f_code.co_filename)
420 filename = self.canonic(frame.f_code.co_filename)
386 link = tpl_link % py3compat.cast_unicode(filename)
421 link = tpl_link % py3compat.cast_unicode(filename)
387
422
388 if frame.f_code.co_name:
423 if frame.f_code.co_name:
389 func = frame.f_code.co_name
424 func = frame.f_code.co_name
390 else:
425 else:
391 func = "<lambda>"
426 func = "<lambda>"
392
427
393 call = ''
428 call = ''
394 if func != '?':
429 if func != '?':
395 if '__args__' in frame.f_locals:
430 if '__args__' in frame.f_locals:
396 args = reprlib.repr(frame.f_locals['__args__'])
431 args = reprlib.repr(frame.f_locals['__args__'])
397 else:
432 else:
398 args = '()'
433 args = '()'
399 call = tpl_call % (func, args)
434 call = tpl_call % (func, args)
400
435
401 # The level info should be generated in the same format pdb uses, to
436 # The level info should be generated in the same format pdb uses, to
402 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
437 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
403 if frame is self.curframe:
438 if frame is self.curframe:
404 ret.append('> ')
439 ret.append('> ')
405 else:
440 else:
406 ret.append(' ')
441 ret.append(' ')
407 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
442 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
408
443
409 start = lineno - 1 - context//2
444 start = lineno - 1 - context//2
410 lines = ulinecache.getlines(filename)
445 lines = ulinecache.getlines(filename)
411 start = min(start, len(lines) - context)
446 start = min(start, len(lines) - context)
412 start = max(start, 0)
447 start = max(start, 0)
413 lines = lines[start : start + context]
448 lines = lines[start : start + context]
414
449
415 for i,line in enumerate(lines):
450 for i,line in enumerate(lines):
416 show_arrow = (start + 1 + i == lineno)
451 show_arrow = (start + 1 + i == lineno)
417 linetpl = (frame is self.curframe or show_arrow) \
452 linetpl = (frame is self.curframe or show_arrow) \
418 and tpl_line_em \
453 and tpl_line_em \
419 or tpl_line
454 or tpl_line
420 ret.append(self.__format_line(linetpl, filename,
455 ret.append(self.__format_line(linetpl, filename,
421 start + 1 + i, line,
456 start + 1 + i, line,
422 arrow = show_arrow) )
457 arrow = show_arrow) )
423 return ''.join(ret)
458 return ''.join(ret)
424
459
425 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
460 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
426 bp_mark = ""
461 bp_mark = ""
427 bp_mark_color = ""
462 bp_mark_color = ""
428
463
429 scheme = self.color_scheme_table.active_scheme_name
464 scheme = self.color_scheme_table.active_scheme_name
430 new_line, err = self.parser.format2(line, 'str', scheme)
465 new_line, err = self.parser.format2(line, 'str', scheme)
431 if not err: line = new_line
466 if not err: line = new_line
432
467
433 bp = None
468 bp = None
434 if lineno in self.get_file_breaks(filename):
469 if lineno in self.get_file_breaks(filename):
435 bps = self.get_breaks(filename, lineno)
470 bps = self.get_breaks(filename, lineno)
436 bp = bps[-1]
471 bp = bps[-1]
437
472
438 if bp:
473 if bp:
439 Colors = self.color_scheme_table.active_colors
474 Colors = self.color_scheme_table.active_colors
440 bp_mark = str(bp.number)
475 bp_mark = str(bp.number)
441 bp_mark_color = Colors.breakpoint_enabled
476 bp_mark_color = Colors.breakpoint_enabled
442 if not bp.enabled:
477 if not bp.enabled:
443 bp_mark_color = Colors.breakpoint_disabled
478 bp_mark_color = Colors.breakpoint_disabled
444
479
445 numbers_width = 7
480 numbers_width = 7
446 if arrow:
481 if arrow:
447 # This is the line with the error
482 # This is the line with the error
448 pad = numbers_width - len(str(lineno)) - len(bp_mark)
483 pad = numbers_width - len(str(lineno)) - len(bp_mark)
449 num = '%s%s' % (make_arrow(pad), str(lineno))
484 num = '%s%s' % (make_arrow(pad), str(lineno))
450 else:
485 else:
451 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
486 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
452
487
453 return tpl_line % (bp_mark_color + bp_mark, num, line)
488 return tpl_line % (bp_mark_color + bp_mark, num, line)
454
489
455
490
456 def print_list_lines(self, filename, first, last):
491 def print_list_lines(self, filename, first, last):
457 """The printing (as opposed to the parsing part of a 'list'
492 """The printing (as opposed to the parsing part of a 'list'
458 command."""
493 command."""
459 try:
494 try:
460 Colors = self.color_scheme_table.active_colors
495 Colors = self.color_scheme_table.active_colors
461 ColorsNormal = Colors.Normal
496 ColorsNormal = Colors.Normal
462 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
497 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
463 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
498 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
464 src = []
499 src = []
465 if filename == "<string>" and hasattr(self, "_exec_filename"):
500 if filename == "<string>" and hasattr(self, "_exec_filename"):
466 filename = self._exec_filename
501 filename = self._exec_filename
467
502
468 for lineno in range(first, last+1):
503 for lineno in range(first, last+1):
469 line = ulinecache.getline(filename, lineno)
504 line = ulinecache.getline(filename, lineno)
470 if not line:
505 if not line:
471 break
506 break
472
507
473 if lineno == self.curframe.f_lineno:
508 if lineno == self.curframe.f_lineno:
474 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
509 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
475 else:
510 else:
476 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
511 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
477
512
478 src.append(line)
513 src.append(line)
479 self.lineno = lineno
514 self.lineno = lineno
480
515
481 print(''.join(src))
516 print(''.join(src))
482
517
483 except KeyboardInterrupt:
518 except KeyboardInterrupt:
484 pass
519 pass
485
520
486 def do_list(self, arg):
521 def do_list(self, arg):
487 self.lastcmd = 'list'
522 self.lastcmd = 'list'
488 last = None
523 last = None
489 if arg:
524 if arg:
490 try:
525 try:
491 x = eval(arg, {}, {})
526 x = eval(arg, {}, {})
492 if type(x) == type(()):
527 if type(x) == type(()):
493 first, last = x
528 first, last = x
494 first = int(first)
529 first = int(first)
495 last = int(last)
530 last = int(last)
496 if last < first:
531 if last < first:
497 # Assume it's a count
532 # Assume it's a count
498 last = first + last
533 last = first + last
499 else:
534 else:
500 first = max(1, int(x) - 5)
535 first = max(1, int(x) - 5)
501 except:
536 except:
502 print('*** Error in argument:', repr(arg))
537 print('*** Error in argument:', repr(arg))
503 return
538 return
504 elif self.lineno is None:
539 elif self.lineno is None:
505 first = max(1, self.curframe.f_lineno - 5)
540 first = max(1, self.curframe.f_lineno - 5)
506 else:
541 else:
507 first = self.lineno + 1
542 first = self.lineno + 1
508 if last is None:
543 if last is None:
509 last = first + 10
544 last = first + 10
510 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
545 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
511
546
512 # vds: >>
547 # vds: >>
513 lineno = first
548 lineno = first
514 filename = self.curframe.f_code.co_filename
549 filename = self.curframe.f_code.co_filename
515 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
550 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
516 # vds: <<
551 # vds: <<
517
552
518 do_l = do_list
553 do_l = do_list
519
554
520 def getsourcelines(self, obj):
555 def getsourcelines(self, obj):
521 lines, lineno = inspect.findsource(obj)
556 lines, lineno = inspect.findsource(obj)
522 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
557 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
523 # must be a module frame: do not try to cut a block out of it
558 # must be a module frame: do not try to cut a block out of it
524 return lines, 1
559 return lines, 1
525 elif inspect.ismodule(obj):
560 elif inspect.ismodule(obj):
526 return lines, 1
561 return lines, 1
527 return inspect.getblock(lines[lineno:]), lineno+1
562 return inspect.getblock(lines[lineno:]), lineno+1
528
563
529 def do_longlist(self, arg):
564 def do_longlist(self, arg):
530 self.lastcmd = 'longlist'
565 self.lastcmd = 'longlist'
531 try:
566 try:
532 lines, lineno = self.getsourcelines(self.curframe)
567 lines, lineno = self.getsourcelines(self.curframe)
533 except OSError as err:
568 except OSError as err:
534 self.error(err)
569 self.error(err)
535 return
570 return
536 last = lineno + len(lines)
571 last = lineno + len(lines)
537 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
572 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
538 do_ll = do_longlist
573 do_ll = do_longlist
539
574
540 def do_pdef(self, arg):
575 def do_pdef(self, arg):
541 """Print the call signature for any callable object.
576 """Print the call signature for any callable object.
542
577
543 The debugger interface to %pdef"""
578 The debugger interface to %pdef"""
544 namespaces = [('Locals', self.curframe.f_locals),
579 namespaces = [('Locals', self.curframe.f_locals),
545 ('Globals', self.curframe.f_globals)]
580 ('Globals', self.curframe.f_globals)]
546 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
581 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
547
582
548 def do_pdoc(self, arg):
583 def do_pdoc(self, arg):
549 """Print the docstring for an object.
584 """Print the docstring for an object.
550
585
551 The debugger interface to %pdoc."""
586 The debugger interface to %pdoc."""
552 namespaces = [('Locals', self.curframe.f_locals),
587 namespaces = [('Locals', self.curframe.f_locals),
553 ('Globals', self.curframe.f_globals)]
588 ('Globals', self.curframe.f_globals)]
554 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
589 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
555
590
556 def do_pfile(self, arg):
591 def do_pfile(self, arg):
557 """Print (or run through pager) the file where an object is defined.
592 """Print (or run through pager) the file where an object is defined.
558
593
559 The debugger interface to %pfile.
594 The debugger interface to %pfile.
560 """
595 """
561 namespaces = [('Locals', self.curframe.f_locals),
596 namespaces = [('Locals', self.curframe.f_locals),
562 ('Globals', self.curframe.f_globals)]
597 ('Globals', self.curframe.f_globals)]
563 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
598 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
564
599
565 def do_pinfo(self, arg):
600 def do_pinfo(self, arg):
566 """Provide detailed information about an object.
601 """Provide detailed information about an object.
567
602
568 The debugger interface to %pinfo, i.e., obj?."""
603 The debugger interface to %pinfo, i.e., obj?."""
569 namespaces = [('Locals', self.curframe.f_locals),
604 namespaces = [('Locals', self.curframe.f_locals),
570 ('Globals', self.curframe.f_globals)]
605 ('Globals', self.curframe.f_globals)]
571 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
606 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
572
607
573 def do_pinfo2(self, arg):
608 def do_pinfo2(self, arg):
574 """Provide extra detailed information about an object.
609 """Provide extra detailed information about an object.
575
610
576 The debugger interface to %pinfo2, i.e., obj??."""
611 The debugger interface to %pinfo2, i.e., obj??."""
577 namespaces = [('Locals', self.curframe.f_locals),
612 namespaces = [('Locals', self.curframe.f_locals),
578 ('Globals', self.curframe.f_globals)]
613 ('Globals', self.curframe.f_globals)]
579 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
614 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
580
615
581 def do_psource(self, arg):
616 def do_psource(self, arg):
582 """Print (or run through pager) the source code for an object."""
617 """Print (or run through pager) the source code for an object."""
583 namespaces = [('Locals', self.curframe.f_locals),
618 namespaces = [('Locals', self.curframe.f_locals),
584 ('Globals', self.curframe.f_globals)]
619 ('Globals', self.curframe.f_globals)]
585 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
620 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
586
621
587 if sys.version_info > (3, ):
622 if sys.version_info > (3, ):
588 def do_where(self, arg):
623 def do_where(self, arg):
589 """w(here)
624 """w(here)
590 Print a stack trace, with the most recent frame at the bottom.
625 Print a stack trace, with the most recent frame at the bottom.
591 An arrow indicates the "current frame", which determines the
626 An arrow indicates the "current frame", which determines the
592 context of most commands. 'bt' is an alias for this command.
627 context of most commands. 'bt' is an alias for this command.
593
628
594 Take a number as argument as an (optional) number of context line to
629 Take a number as argument as an (optional) number of context line to
595 print"""
630 print"""
596 if arg:
631 if arg:
597 context = int(arg)
632 context = int(arg)
598 self.print_stack_trace(context)
633 self.print_stack_trace(context)
599 else:
634 else:
600 self.print_stack_trace()
635 self.print_stack_trace()
601
636
602 do_w = do_where
637 do_w = do_where
General Comments 0
You need to be logged in to leave comments. Login now