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