##// END OF EJS Templates
catch KeyboardInterrupt in debug...
MinRK -
Show More
@@ -1,571 +1,577 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 linecache
31 import linecache
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, io, py3compat
36 from IPython.utils import coloransi, io, py3compat
37 from IPython.core.excolors import exception_colors
37 from IPython.core.excolors import exception_colors
38
38
39 # See if we can use pydb.
39 # See if we can use pydb.
40 has_pydb = False
40 has_pydb = False
41 prompt = 'ipdb> '
41 prompt = 'ipdb> '
42 #We have to check this directly from sys.argv, config struct not yet available
42 #We have to check this directly from sys.argv, config struct not yet available
43 if '--pydb' in sys.argv:
43 if '--pydb' in sys.argv:
44 try:
44 try:
45 import pydb
45 import pydb
46 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
46 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
47 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
47 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
48 # better protect against it.
48 # better protect against it.
49 has_pydb = True
49 has_pydb = True
50 except ImportError:
50 except ImportError:
51 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
51 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
52
52
53 if has_pydb:
53 if has_pydb:
54 from pydb import Pdb as OldPdb
54 from pydb import Pdb as OldPdb
55 #print "Using pydb for %run -d and post-mortem" #dbg
55 #print "Using pydb for %run -d and post-mortem" #dbg
56 prompt = 'ipydb> '
56 prompt = 'ipydb> '
57 else:
57 else:
58 from pdb import Pdb as OldPdb
58 from pdb import Pdb as OldPdb
59
59
60 # Allow the set_trace code to operate outside of an ipython instance, even if
60 # Allow the set_trace code to operate outside of an ipython instance, even if
61 # it does so with some limitations. The rest of this support is implemented in
61 # it does so with some limitations. The rest of this support is implemented in
62 # the Tracer constructor.
62 # the Tracer constructor.
63 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
63 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
64 """Exception hook which handles `BdbQuit` exceptions.
64 """Exception hook which handles `BdbQuit` exceptions.
65
65
66 All other exceptions are processed using the `excepthook`
66 All other exceptions are processed using the `excepthook`
67 parameter.
67 parameter.
68 """
68 """
69 if et==bdb.BdbQuit:
69 if et==bdb.BdbQuit:
70 print('Exiting Debugger.')
70 print('Exiting Debugger.')
71 elif excepthook is not None:
71 elif excepthook is not None:
72 excepthook(et, ev, tb)
72 excepthook(et, ev, tb)
73 else:
73 else:
74 # Backwards compatibility. Raise deprecation warning?
74 # Backwards compatibility. Raise deprecation warning?
75 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
75 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
76
76
77 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
77 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
78 print('Exiting Debugger.')
78 print('Exiting Debugger.')
79
79
80
80
81 class Tracer(object):
81 class Tracer(object):
82 """Class for local debugging, similar to pdb.set_trace.
82 """Class for local debugging, similar to pdb.set_trace.
83
83
84 Instances of this class, when called, behave like pdb.set_trace, but
84 Instances of this class, when called, behave like pdb.set_trace, but
85 providing IPython's enhanced capabilities.
85 providing IPython's enhanced capabilities.
86
86
87 This is implemented as a class which must be initialized in your own code
87 This is implemented as a class which must be initialized in your own code
88 and not as a standalone function because we need to detect at runtime
88 and not as a standalone function because we need to detect at runtime
89 whether IPython is already active or not. That detection is done in the
89 whether IPython is already active or not. That detection is done in the
90 constructor, ensuring that this code plays nicely with a running IPython,
90 constructor, ensuring that this code plays nicely with a running IPython,
91 while functioning acceptably (though with limitations) if outside of it.
91 while functioning acceptably (though with limitations) if outside of it.
92 """
92 """
93
93
94 def __init__(self,colors=None):
94 def __init__(self,colors=None):
95 """Create a local debugger instance.
95 """Create a local debugger instance.
96
96
97 :Parameters:
97 :Parameters:
98
98
99 - `colors` (None): a string containing the name of the color scheme to
99 - `colors` (None): a string containing the name of the color scheme to
100 use, it must be one of IPython's valid color schemes. If not given, the
100 use, it must be one of IPython's valid color schemes. If not given, the
101 function will default to the current IPython scheme when running inside
101 function will default to the current IPython scheme when running inside
102 IPython, and to 'NoColor' otherwise.
102 IPython, and to 'NoColor' otherwise.
103
103
104 Usage example:
104 Usage example:
105
105
106 from IPython.core.debugger import Tracer; debug_here = Tracer()
106 from IPython.core.debugger import Tracer; debug_here = Tracer()
107
107
108 ... later in your code
108 ... later in your code
109 debug_here() # -> will open up the debugger at that point.
109 debug_here() # -> will open up the debugger at that point.
110
110
111 Once the debugger activates, you can use all of its regular commands to
111 Once the debugger activates, you can use all of its regular commands to
112 step through code, set breakpoints, etc. See the pdb documentation
112 step through code, set breakpoints, etc. See the pdb documentation
113 from the Python standard library for usage details.
113 from the Python standard library for usage details.
114 """
114 """
115
115
116 ip = get_ipython()
116 ip = get_ipython()
117 if ip is None:
117 if ip is None:
118 # Outside of ipython, we set our own exception hook manually
118 # Outside of ipython, we set our own exception hook manually
119 sys.excepthook = functools.partial(BdbQuit_excepthook,
119 sys.excepthook = functools.partial(BdbQuit_excepthook,
120 excepthook=sys.excepthook)
120 excepthook=sys.excepthook)
121 def_colors = 'NoColor'
121 def_colors = 'NoColor'
122 try:
122 try:
123 # Limited tab completion support
123 # Limited tab completion support
124 import readline
124 import readline
125 readline.parse_and_bind('tab: complete')
125 readline.parse_and_bind('tab: complete')
126 except ImportError:
126 except ImportError:
127 pass
127 pass
128 else:
128 else:
129 # In ipython, we use its custom exception handler mechanism
129 # In ipython, we use its custom exception handler mechanism
130 def_colors = ip.colors
130 def_colors = ip.colors
131 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
131 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
132
132
133 if colors is None:
133 if colors is None:
134 colors = def_colors
134 colors = def_colors
135
135
136 # The stdlib debugger internally uses a modified repr from the `repr`
136 # The stdlib debugger internally uses a modified repr from the `repr`
137 # module, that limits the length of printed strings to a hardcoded
137 # module, that limits the length of printed strings to a hardcoded
138 # limit of 30 characters. That much trimming is too aggressive, let's
138 # limit of 30 characters. That much trimming is too aggressive, let's
139 # at least raise that limit to 80 chars, which should be enough for
139 # at least raise that limit to 80 chars, which should be enough for
140 # most interactive uses.
140 # most interactive uses.
141 try:
141 try:
142 from repr import aRepr
142 from repr import aRepr
143 aRepr.maxstring = 80
143 aRepr.maxstring = 80
144 except:
144 except:
145 # This is only a user-facing convenience, so any error we encounter
145 # This is only a user-facing convenience, so any error we encounter
146 # here can be warned about but can be otherwise ignored. These
146 # here can be warned about but can be otherwise ignored. These
147 # printouts will tell us about problems if this API changes
147 # printouts will tell us about problems if this API changes
148 import traceback
148 import traceback
149 traceback.print_exc()
149 traceback.print_exc()
150
150
151 self.debugger = Pdb(colors)
151 self.debugger = Pdb(colors)
152
152
153 def __call__(self):
153 def __call__(self):
154 """Starts an interactive debugger at the point where called.
154 """Starts an interactive debugger at the point where called.
155
155
156 This is similar to the pdb.set_trace() function from the std lib, but
156 This is similar to the pdb.set_trace() function from the std lib, but
157 using IPython's enhanced debugger."""
157 using IPython's enhanced debugger."""
158
158
159 self.debugger.set_trace(sys._getframe().f_back)
159 self.debugger.set_trace(sys._getframe().f_back)
160
160
161
161
162 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
162 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
163 """Make new_fn have old_fn's doc string. This is particularly useful
163 """Make new_fn have old_fn's doc string. This is particularly useful
164 for the ``do_...`` commands that hook into the help system.
164 for the ``do_...`` commands that hook into the help system.
165 Adapted from from a comp.lang.python posting
165 Adapted from from a comp.lang.python posting
166 by Duncan Booth."""
166 by Duncan Booth."""
167 def wrapper(*args, **kw):
167 def wrapper(*args, **kw):
168 return new_fn(*args, **kw)
168 return new_fn(*args, **kw)
169 if old_fn.__doc__:
169 if old_fn.__doc__:
170 wrapper.__doc__ = old_fn.__doc__ + additional_text
170 wrapper.__doc__ = old_fn.__doc__ + additional_text
171 return wrapper
171 return wrapper
172
172
173
173
174 def _file_lines(fname):
174 def _file_lines(fname):
175 """Return the contents of a named file as a list of lines.
175 """Return the contents of a named file as a list of lines.
176
176
177 This function never raises an IOError exception: if the file can't be
177 This function never raises an IOError exception: if the file can't be
178 read, it simply returns an empty list."""
178 read, it simply returns an empty list."""
179
179
180 try:
180 try:
181 outfile = open(fname)
181 outfile = open(fname)
182 except IOError:
182 except IOError:
183 return []
183 return []
184 else:
184 else:
185 out = outfile.readlines()
185 out = outfile.readlines()
186 outfile.close()
186 outfile.close()
187 return out
187 return out
188
188
189
189
190 class Pdb(OldPdb):
190 class Pdb(OldPdb):
191 """Modified Pdb class, does not load readline."""
191 """Modified Pdb class, does not load readline."""
192
192
193 def __init__(self,color_scheme='NoColor',completekey=None,
193 def __init__(self,color_scheme='NoColor',completekey=None,
194 stdin=None, stdout=None):
194 stdin=None, stdout=None):
195
195
196 # Parent constructor:
196 # Parent constructor:
197 if has_pydb and completekey is None:
197 if has_pydb and completekey is None:
198 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
198 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
199 else:
199 else:
200 OldPdb.__init__(self,completekey,stdin,stdout)
200 OldPdb.__init__(self,completekey,stdin,stdout)
201
201
202 self.prompt = prompt # The default prompt is '(Pdb)'
202 self.prompt = prompt # The default prompt is '(Pdb)'
203
203
204 # IPython changes...
204 # IPython changes...
205 self.is_pydb = has_pydb
205 self.is_pydb = has_pydb
206
206
207 self.shell = get_ipython()
207 self.shell = get_ipython()
208
208
209 if self.shell is None:
209 if self.shell is None:
210 # No IPython instance running, we must create one
210 # No IPython instance running, we must create one
211 from IPython.terminal.interactiveshell import \
211 from IPython.terminal.interactiveshell import \
212 TerminalInteractiveShell
212 TerminalInteractiveShell
213 self.shell = TerminalInteractiveShell.instance()
213 self.shell = TerminalInteractiveShell.instance()
214
214
215 if self.is_pydb:
215 if self.is_pydb:
216
216
217 # interactiveshell.py's ipalias seems to want pdb's checkline
217 # interactiveshell.py's ipalias seems to want pdb's checkline
218 # which located in pydb.fn
218 # which located in pydb.fn
219 import pydb.fns
219 import pydb.fns
220 self.checkline = lambda filename, lineno: \
220 self.checkline = lambda filename, lineno: \
221 pydb.fns.checkline(self, filename, lineno)
221 pydb.fns.checkline(self, filename, lineno)
222
222
223 self.curframe = None
223 self.curframe = None
224 self.do_restart = self.new_do_restart
224 self.do_restart = self.new_do_restart
225
225
226 self.old_all_completions = self.shell.Completer.all_completions
226 self.old_all_completions = self.shell.Completer.all_completions
227 self.shell.Completer.all_completions=self.all_completions
227 self.shell.Completer.all_completions=self.all_completions
228
228
229 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
229 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
230 OldPdb.do_list)
230 OldPdb.do_list)
231 self.do_l = self.do_list
231 self.do_l = self.do_list
232 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
232 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
233 OldPdb.do_frame)
233 OldPdb.do_frame)
234
234
235 self.aliases = {}
235 self.aliases = {}
236
236
237 # Create color table: we copy the default one from the traceback
237 # Create color table: we copy the default one from the traceback
238 # module and add a few attributes needed for debugging
238 # module and add a few attributes needed for debugging
239 self.color_scheme_table = exception_colors()
239 self.color_scheme_table = exception_colors()
240
240
241 # shorthands
241 # shorthands
242 C = coloransi.TermColors
242 C = coloransi.TermColors
243 cst = self.color_scheme_table
243 cst = self.color_scheme_table
244
244
245 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
245 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
246 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
246 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
247
247
248 cst['Linux'].colors.breakpoint_enabled = C.LightRed
248 cst['Linux'].colors.breakpoint_enabled = C.LightRed
249 cst['Linux'].colors.breakpoint_disabled = C.Red
249 cst['Linux'].colors.breakpoint_disabled = C.Red
250
250
251 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
251 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
252 cst['LightBG'].colors.breakpoint_disabled = C.Red
252 cst['LightBG'].colors.breakpoint_disabled = C.Red
253
253
254 self.set_colors(color_scheme)
254 self.set_colors(color_scheme)
255
255
256 # Add a python parser so we can syntax highlight source while
256 # Add a python parser so we can syntax highlight source while
257 # debugging.
257 # debugging.
258 self.parser = PyColorize.Parser()
258 self.parser = PyColorize.Parser()
259
259
260 def set_colors(self, scheme):
260 def set_colors(self, scheme):
261 """Shorthand access to the color table scheme selector method."""
261 """Shorthand access to the color table scheme selector method."""
262 self.color_scheme_table.set_active_scheme(scheme)
262 self.color_scheme_table.set_active_scheme(scheme)
263
263
264 def interaction(self, frame, traceback):
264 def interaction(self, frame, traceback):
265 self.shell.set_completer_frame(frame)
265 self.shell.set_completer_frame(frame)
266 OldPdb.interaction(self, frame, traceback)
266 while True:
267 try:
268 OldPdb.interaction(self, frame, traceback)
269 except KeyboardInterrupt:
270 self.shell.write("\nKeyboardInterrupt\n")
271 else:
272 break
267
273
268 def new_do_up(self, arg):
274 def new_do_up(self, arg):
269 OldPdb.do_up(self, arg)
275 OldPdb.do_up(self, arg)
270 self.shell.set_completer_frame(self.curframe)
276 self.shell.set_completer_frame(self.curframe)
271 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
277 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
272
278
273 def new_do_down(self, arg):
279 def new_do_down(self, arg):
274 OldPdb.do_down(self, arg)
280 OldPdb.do_down(self, arg)
275 self.shell.set_completer_frame(self.curframe)
281 self.shell.set_completer_frame(self.curframe)
276
282
277 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
283 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
278
284
279 def new_do_frame(self, arg):
285 def new_do_frame(self, arg):
280 OldPdb.do_frame(self, arg)
286 OldPdb.do_frame(self, arg)
281 self.shell.set_completer_frame(self.curframe)
287 self.shell.set_completer_frame(self.curframe)
282
288
283 def new_do_quit(self, arg):
289 def new_do_quit(self, arg):
284
290
285 if hasattr(self, 'old_all_completions'):
291 if hasattr(self, 'old_all_completions'):
286 self.shell.Completer.all_completions=self.old_all_completions
292 self.shell.Completer.all_completions=self.old_all_completions
287
293
288
294
289 return OldPdb.do_quit(self, arg)
295 return OldPdb.do_quit(self, arg)
290
296
291 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
297 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
292
298
293 def new_do_restart(self, arg):
299 def new_do_restart(self, arg):
294 """Restart command. In the context of ipython this is exactly the same
300 """Restart command. In the context of ipython this is exactly the same
295 thing as 'quit'."""
301 thing as 'quit'."""
296 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
302 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
297 return self.do_quit(arg)
303 return self.do_quit(arg)
298
304
299 def postloop(self):
305 def postloop(self):
300 self.shell.set_completer_frame(None)
306 self.shell.set_completer_frame(None)
301
307
302 def print_stack_trace(self):
308 def print_stack_trace(self):
303 try:
309 try:
304 for frame_lineno in self.stack:
310 for frame_lineno in self.stack:
305 self.print_stack_entry(frame_lineno, context = 5)
311 self.print_stack_entry(frame_lineno, context = 5)
306 except KeyboardInterrupt:
312 except KeyboardInterrupt:
307 pass
313 pass
308
314
309 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
315 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
310 context = 3):
316 context = 3):
311 #frame, lineno = frame_lineno
317 #frame, lineno = frame_lineno
312 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
318 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
313
319
314 # vds: >>
320 # vds: >>
315 frame, lineno = frame_lineno
321 frame, lineno = frame_lineno
316 filename = frame.f_code.co_filename
322 filename = frame.f_code.co_filename
317 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
323 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
318 # vds: <<
324 # vds: <<
319
325
320 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
326 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
321 import repr
327 import repr
322
328
323 ret = []
329 ret = []
324
330
325 Colors = self.color_scheme_table.active_colors
331 Colors = self.color_scheme_table.active_colors
326 ColorsNormal = Colors.Normal
332 ColorsNormal = Colors.Normal
327 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
333 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
328 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
334 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
329 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
335 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
330 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
336 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
331 ColorsNormal)
337 ColorsNormal)
332
338
333 frame, lineno = frame_lineno
339 frame, lineno = frame_lineno
334
340
335 return_value = ''
341 return_value = ''
336 if '__return__' in frame.f_locals:
342 if '__return__' in frame.f_locals:
337 rv = frame.f_locals['__return__']
343 rv = frame.f_locals['__return__']
338 #return_value += '->'
344 #return_value += '->'
339 return_value += repr.repr(rv) + '\n'
345 return_value += repr.repr(rv) + '\n'
340 ret.append(return_value)
346 ret.append(return_value)
341
347
342 #s = filename + '(' + `lineno` + ')'
348 #s = filename + '(' + `lineno` + ')'
343 filename = self.canonic(frame.f_code.co_filename)
349 filename = self.canonic(frame.f_code.co_filename)
344 link = tpl_link % py3compat.cast_unicode(filename)
350 link = tpl_link % py3compat.cast_unicode(filename)
345
351
346 if frame.f_code.co_name:
352 if frame.f_code.co_name:
347 func = frame.f_code.co_name
353 func = frame.f_code.co_name
348 else:
354 else:
349 func = "<lambda>"
355 func = "<lambda>"
350
356
351 call = ''
357 call = ''
352 if func != '?':
358 if func != '?':
353 if '__args__' in frame.f_locals:
359 if '__args__' in frame.f_locals:
354 args = repr.repr(frame.f_locals['__args__'])
360 args = repr.repr(frame.f_locals['__args__'])
355 else:
361 else:
356 args = '()'
362 args = '()'
357 call = tpl_call % (func, args)
363 call = tpl_call % (func, args)
358
364
359 # The level info should be generated in the same format pdb uses, to
365 # The level info should be generated in the same format pdb uses, to
360 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
366 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
361 if frame is self.curframe:
367 if frame is self.curframe:
362 ret.append('> ')
368 ret.append('> ')
363 else:
369 else:
364 ret.append(' ')
370 ret.append(' ')
365 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
371 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
366
372
367 start = lineno - 1 - context//2
373 start = lineno - 1 - context//2
368 lines = ulinecache.getlines(filename)
374 lines = ulinecache.getlines(filename)
369 start = min(start, len(lines) - context)
375 start = min(start, len(lines) - context)
370 start = max(start, 0)
376 start = max(start, 0)
371 lines = lines[start : start + context]
377 lines = lines[start : start + context]
372
378
373 for i,line in enumerate(lines):
379 for i,line in enumerate(lines):
374 show_arrow = (start + 1 + i == lineno)
380 show_arrow = (start + 1 + i == lineno)
375 linetpl = (frame is self.curframe or show_arrow) \
381 linetpl = (frame is self.curframe or show_arrow) \
376 and tpl_line_em \
382 and tpl_line_em \
377 or tpl_line
383 or tpl_line
378 ret.append(self.__format_line(linetpl, filename,
384 ret.append(self.__format_line(linetpl, filename,
379 start + 1 + i, line,
385 start + 1 + i, line,
380 arrow = show_arrow) )
386 arrow = show_arrow) )
381 return ''.join(ret)
387 return ''.join(ret)
382
388
383 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
389 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
384 bp_mark = ""
390 bp_mark = ""
385 bp_mark_color = ""
391 bp_mark_color = ""
386
392
387 scheme = self.color_scheme_table.active_scheme_name
393 scheme = self.color_scheme_table.active_scheme_name
388 new_line, err = self.parser.format2(line, 'str', scheme)
394 new_line, err = self.parser.format2(line, 'str', scheme)
389 if not err: line = new_line
395 if not err: line = new_line
390
396
391 bp = None
397 bp = None
392 if lineno in self.get_file_breaks(filename):
398 if lineno in self.get_file_breaks(filename):
393 bps = self.get_breaks(filename, lineno)
399 bps = self.get_breaks(filename, lineno)
394 bp = bps[-1]
400 bp = bps[-1]
395
401
396 if bp:
402 if bp:
397 Colors = self.color_scheme_table.active_colors
403 Colors = self.color_scheme_table.active_colors
398 bp_mark = str(bp.number)
404 bp_mark = str(bp.number)
399 bp_mark_color = Colors.breakpoint_enabled
405 bp_mark_color = Colors.breakpoint_enabled
400 if not bp.enabled:
406 if not bp.enabled:
401 bp_mark_color = Colors.breakpoint_disabled
407 bp_mark_color = Colors.breakpoint_disabled
402
408
403 numbers_width = 7
409 numbers_width = 7
404 if arrow:
410 if arrow:
405 # This is the line with the error
411 # This is the line with the error
406 pad = numbers_width - len(str(lineno)) - len(bp_mark)
412 pad = numbers_width - len(str(lineno)) - len(bp_mark)
407 if pad >= 3:
413 if pad >= 3:
408 marker = '-'*(pad-3) + '-> '
414 marker = '-'*(pad-3) + '-> '
409 elif pad == 2:
415 elif pad == 2:
410 marker = '> '
416 marker = '> '
411 elif pad == 1:
417 elif pad == 1:
412 marker = '>'
418 marker = '>'
413 else:
419 else:
414 marker = ''
420 marker = ''
415 num = '%s%s' % (marker, str(lineno))
421 num = '%s%s' % (marker, str(lineno))
416 line = tpl_line % (bp_mark_color + bp_mark, num, line)
422 line = tpl_line % (bp_mark_color + bp_mark, num, line)
417 else:
423 else:
418 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
424 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
419 line = tpl_line % (bp_mark_color + bp_mark, num, line)
425 line = tpl_line % (bp_mark_color + bp_mark, num, line)
420
426
421 return line
427 return line
422
428
423 def list_command_pydb(self, arg):
429 def list_command_pydb(self, arg):
424 """List command to use if we have a newer pydb installed"""
430 """List command to use if we have a newer pydb installed"""
425 filename, first, last = OldPdb.parse_list_cmd(self, arg)
431 filename, first, last = OldPdb.parse_list_cmd(self, arg)
426 if filename is not None:
432 if filename is not None:
427 self.print_list_lines(filename, first, last)
433 self.print_list_lines(filename, first, last)
428
434
429 def print_list_lines(self, filename, first, last):
435 def print_list_lines(self, filename, first, last):
430 """The printing (as opposed to the parsing part of a 'list'
436 """The printing (as opposed to the parsing part of a 'list'
431 command."""
437 command."""
432 try:
438 try:
433 Colors = self.color_scheme_table.active_colors
439 Colors = self.color_scheme_table.active_colors
434 ColorsNormal = Colors.Normal
440 ColorsNormal = Colors.Normal
435 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
441 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
436 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
442 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
437 src = []
443 src = []
438 if filename == "<string>" and hasattr(self, "_exec_filename"):
444 if filename == "<string>" and hasattr(self, "_exec_filename"):
439 filename = self._exec_filename
445 filename = self._exec_filename
440
446
441 for lineno in range(first, last+1):
447 for lineno in range(first, last+1):
442 line = ulinecache.getline(filename, lineno)
448 line = ulinecache.getline(filename, lineno)
443 if not line:
449 if not line:
444 break
450 break
445
451
446 if lineno == self.curframe.f_lineno:
452 if lineno == self.curframe.f_lineno:
447 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
453 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
448 else:
454 else:
449 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
455 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
450
456
451 src.append(line)
457 src.append(line)
452 self.lineno = lineno
458 self.lineno = lineno
453
459
454 print(''.join(src), file=io.stdout)
460 print(''.join(src), file=io.stdout)
455
461
456 except KeyboardInterrupt:
462 except KeyboardInterrupt:
457 pass
463 pass
458
464
459 def do_list(self, arg):
465 def do_list(self, arg):
460 self.lastcmd = 'list'
466 self.lastcmd = 'list'
461 last = None
467 last = None
462 if arg:
468 if arg:
463 try:
469 try:
464 x = eval(arg, {}, {})
470 x = eval(arg, {}, {})
465 if type(x) == type(()):
471 if type(x) == type(()):
466 first, last = x
472 first, last = x
467 first = int(first)
473 first = int(first)
468 last = int(last)
474 last = int(last)
469 if last < first:
475 if last < first:
470 # Assume it's a count
476 # Assume it's a count
471 last = first + last
477 last = first + last
472 else:
478 else:
473 first = max(1, int(x) - 5)
479 first = max(1, int(x) - 5)
474 except:
480 except:
475 print('*** Error in argument:', repr(arg))
481 print('*** Error in argument:', repr(arg))
476 return
482 return
477 elif self.lineno is None:
483 elif self.lineno is None:
478 first = max(1, self.curframe.f_lineno - 5)
484 first = max(1, self.curframe.f_lineno - 5)
479 else:
485 else:
480 first = self.lineno + 1
486 first = self.lineno + 1
481 if last is None:
487 if last is None:
482 last = first + 10
488 last = first + 10
483 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
489 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
484
490
485 # vds: >>
491 # vds: >>
486 lineno = first
492 lineno = first
487 filename = self.curframe.f_code.co_filename
493 filename = self.curframe.f_code.co_filename
488 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
494 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
489 # vds: <<
495 # vds: <<
490
496
491 do_l = do_list
497 do_l = do_list
492
498
493 def do_pdef(self, arg):
499 def do_pdef(self, arg):
494 """Print the call signature for any callable object.
500 """Print the call signature for any callable object.
495
501
496 The debugger interface to %pdef"""
502 The debugger interface to %pdef"""
497 namespaces = [('Locals', self.curframe.f_locals),
503 namespaces = [('Locals', self.curframe.f_locals),
498 ('Globals', self.curframe.f_globals)]
504 ('Globals', self.curframe.f_globals)]
499 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
505 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
500
506
501 def do_pdoc(self, arg):
507 def do_pdoc(self, arg):
502 """Print the docstring for an object.
508 """Print the docstring for an object.
503
509
504 The debugger interface to %pdoc."""
510 The debugger interface to %pdoc."""
505 namespaces = [('Locals', self.curframe.f_locals),
511 namespaces = [('Locals', self.curframe.f_locals),
506 ('Globals', self.curframe.f_globals)]
512 ('Globals', self.curframe.f_globals)]
507 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
513 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
508
514
509 def do_pfile(self, arg):
515 def do_pfile(self, arg):
510 """Print (or run through pager) the file where an object is defined.
516 """Print (or run through pager) the file where an object is defined.
511
517
512 The debugger interface to %pfile.
518 The debugger interface to %pfile.
513 """
519 """
514 namespaces = [('Locals', self.curframe.f_locals),
520 namespaces = [('Locals', self.curframe.f_locals),
515 ('Globals', self.curframe.f_globals)]
521 ('Globals', self.curframe.f_globals)]
516 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
522 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
517
523
518 def do_pinfo(self, arg):
524 def do_pinfo(self, arg):
519 """Provide detailed information about an object.
525 """Provide detailed information about an object.
520
526
521 The debugger interface to %pinfo, i.e., obj?."""
527 The debugger interface to %pinfo, i.e., obj?."""
522 namespaces = [('Locals', self.curframe.f_locals),
528 namespaces = [('Locals', self.curframe.f_locals),
523 ('Globals', self.curframe.f_globals)]
529 ('Globals', self.curframe.f_globals)]
524 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
530 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
525
531
526 def do_pinfo2(self, arg):
532 def do_pinfo2(self, arg):
527 """Provide extra detailed information about an object.
533 """Provide extra detailed information about an object.
528
534
529 The debugger interface to %pinfo2, i.e., obj??."""
535 The debugger interface to %pinfo2, i.e., obj??."""
530 namespaces = [('Locals', self.curframe.f_locals),
536 namespaces = [('Locals', self.curframe.f_locals),
531 ('Globals', self.curframe.f_globals)]
537 ('Globals', self.curframe.f_globals)]
532 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
538 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
533
539
534 def do_psource(self, arg):
540 def do_psource(self, arg):
535 """Print (or run through pager) the source code for an object."""
541 """Print (or run through pager) the source code for an object."""
536 namespaces = [('Locals', self.curframe.f_locals),
542 namespaces = [('Locals', self.curframe.f_locals),
537 ('Globals', self.curframe.f_globals)]
543 ('Globals', self.curframe.f_globals)]
538 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
544 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
539
545
540 def checkline(self, filename, lineno):
546 def checkline(self, filename, lineno):
541 """Check whether specified line seems to be executable.
547 """Check whether specified line seems to be executable.
542
548
543 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
549 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
544 line or EOF). Warning: testing is not comprehensive.
550 line or EOF). Warning: testing is not comprehensive.
545 """
551 """
546 #######################################################################
552 #######################################################################
547 # XXX Hack! Use python-2.5 compatible code for this call, because with
553 # XXX Hack! Use python-2.5 compatible code for this call, because with
548 # all of our changes, we've drifted from the pdb api in 2.6. For now,
554 # all of our changes, we've drifted from the pdb api in 2.6. For now,
549 # changing:
555 # changing:
550 #
556 #
551 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
557 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
552 # to:
558 # to:
553 #
559 #
554 line = linecache.getline(filename, lineno)
560 line = linecache.getline(filename, lineno)
555 #
561 #
556 # does the trick. But in reality, we need to fix this by reconciling
562 # does the trick. But in reality, we need to fix this by reconciling
557 # our updates with the new Pdb APIs in Python 2.6.
563 # our updates with the new Pdb APIs in Python 2.6.
558 #
564 #
559 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
565 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
560 #######################################################################
566 #######################################################################
561
567
562 if not line:
568 if not line:
563 print('End of file', file=self.stdout)
569 print('End of file', file=self.stdout)
564 return 0
570 return 0
565 line = line.strip()
571 line = line.strip()
566 # Don't allow setting breakpoint at a blank line
572 # Don't allow setting breakpoint at a blank line
567 if (not line or (line[0] == '#') or
573 if (not line or (line[0] == '#') or
568 (line[:3] == '"""') or line[:3] == "'''"):
574 (line[:3] == '"""') or line[:3] == "'''"):
569 print('*** Blank or comment', file=self.stdout)
575 print('*** Blank or comment', file=self.stdout)
570 return 0
576 return 0
571 return lineno
577 return lineno
General Comments 0
You need to be logged in to leave comments. Login now