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