##// END OF EJS Templates
synchronize with editor patch
vds -
Show More
@@ -1,517 +1,529 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 $Id: Debugger.py 2913 2007-12-31 12:42:14Z vivainio $"""
18 $Id: Debugger.py 2913 2007-12-31 12:42:14Z vivainio $"""
19
19
20 #*****************************************************************************
20 #*****************************************************************************
21 #
21 #
22 # This file is licensed under the PSF license.
22 # This file is licensed under the PSF license.
23 #
23 #
24 # Copyright (C) 2001 Python Software Foundation, www.python.org
24 # Copyright (C) 2001 Python Software Foundation, www.python.org
25 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
25 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
26 #
26 #
27 #
27 #
28 #*****************************************************************************
28 #*****************************************************************************
29
29
30 from IPython import Release
30 from IPython import Release
31 __author__ = '%s <%s>' % Release.authors['Fernando']
31 __author__ = '%s <%s>' % Release.authors['Fernando']
32 __license__ = 'Python'
32 __license__ = 'Python'
33
33
34 import bdb
34 import bdb
35 import cmd
35 import cmd
36 import linecache
36 import linecache
37 import os
37 import os
38 import sys
38 import sys
39
39
40 from IPython import PyColorize, ColorANSI, ipapi
40 from IPython import PyColorize, ColorANSI, ipapi
41 from IPython.genutils import Term
41 from IPython.genutils import Term
42 from IPython.excolors import ExceptionColors
42 from IPython.excolors import ExceptionColors
43
43
44 # See if we can use pydb.
44 # See if we can use pydb.
45 has_pydb = False
45 has_pydb = False
46 prompt = 'ipdb> '
46 prompt = 'ipdb> '
47 #We have to check this directly from sys.argv, config struct not yet available
47 #We have to check this directly from sys.argv, config struct not yet available
48 if '-pydb' in sys.argv:
48 if '-pydb' in sys.argv:
49 try:
49 try:
50 import pydb
50 import pydb
51 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
51 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
52 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
52 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
53 # better protect against it.
53 # better protect against it.
54 has_pydb = True
54 has_pydb = True
55 except ImportError:
55 except ImportError:
56 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
56 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
57
57
58 if has_pydb:
58 if has_pydb:
59 from pydb import Pdb as OldPdb
59 from pydb import Pdb as OldPdb
60 #print "Using pydb for %run -d and post-mortem" #dbg
60 #print "Using pydb for %run -d and post-mortem" #dbg
61 prompt = 'ipydb> '
61 prompt = 'ipydb> '
62 else:
62 else:
63 from pdb import Pdb as OldPdb
63 from pdb import Pdb as OldPdb
64
64
65 # Allow the set_trace code to operate outside of an ipython instance, even if
65 # Allow the set_trace code to operate outside of an ipython instance, even if
66 # it does so with some limitations. The rest of this support is implemented in
66 # it does so with some limitations. The rest of this support is implemented in
67 # the Tracer constructor.
67 # the Tracer constructor.
68 def BdbQuit_excepthook(et,ev,tb):
68 def BdbQuit_excepthook(et,ev,tb):
69 if et==bdb.BdbQuit:
69 if et==bdb.BdbQuit:
70 print 'Exiting Debugger.'
70 print 'Exiting Debugger.'
71 else:
71 else:
72 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
72 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
73
73
74 def BdbQuit_IPython_excepthook(self,et,ev,tb):
74 def BdbQuit_IPython_excepthook(self,et,ev,tb):
75 print 'Exiting Debugger.'
75 print 'Exiting Debugger.'
76
76
77 class Tracer(object):
77 class Tracer(object):
78 """Class for local debugging, similar to pdb.set_trace.
78 """Class for local debugging, similar to pdb.set_trace.
79
79
80 Instances of this class, when called, behave like pdb.set_trace, but
80 Instances of this class, when called, behave like pdb.set_trace, but
81 providing IPython's enhanced capabilities.
81 providing IPython's enhanced capabilities.
82
82
83 This is implemented as a class which must be initialized in your own code
83 This is implemented as a class which must be initialized in your own code
84 and not as a standalone function because we need to detect at runtime
84 and not as a standalone function because we need to detect at runtime
85 whether IPython is already active or not. That detection is done in the
85 whether IPython is already active or not. That detection is done in the
86 constructor, ensuring that this code plays nicely with a running IPython,
86 constructor, ensuring that this code plays nicely with a running IPython,
87 while functioning acceptably (though with limitations) if outside of it.
87 while functioning acceptably (though with limitations) if outside of it.
88 """
88 """
89
89
90 def __init__(self,colors=None):
90 def __init__(self,colors=None):
91 """Create a local debugger instance.
91 """Create a local debugger instance.
92
92
93 :Parameters:
93 :Parameters:
94
94
95 - `colors` (None): a string containing the name of the color scheme to
95 - `colors` (None): a string containing the name of the color scheme to
96 use, it must be one of IPython's valid color schemes. If not given, the
96 use, it must be one of IPython's valid color schemes. If not given, the
97 function will default to the current IPython scheme when running inside
97 function will default to the current IPython scheme when running inside
98 IPython, and to 'NoColor' otherwise.
98 IPython, and to 'NoColor' otherwise.
99
99
100 Usage example:
100 Usage example:
101
101
102 from IPython.Debugger import Tracer; debug_here = Tracer()
102 from IPython.Debugger import Tracer; debug_here = Tracer()
103
103
104 ... later in your code
104 ... later in your code
105 debug_here() # -> will open up the debugger at that point.
105 debug_here() # -> will open up the debugger at that point.
106
106
107 Once the debugger activates, you can use all of its regular commands to
107 Once the debugger activates, you can use all of its regular commands to
108 step through code, set breakpoints, etc. See the pdb documentation
108 step through code, set breakpoints, etc. See the pdb documentation
109 from the Python standard library for usage details.
109 from the Python standard library for usage details.
110 """
110 """
111
111
112 global __IPYTHON__
112 global __IPYTHON__
113 try:
113 try:
114 __IPYTHON__
114 __IPYTHON__
115 except NameError:
115 except NameError:
116 # Outside of ipython, we set our own exception hook manually
116 # Outside of ipython, we set our own exception hook manually
117 __IPYTHON__ = ipapi.get(True,False)
117 __IPYTHON__ = ipapi.get(True,False)
118 BdbQuit_excepthook.excepthook_ori = sys.excepthook
118 BdbQuit_excepthook.excepthook_ori = sys.excepthook
119 sys.excepthook = BdbQuit_excepthook
119 sys.excepthook = BdbQuit_excepthook
120 def_colors = 'NoColor'
120 def_colors = 'NoColor'
121 try:
121 try:
122 # Limited tab completion support
122 # Limited tab completion support
123 import rlcompleter,readline
123 import rlcompleter,readline
124 readline.parse_and_bind('tab: complete')
124 readline.parse_and_bind('tab: complete')
125 except ImportError:
125 except ImportError:
126 pass
126 pass
127 else:
127 else:
128 # In ipython, we use its custom exception handler mechanism
128 # In ipython, we use its custom exception handler mechanism
129 ip = ipapi.get()
129 ip = ipapi.get()
130 def_colors = ip.options.colors
130 def_colors = ip.options.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 self.debugger = Pdb(colors)
135 self.debugger = Pdb(colors)
136
136
137 def __call__(self):
137 def __call__(self):
138 """Starts an interactive debugger at the point where called.
138 """Starts an interactive debugger at the point where called.
139
139
140 This is similar to the pdb.set_trace() function from the std lib, but
140 This is similar to the pdb.set_trace() function from the std lib, but
141 using IPython's enhanced debugger."""
141 using IPython's enhanced debugger."""
142
142
143 self.debugger.set_trace(sys._getframe().f_back)
143 self.debugger.set_trace(sys._getframe().f_back)
144
144
145 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
145 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
146 """Make new_fn have old_fn's doc string. This is particularly useful
146 """Make new_fn have old_fn's doc string. This is particularly useful
147 for the do_... commands that hook into the help system.
147 for the do_... commands that hook into the help system.
148 Adapted from from a comp.lang.python posting
148 Adapted from from a comp.lang.python posting
149 by Duncan Booth."""
149 by Duncan Booth."""
150 def wrapper(*args, **kw):
150 def wrapper(*args, **kw):
151 return new_fn(*args, **kw)
151 return new_fn(*args, **kw)
152 if old_fn.__doc__:
152 if old_fn.__doc__:
153 wrapper.__doc__ = old_fn.__doc__ + additional_text
153 wrapper.__doc__ = old_fn.__doc__ + additional_text
154 return wrapper
154 return wrapper
155
155
156 def _file_lines(fname):
156 def _file_lines(fname):
157 """Return the contents of a named file as a list of lines.
157 """Return the contents of a named file as a list of lines.
158
158
159 This function never raises an IOError exception: if the file can't be
159 This function never raises an IOError exception: if the file can't be
160 read, it simply returns an empty list."""
160 read, it simply returns an empty list."""
161
161
162 try:
162 try:
163 outfile = open(fname)
163 outfile = open(fname)
164 except IOError:
164 except IOError:
165 return []
165 return []
166 else:
166 else:
167 out = outfile.readlines()
167 out = outfile.readlines()
168 outfile.close()
168 outfile.close()
169 return out
169 return out
170
170
171 class Pdb(OldPdb):
171 class Pdb(OldPdb):
172 """Modified Pdb class, does not load readline."""
172 """Modified Pdb class, does not load readline."""
173
173
174 if sys.version[:3] >= '2.5' or has_pydb:
174 if sys.version[:3] >= '2.5' or has_pydb:
175 def __init__(self,color_scheme='NoColor',completekey=None,
175 def __init__(self,color_scheme='NoColor',completekey=None,
176 stdin=None, stdout=None):
176 stdin=None, stdout=None):
177
177
178 # Parent constructor:
178 # Parent constructor:
179 if has_pydb and completekey is None:
179 if has_pydb and completekey is None:
180 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
180 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
181 else:
181 else:
182 OldPdb.__init__(self,completekey,stdin,stdout)
182 OldPdb.__init__(self,completekey,stdin,stdout)
183
183
184 self.prompt = prompt # The default prompt is '(Pdb)'
184 self.prompt = prompt # The default prompt is '(Pdb)'
185
185
186 # IPython changes...
186 # IPython changes...
187 self.is_pydb = has_pydb
187 self.is_pydb = has_pydb
188
188
189 if self.is_pydb:
189 if self.is_pydb:
190
190
191 # iplib.py's ipalias seems to want pdb's checkline
191 # iplib.py's ipalias seems to want pdb's checkline
192 # which located in pydb.fn
192 # which located in pydb.fn
193 import pydb.fns
193 import pydb.fns
194 self.checkline = lambda filename, lineno: \
194 self.checkline = lambda filename, lineno: \
195 pydb.fns.checkline(self, filename, lineno)
195 pydb.fns.checkline(self, filename, lineno)
196
196
197 self.curframe = None
197 self.curframe = None
198 self.do_restart = self.new_do_restart
198 self.do_restart = self.new_do_restart
199
199
200 self.old_all_completions = __IPYTHON__.Completer.all_completions
200 self.old_all_completions = __IPYTHON__.Completer.all_completions
201 __IPYTHON__.Completer.all_completions=self.all_completions
201 __IPYTHON__.Completer.all_completions=self.all_completions
202
202
203 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
203 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
204 OldPdb.do_list)
204 OldPdb.do_list)
205 self.do_l = self.do_list
205 self.do_l = self.do_list
206 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
206 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
207 OldPdb.do_frame)
207 OldPdb.do_frame)
208
208
209 self.aliases = {}
209 self.aliases = {}
210
210
211 # Create color table: we copy the default one from the traceback
211 # Create color table: we copy the default one from the traceback
212 # module and add a few attributes needed for debugging
212 # module and add a few attributes needed for debugging
213 self.color_scheme_table = ExceptionColors.copy()
213 self.color_scheme_table = ExceptionColors.copy()
214
214
215 # shorthands
215 # shorthands
216 C = ColorANSI.TermColors
216 C = ColorANSI.TermColors
217 cst = self.color_scheme_table
217 cst = self.color_scheme_table
218
218
219 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
219 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
220 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
220 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
221
221
222 cst['Linux'].colors.breakpoint_enabled = C.LightRed
222 cst['Linux'].colors.breakpoint_enabled = C.LightRed
223 cst['Linux'].colors.breakpoint_disabled = C.Red
223 cst['Linux'].colors.breakpoint_disabled = C.Red
224
224
225 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
225 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
226 cst['LightBG'].colors.breakpoint_disabled = C.Red
226 cst['LightBG'].colors.breakpoint_disabled = C.Red
227
227
228 self.set_colors(color_scheme)
228 self.set_colors(color_scheme)
229
229
230 # Add a python parser so we can syntax highlight source while
230 # Add a python parser so we can syntax highlight source while
231 # debugging.
231 # debugging.
232 self.parser = PyColorize.Parser()
232 self.parser = PyColorize.Parser()
233
233
234
234
235 else:
235 else:
236 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
236 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
237 # because it binds readline and breaks tab-completion. This means we
237 # because it binds readline and breaks tab-completion. This means we
238 # have to COPY the constructor here.
238 # have to COPY the constructor here.
239 def __init__(self,color_scheme='NoColor'):
239 def __init__(self,color_scheme='NoColor'):
240 bdb.Bdb.__init__(self)
240 bdb.Bdb.__init__(self)
241 cmd.Cmd.__init__(self,completekey=None) # don't load readline
241 cmd.Cmd.__init__(self,completekey=None) # don't load readline
242 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
242 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
243 self.aliases = {}
243 self.aliases = {}
244
244
245 # These two lines are part of the py2.4 constructor, let's put them
245 # These two lines are part of the py2.4 constructor, let's put them
246 # unconditionally here as they won't cause any problems in 2.3.
246 # unconditionally here as they won't cause any problems in 2.3.
247 self.mainpyfile = ''
247 self.mainpyfile = ''
248 self._wait_for_mainpyfile = 0
248 self._wait_for_mainpyfile = 0
249
249
250 # Read $HOME/.pdbrc and ./.pdbrc
250 # Read $HOME/.pdbrc and ./.pdbrc
251 try:
251 try:
252 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
252 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
253 ".pdbrc"))
253 ".pdbrc"))
254 except KeyError:
254 except KeyError:
255 self.rcLines = []
255 self.rcLines = []
256 self.rcLines.extend(_file_lines(".pdbrc"))
256 self.rcLines.extend(_file_lines(".pdbrc"))
257
257
258 # Create color table: we copy the default one from the traceback
258 # Create color table: we copy the default one from the traceback
259 # module and add a few attributes needed for debugging
259 # module and add a few attributes needed for debugging
260 ExceptionColors.set_active_scheme(color_scheme)
260 ExceptionColors.set_active_scheme(color_scheme)
261 self.color_scheme_table = ExceptionColors.copy()
261 self.color_scheme_table = ExceptionColors.copy()
262
262
263 # shorthands
263 # shorthands
264 C = ColorANSI.TermColors
264 C = ColorANSI.TermColors
265 cst = self.color_scheme_table
265 cst = self.color_scheme_table
266
266
267 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
267 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
268 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
268 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
269
269
270 cst['Linux'].colors.breakpoint_enabled = C.LightRed
270 cst['Linux'].colors.breakpoint_enabled = C.LightRed
271 cst['Linux'].colors.breakpoint_disabled = C.Red
271 cst['Linux'].colors.breakpoint_disabled = C.Red
272
272
273 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
273 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
274 cst['LightBG'].colors.breakpoint_disabled = C.Red
274 cst['LightBG'].colors.breakpoint_disabled = C.Red
275
275
276 self.set_colors(color_scheme)
276 self.set_colors(color_scheme)
277
277
278 # Add a python parser so we can syntax highlight source while
278 # Add a python parser so we can syntax highlight source while
279 # debugging.
279 # debugging.
280 self.parser = PyColorize.Parser()
280 self.parser = PyColorize.Parser()
281
281
282 def set_colors(self, scheme):
282 def set_colors(self, scheme):
283 """Shorthand access to the color table scheme selector method."""
283 """Shorthand access to the color table scheme selector method."""
284 self.color_scheme_table.set_active_scheme(scheme)
284 self.color_scheme_table.set_active_scheme(scheme)
285
285
286 def interaction(self, frame, traceback):
286 def interaction(self, frame, traceback):
287 __IPYTHON__.set_completer_frame(frame)
287 __IPYTHON__.set_completer_frame(frame)
288 OldPdb.interaction(self, frame, traceback)
288 OldPdb.interaction(self, frame, traceback)
289
289
290 def new_do_up(self, arg):
290 def new_do_up(self, arg):
291 OldPdb.do_up(self, arg)
291 OldPdb.do_up(self, arg)
292 __IPYTHON__.set_completer_frame(self.curframe)
292 __IPYTHON__.set_completer_frame(self.curframe)
293 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
293 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
294
294
295 def new_do_down(self, arg):
295 def new_do_down(self, arg):
296 OldPdb.do_down(self, arg)
296 OldPdb.do_down(self, arg)
297 __IPYTHON__.set_completer_frame(self.curframe)
297 __IPYTHON__.set_completer_frame(self.curframe)
298
298
299 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
299 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
300
300
301 def new_do_frame(self, arg):
301 def new_do_frame(self, arg):
302 OldPdb.do_frame(self, arg)
302 OldPdb.do_frame(self, arg)
303 __IPYTHON__.set_completer_frame(self.curframe)
303 __IPYTHON__.set_completer_frame(self.curframe)
304
304
305 def new_do_quit(self, arg):
305 def new_do_quit(self, arg):
306
306
307 if hasattr(self, 'old_all_completions'):
307 if hasattr(self, 'old_all_completions'):
308 __IPYTHON__.Completer.all_completions=self.old_all_completions
308 __IPYTHON__.Completer.all_completions=self.old_all_completions
309
309
310
310
311 return OldPdb.do_quit(self, arg)
311 return OldPdb.do_quit(self, arg)
312
312
313 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
313 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
314
314
315 def new_do_restart(self, arg):
315 def new_do_restart(self, arg):
316 """Restart command. In the context of ipython this is exactly the same
316 """Restart command. In the context of ipython this is exactly the same
317 thing as 'quit'."""
317 thing as 'quit'."""
318 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
318 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
319 return self.do_quit(arg)
319 return self.do_quit(arg)
320
320
321 def postloop(self):
321 def postloop(self):
322 __IPYTHON__.set_completer_frame(None)
322 __IPYTHON__.set_completer_frame(None)
323
323
324 def print_stack_trace(self):
324 def print_stack_trace(self):
325 try:
325 try:
326 for frame_lineno in self.stack:
326 for frame_lineno in self.stack:
327 self.print_stack_entry(frame_lineno, context = 5)
327 self.print_stack_entry(frame_lineno, context = 5)
328 except KeyboardInterrupt:
328 except KeyboardInterrupt:
329 pass
329 pass
330
330
331 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
331 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
332 context = 3):
332 context = 3):
333 #frame, lineno = frame_lineno
333 #frame, lineno = frame_lineno
334 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
334 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
335
335
336 # vds: >>
337 frame, lineno = frame_lineno
338 filename = frame.f_code.co_filename
339 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
340 # vds: <<
341
336 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
342 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
337 import linecache, repr
343 import linecache, repr
338
344
339 ret = []
345 ret = []
340
346
341 Colors = self.color_scheme_table.active_colors
347 Colors = self.color_scheme_table.active_colors
342 ColorsNormal = Colors.Normal
348 ColorsNormal = Colors.Normal
343 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
349 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
344 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
350 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
345 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
351 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
346 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
352 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
347 ColorsNormal)
353 ColorsNormal)
348
354
349 frame, lineno = frame_lineno
355 frame, lineno = frame_lineno
350
356
351 return_value = ''
357 return_value = ''
352 if '__return__' in frame.f_locals:
358 if '__return__' in frame.f_locals:
353 rv = frame.f_locals['__return__']
359 rv = frame.f_locals['__return__']
354 #return_value += '->'
360 #return_value += '->'
355 return_value += repr.repr(rv) + '\n'
361 return_value += repr.repr(rv) + '\n'
356 ret.append(return_value)
362 ret.append(return_value)
357
363
358 #s = filename + '(' + `lineno` + ')'
364 #s = filename + '(' + `lineno` + ')'
359 filename = self.canonic(frame.f_code.co_filename)
365 filename = self.canonic(frame.f_code.co_filename)
360 link = tpl_link % filename
366 link = tpl_link % filename
361
367
362 if frame.f_code.co_name:
368 if frame.f_code.co_name:
363 func = frame.f_code.co_name
369 func = frame.f_code.co_name
364 else:
370 else:
365 func = "<lambda>"
371 func = "<lambda>"
366
372
367 call = ''
373 call = ''
368 if func != '?':
374 if func != '?':
369 if '__args__' in frame.f_locals:
375 if '__args__' in frame.f_locals:
370 args = repr.repr(frame.f_locals['__args__'])
376 args = repr.repr(frame.f_locals['__args__'])
371 else:
377 else:
372 args = '()'
378 args = '()'
373 call = tpl_call % (func, args)
379 call = tpl_call % (func, args)
374
380
375 # The level info should be generated in the same format pdb uses, to
381 # The level info should be generated in the same format pdb uses, to
376 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
382 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
377 if frame is self.curframe:
383 if frame is self.curframe:
378 ret.append('> ')
384 ret.append('> ')
379 else:
385 else:
380 ret.append(' ')
386 ret.append(' ')
381 ret.append('%s(%s)%s\n' % (link,lineno,call))
387 ret.append('%s(%s)%s\n' % (link,lineno,call))
382
388
383 start = lineno - 1 - context//2
389 start = lineno - 1 - context//2
384 lines = linecache.getlines(filename)
390 lines = linecache.getlines(filename)
385 start = max(start, 0)
391 start = max(start, 0)
386 start = min(start, len(lines) - context)
392 start = min(start, len(lines) - context)
387 lines = lines[start : start + context]
393 lines = lines[start : start + context]
388
394
389 for i,line in enumerate(lines):
395 for i,line in enumerate(lines):
390 show_arrow = (start + 1 + i == lineno)
396 show_arrow = (start + 1 + i == lineno)
391 linetpl = (frame is self.curframe or show_arrow) \
397 linetpl = (frame is self.curframe or show_arrow) \
392 and tpl_line_em \
398 and tpl_line_em \
393 or tpl_line
399 or tpl_line
394 ret.append(self.__format_line(linetpl, filename,
400 ret.append(self.__format_line(linetpl, filename,
395 start + 1 + i, line,
401 start + 1 + i, line,
396 arrow = show_arrow) )
402 arrow = show_arrow) )
397
403
398 return ''.join(ret)
404 return ''.join(ret)
399
405
400 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
406 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
401 bp_mark = ""
407 bp_mark = ""
402 bp_mark_color = ""
408 bp_mark_color = ""
403
409
404 scheme = self.color_scheme_table.active_scheme_name
410 scheme = self.color_scheme_table.active_scheme_name
405 new_line, err = self.parser.format2(line, 'str', scheme)
411 new_line, err = self.parser.format2(line, 'str', scheme)
406 if not err: line = new_line
412 if not err: line = new_line
407
413
408 bp = None
414 bp = None
409 if lineno in self.get_file_breaks(filename):
415 if lineno in self.get_file_breaks(filename):
410 bps = self.get_breaks(filename, lineno)
416 bps = self.get_breaks(filename, lineno)
411 bp = bps[-1]
417 bp = bps[-1]
412
418
413 if bp:
419 if bp:
414 Colors = self.color_scheme_table.active_colors
420 Colors = self.color_scheme_table.active_colors
415 bp_mark = str(bp.number)
421 bp_mark = str(bp.number)
416 bp_mark_color = Colors.breakpoint_enabled
422 bp_mark_color = Colors.breakpoint_enabled
417 if not bp.enabled:
423 if not bp.enabled:
418 bp_mark_color = Colors.breakpoint_disabled
424 bp_mark_color = Colors.breakpoint_disabled
419
425
420 numbers_width = 7
426 numbers_width = 7
421 if arrow:
427 if arrow:
422 # This is the line with the error
428 # This is the line with the error
423 pad = numbers_width - len(str(lineno)) - len(bp_mark)
429 pad = numbers_width - len(str(lineno)) - len(bp_mark)
424 if pad >= 3:
430 if pad >= 3:
425 marker = '-'*(pad-3) + '-> '
431 marker = '-'*(pad-3) + '-> '
426 elif pad == 2:
432 elif pad == 2:
427 marker = '> '
433 marker = '> '
428 elif pad == 1:
434 elif pad == 1:
429 marker = '>'
435 marker = '>'
430 else:
436 else:
431 marker = ''
437 marker = ''
432 num = '%s%s' % (marker, str(lineno))
438 num = '%s%s' % (marker, str(lineno))
433 line = tpl_line % (bp_mark_color + bp_mark, num, line)
439 line = tpl_line % (bp_mark_color + bp_mark, num, line)
434 else:
440 else:
435 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
441 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
436 line = tpl_line % (bp_mark_color + bp_mark, num, line)
442 line = tpl_line % (bp_mark_color + bp_mark, num, line)
437
443
438 return line
444 return line
439
445
440 def list_command_pydb(self, arg):
446 def list_command_pydb(self, arg):
441 """List command to use if we have a newer pydb installed"""
447 """List command to use if we have a newer pydb installed"""
442 filename, first, last = OldPdb.parse_list_cmd(self, arg)
448 filename, first, last = OldPdb.parse_list_cmd(self, arg)
443 if filename is not None:
449 if filename is not None:
444 self.print_list_lines(filename, first, last)
450 self.print_list_lines(filename, first, last)
445
451
446 def print_list_lines(self, filename, first, last):
452 def print_list_lines(self, filename, first, last):
447 """The printing (as opposed to the parsing part of a 'list'
453 """The printing (as opposed to the parsing part of a 'list'
448 command."""
454 command."""
449 try:
455 try:
450 Colors = self.color_scheme_table.active_colors
456 Colors = self.color_scheme_table.active_colors
451 ColorsNormal = Colors.Normal
457 ColorsNormal = Colors.Normal
452 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
458 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
453 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
459 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
454 src = []
460 src = []
455 for lineno in range(first, last+1):
461 for lineno in range(first, last+1):
456 line = linecache.getline(filename, lineno)
462 line = linecache.getline(filename, lineno)
457 if not line:
463 if not line:
458 break
464 break
459
465
460 if lineno == self.curframe.f_lineno:
466 if lineno == self.curframe.f_lineno:
461 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
467 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
462 else:
468 else:
463 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
469 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
464
470
465 src.append(line)
471 src.append(line)
466 self.lineno = lineno
472 self.lineno = lineno
467
473
468 print >>Term.cout, ''.join(src)
474 print >>Term.cout, ''.join(src)
469
475
470 except KeyboardInterrupt:
476 except KeyboardInterrupt:
471 pass
477 pass
472
478
473 def do_list(self, arg):
479 def do_list(self, arg):
474 self.lastcmd = 'list'
480 self.lastcmd = 'list'
475 last = None
481 last = None
476 if arg:
482 if arg:
477 try:
483 try:
478 x = eval(arg, {}, {})
484 x = eval(arg, {}, {})
479 if type(x) == type(()):
485 if type(x) == type(()):
480 first, last = x
486 first, last = x
481 first = int(first)
487 first = int(first)
482 last = int(last)
488 last = int(last)
483 if last < first:
489 if last < first:
484 # Assume it's a count
490 # Assume it's a count
485 last = first + last
491 last = first + last
486 else:
492 else:
487 first = max(1, int(x) - 5)
493 first = max(1, int(x) - 5)
488 except:
494 except:
489 print '*** Error in argument:', `arg`
495 print '*** Error in argument:', `arg`
490 return
496 return
491 elif self.lineno is None:
497 elif self.lineno is None:
492 first = max(1, self.curframe.f_lineno - 5)
498 first = max(1, self.curframe.f_lineno - 5)
493 else:
499 else:
494 first = self.lineno + 1
500 first = self.lineno + 1
495 if last is None:
501 if last is None:
496 last = first + 10
502 last = first + 10
497 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
503 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
498
504
505 # vds: >>
506 lineno = first
507 filename = self.curframe.f_code.co_filename
508 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
509 # vds: <<
510
499 do_l = do_list
511 do_l = do_list
500
512
501 def do_pdef(self, arg):
513 def do_pdef(self, arg):
502 """The debugger interface to magic_pdef"""
514 """The debugger interface to magic_pdef"""
503 namespaces = [('Locals', self.curframe.f_locals),
515 namespaces = [('Locals', self.curframe.f_locals),
504 ('Globals', self.curframe.f_globals)]
516 ('Globals', self.curframe.f_globals)]
505 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
517 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
506
518
507 def do_pdoc(self, arg):
519 def do_pdoc(self, arg):
508 """The debugger interface to magic_pdoc"""
520 """The debugger interface to magic_pdoc"""
509 namespaces = [('Locals', self.curframe.f_locals),
521 namespaces = [('Locals', self.curframe.f_locals),
510 ('Globals', self.curframe.f_globals)]
522 ('Globals', self.curframe.f_globals)]
511 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
523 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
512
524
513 def do_pinfo(self, arg):
525 def do_pinfo(self, arg):
514 """The debugger equivalant of ?obj"""
526 """The debugger equivalant of ?obj"""
515 namespaces = [('Locals', self.curframe.f_locals),
527 namespaces = [('Locals', self.curframe.f_locals),
516 ('Globals', self.curframe.f_globals)]
528 ('Globals', self.curframe.f_globals)]
517 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
529 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
@@ -1,243 +1,249 b''
1 """hooks for IPython.
1 """hooks for IPython.
2
2
3 In Python, it is possible to overwrite any method of any object if you really
3 In Python, it is possible to overwrite any method of any object if you really
4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
5 be overwritten by users for customization purposes. This module defines the
5 be overwritten by users for customization purposes. This module defines the
6 default versions of all such hooks, which get used by IPython if not
6 default versions of all such hooks, which get used by IPython if not
7 overridden by the user.
7 overridden by the user.
8
8
9 hooks are simple functions, but they should be declared with 'self' as their
9 hooks are simple functions, but they should be declared with 'self' as their
10 first argument, because when activated they are registered into IPython as
10 first argument, because when activated they are registered into IPython as
11 instance methods. The self argument will be the IPython running instance
11 instance methods. The self argument will be the IPython running instance
12 itself, so hooks have full access to the entire IPython object.
12 itself, so hooks have full access to the entire IPython object.
13
13
14 If you wish to define a new hook and activate it, you need to put the
14 If you wish to define a new hook and activate it, you need to put the
15 necessary code into a python file which can be either imported or execfile()'d
15 necessary code into a python file which can be either imported or execfile()'d
16 from within your ipythonrc configuration.
16 from within your ipythonrc configuration.
17
17
18 For example, suppose that you have a module called 'myiphooks' in your
18 For example, suppose that you have a module called 'myiphooks' in your
19 PYTHONPATH, which contains the following definition:
19 PYTHONPATH, which contains the following definition:
20
20
21 import os
21 import os
22 import IPython.ipapi
22 import IPython.ipapi
23 ip = IPython.ipapi.get()
23 ip = IPython.ipapi.get()
24
24
25 def calljed(self,filename, linenum):
25 def calljed(self,filename, linenum):
26 "My editor hook calls the jed editor directly."
26 "My editor hook calls the jed editor directly."
27 print "Calling my own editor, jed ..."
27 print "Calling my own editor, jed ..."
28 os.system('jed +%d %s' % (linenum,filename))
28 os.system('jed +%d %s' % (linenum,filename))
29
29
30 ip.set_hook('editor', calljed)
30 ip.set_hook('editor', calljed)
31
31
32 You can then enable the functionality by doing 'import myiphooks'
32 You can then enable the functionality by doing 'import myiphooks'
33 somewhere in your configuration files or ipython command line.
33 somewhere in your configuration files or ipython command line.
34
34
35 $Id: hooks.py 2998 2008-01-31 10:06:04Z vivainio $"""
35 $Id: hooks.py 2998 2008-01-31 10:06:04Z vivainio $"""
36
36
37 #*****************************************************************************
37 #*****************************************************************************
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
39 #
39 #
40 # Distributed under the terms of the BSD License. The full license is in
40 # Distributed under the terms of the BSD License. The full license is in
41 # the file COPYING, distributed as part of this software.
41 # the file COPYING, distributed as part of this software.
42 #*****************************************************************************
42 #*****************************************************************************
43
43
44 from IPython import Release
44 from IPython import Release
45 from IPython import ipapi
45 from IPython import ipapi
46 __author__ = '%s <%s>' % Release.authors['Fernando']
46 __author__ = '%s <%s>' % Release.authors['Fernando']
47 __license__ = Release.license
47 __license__ = Release.license
48 __version__ = Release.version
48 __version__ = Release.version
49
49
50 import os,bisect
50 import os,bisect
51 from genutils import Term,shell
51 from genutils import Term,shell
52 from pprint import PrettyPrinter
52 from pprint import PrettyPrinter
53
53
54 # List here all the default hooks. For now it's just the editor functions
54 # List here all the default hooks. For now it's just the editor functions
55 # but over time we'll move here all the public API for user-accessible things.
55 # but over time we'll move here all the public API for user-accessible things.
56 __all__ = ['editor', 'fix_error_editor', 'result_display',
56 # vds: >>
57 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
57 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
58 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
58 'generate_prompt', 'generate_output_prompt','shell_hook',
59 'generate_prompt', 'generate_output_prompt','shell_hook',
59 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
60 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
61 # vds: <<
60
62
61 pformat = PrettyPrinter().pformat
63 pformat = PrettyPrinter().pformat
62
64
63 def editor(self,filename, linenum=None):
65 def editor(self,filename, linenum=None):
64 """Open the default editor at the given filename and linenumber.
66 """Open the default editor at the given filename and linenumber.
65
67
66 This is IPython's default editor hook, you can use it as an example to
68 This is IPython's default editor hook, you can use it as an example to
67 write your own modified one. To set your own editor function as the
69 write your own modified one. To set your own editor function as the
68 new editor hook, call ip.set_hook('editor',yourfunc)."""
70 new editor hook, call ip.set_hook('editor',yourfunc)."""
69
71
70 # IPython configures a default editor at startup by reading $EDITOR from
72 # IPython configures a default editor at startup by reading $EDITOR from
71 # the environment, and falling back on vi (unix) or notepad (win32).
73 # the environment, and falling back on vi (unix) or notepad (win32).
72 editor = self.rc.editor
74 editor = self.rc.editor
73
75
74 # marker for at which line to open the file (for existing objects)
76 # marker for at which line to open the file (for existing objects)
75 if linenum is None or editor=='notepad':
77 if linenum is None or editor=='notepad':
76 linemark = ''
78 linemark = ''
77 else:
79 else:
78 linemark = '+%d' % int(linenum)
80 linemark = '+%d' % int(linenum)
79
81
80 # Enclose in quotes if necessary and legal
82 # Enclose in quotes if necessary and legal
81 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
83 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
82 editor = '"%s"' % editor
84 editor = '"%s"' % editor
83
85
84 # Call the actual editor
86 # Call the actual editor
85 os.system('%s %s %s' % (editor,linemark,filename))
87 os.system('%s %s %s' % (editor,linemark,filename))
86
88
87 import tempfile
89 import tempfile
88 def fix_error_editor(self,filename,linenum,column,msg):
90 def fix_error_editor(self,filename,linenum,column,msg):
89 """Open the editor at the given filename, linenumber, column and
91 """Open the editor at the given filename, linenumber, column and
90 show an error message. This is used for correcting syntax errors.
92 show an error message. This is used for correcting syntax errors.
91 The current implementation only has special support for the VIM editor,
93 The current implementation only has special support for the VIM editor,
92 and falls back on the 'editor' hook if VIM is not used.
94 and falls back on the 'editor' hook if VIM is not used.
93
95
94 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
96 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
95 """
97 """
96 def vim_quickfix_file():
98 def vim_quickfix_file():
97 t = tempfile.NamedTemporaryFile()
99 t = tempfile.NamedTemporaryFile()
98 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
100 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
99 t.flush()
101 t.flush()
100 return t
102 return t
101 if os.path.basename(self.rc.editor) != 'vim':
103 if os.path.basename(self.rc.editor) != 'vim':
102 self.hooks.editor(filename,linenum)
104 self.hooks.editor(filename,linenum)
103 return
105 return
104 t = vim_quickfix_file()
106 t = vim_quickfix_file()
105 try:
107 try:
106 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
108 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
107 finally:
109 finally:
108 t.close()
110 t.close()
109
111
112 # vds: >>
113 def synchronize_with_editor(self, filename, linenum, column):
114 pass
115 # vds: <<
110
116
111 class CommandChainDispatcher:
117 class CommandChainDispatcher:
112 """ Dispatch calls to a chain of commands until some func can handle it
118 """ Dispatch calls to a chain of commands until some func can handle it
113
119
114 Usage: instantiate, execute "add" to add commands (with optional
120 Usage: instantiate, execute "add" to add commands (with optional
115 priority), execute normally via f() calling mechanism.
121 priority), execute normally via f() calling mechanism.
116
122
117 """
123 """
118 def __init__(self,commands=None):
124 def __init__(self,commands=None):
119 if commands is None:
125 if commands is None:
120 self.chain = []
126 self.chain = []
121 else:
127 else:
122 self.chain = commands
128 self.chain = commands
123
129
124
130
125 def __call__(self,*args, **kw):
131 def __call__(self,*args, **kw):
126 """ Command chain is called just like normal func.
132 """ Command chain is called just like normal func.
127
133
128 This will call all funcs in chain with the same args as were given to this
134 This will call all funcs in chain with the same args as were given to this
129 function, and return the result of first func that didn't raise
135 function, and return the result of first func that didn't raise
130 TryNext """
136 TryNext """
131
137
132 for prio,cmd in self.chain:
138 for prio,cmd in self.chain:
133 #print "prio",prio,"cmd",cmd #dbg
139 #print "prio",prio,"cmd",cmd #dbg
134 try:
140 try:
135 ret = cmd(*args, **kw)
141 ret = cmd(*args, **kw)
136 return ret
142 return ret
137 except ipapi.TryNext, exc:
143 except ipapi.TryNext, exc:
138 if exc.args or exc.kwargs:
144 if exc.args or exc.kwargs:
139 args = exc.args
145 args = exc.args
140 kw = exc.kwargs
146 kw = exc.kwargs
141 # if no function will accept it, raise TryNext up to the caller
147 # if no function will accept it, raise TryNext up to the caller
142 raise ipapi.TryNext
148 raise ipapi.TryNext
143
149
144 def __str__(self):
150 def __str__(self):
145 return str(self.chain)
151 return str(self.chain)
146
152
147 def add(self, func, priority=0):
153 def add(self, func, priority=0):
148 """ Add a func to the cmd chain with given priority """
154 """ Add a func to the cmd chain with given priority """
149 bisect.insort(self.chain,(priority,func))
155 bisect.insort(self.chain,(priority,func))
150
156
151 def __iter__(self):
157 def __iter__(self):
152 """ Return all objects in chain.
158 """ Return all objects in chain.
153
159
154 Handy if the objects are not callable.
160 Handy if the objects are not callable.
155 """
161 """
156 return iter(self.chain)
162 return iter(self.chain)
157
163
158 def result_display(self,arg):
164 def result_display(self,arg):
159 """ Default display hook.
165 """ Default display hook.
160
166
161 Called for displaying the result to the user.
167 Called for displaying the result to the user.
162 """
168 """
163
169
164 if self.rc.pprint:
170 if self.rc.pprint:
165 out = pformat(arg)
171 out = pformat(arg)
166 if '\n' in out:
172 if '\n' in out:
167 # So that multi-line strings line up with the left column of
173 # So that multi-line strings line up with the left column of
168 # the screen, instead of having the output prompt mess up
174 # the screen, instead of having the output prompt mess up
169 # their first line.
175 # their first line.
170 Term.cout.write('\n')
176 Term.cout.write('\n')
171 print >>Term.cout, out
177 print >>Term.cout, out
172 else:
178 else:
173 # By default, the interactive prompt uses repr() to display results,
179 # By default, the interactive prompt uses repr() to display results,
174 # so we should honor this. Users who'd rather use a different
180 # so we should honor this. Users who'd rather use a different
175 # mechanism can easily override this hook.
181 # mechanism can easily override this hook.
176 print >>Term.cout, repr(arg)
182 print >>Term.cout, repr(arg)
177 # the default display hook doesn't manipulate the value to put in history
183 # the default display hook doesn't manipulate the value to put in history
178 return None
184 return None
179
185
180 def input_prefilter(self,line):
186 def input_prefilter(self,line):
181 """ Default input prefilter
187 """ Default input prefilter
182
188
183 This returns the line as unchanged, so that the interpreter
189 This returns the line as unchanged, so that the interpreter
184 knows that nothing was done and proceeds with "classic" prefiltering
190 knows that nothing was done and proceeds with "classic" prefiltering
185 (%magics, !shell commands etc.).
191 (%magics, !shell commands etc.).
186
192
187 Note that leading whitespace is not passed to this hook. Prefilter
193 Note that leading whitespace is not passed to this hook. Prefilter
188 can't alter indentation.
194 can't alter indentation.
189
195
190 """
196 """
191 #print "attempt to rewrite",line #dbg
197 #print "attempt to rewrite",line #dbg
192 return line
198 return line
193
199
194 def shutdown_hook(self):
200 def shutdown_hook(self):
195 """ default shutdown hook
201 """ default shutdown hook
196
202
197 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
203 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
198 """
204 """
199
205
200 #print "default shutdown hook ok" # dbg
206 #print "default shutdown hook ok" # dbg
201 return
207 return
202
208
203 def late_startup_hook(self):
209 def late_startup_hook(self):
204 """ Executed after ipython has been constructed and configured
210 """ Executed after ipython has been constructed and configured
205
211
206 """
212 """
207 #print "default startup hook ok" # dbg
213 #print "default startup hook ok" # dbg
208
214
209 def generate_prompt(self, is_continuation):
215 def generate_prompt(self, is_continuation):
210 """ calculate and return a string with the prompt to display """
216 """ calculate and return a string with the prompt to display """
211 ip = self.api
217 ip = self.api
212 if is_continuation:
218 if is_continuation:
213 return str(ip.IP.outputcache.prompt2)
219 return str(ip.IP.outputcache.prompt2)
214 return str(ip.IP.outputcache.prompt1)
220 return str(ip.IP.outputcache.prompt1)
215
221
216 def generate_output_prompt(self):
222 def generate_output_prompt(self):
217 ip = self.api
223 ip = self.api
218 return str(ip.IP.outputcache.prompt_out)
224 return str(ip.IP.outputcache.prompt_out)
219
225
220 def shell_hook(self,cmd):
226 def shell_hook(self,cmd):
221 """ Run system/shell command a'la os.system() """
227 """ Run system/shell command a'la os.system() """
222
228
223 shell(cmd, header=self.rc.system_header, verbose=self.rc.system_verbose)
229 shell(cmd, header=self.rc.system_header, verbose=self.rc.system_verbose)
224
230
225 def show_in_pager(self,s):
231 def show_in_pager(self,s):
226 """ Run a string through pager """
232 """ Run a string through pager """
227 # raising TryNext here will use the default paging functionality
233 # raising TryNext here will use the default paging functionality
228 raise ipapi.TryNext
234 raise ipapi.TryNext
229
235
230 def pre_prompt_hook(self):
236 def pre_prompt_hook(self):
231 """ Run before displaying the next prompt
237 """ Run before displaying the next prompt
232
238
233 Use this e.g. to display output from asynchronous operations (in order
239 Use this e.g. to display output from asynchronous operations (in order
234 to not mess up text entry)
240 to not mess up text entry)
235 """
241 """
236
242
237 return None
243 return None
238
244
239 def pre_runcode_hook(self):
245 def pre_runcode_hook(self):
240 """ Executed before running the (prefiltered) code in IPython """
246 """ Executed before running the (prefiltered) code in IPython """
241 return None
247 return None
242
248
243
249
@@ -1,1045 +1,1059 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 ultraTB.py -- Spice up your tracebacks!
3 ultraTB.py -- Spice up your tracebacks!
4
4
5 * ColorTB
5 * ColorTB
6 I've always found it a bit hard to visually parse tracebacks in Python. The
6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 ColorTB class is a solution to that problem. It colors the different parts of a
7 ColorTB class is a solution to that problem. It colors the different parts of a
8 traceback in a manner similar to what you would expect from a syntax-highlighting
8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 text editor.
9 text editor.
10
10
11 Installation instructions for ColorTB:
11 Installation instructions for ColorTB:
12 import sys,ultraTB
12 import sys,ultraTB
13 sys.excepthook = ultraTB.ColorTB()
13 sys.excepthook = ultraTB.ColorTB()
14
14
15 * VerboseTB
15 * VerboseTB
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 and intended it for CGI programmers, but why should they have all the fun? I
18 and intended it for CGI programmers, but why should they have all the fun? I
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 but kind of neat, and maybe useful for long-running programs that you believe
20 but kind of neat, and maybe useful for long-running programs that you believe
21 are bug-free. If a crash *does* occur in that type of program you want details.
21 are bug-free. If a crash *does* occur in that type of program you want details.
22 Give it a shot--you'll love it or you'll hate it.
22 Give it a shot--you'll love it or you'll hate it.
23
23
24 Note:
24 Note:
25
25
26 The Verbose mode prints the variables currently visible where the exception
26 The Verbose mode prints the variables currently visible where the exception
27 happened (shortening their strings if too long). This can potentially be
27 happened (shortening their strings if too long). This can potentially be
28 very slow, if you happen to have a huge data structure whose string
28 very slow, if you happen to have a huge data structure whose string
29 representation is complex to compute. Your computer may appear to freeze for
29 representation is complex to compute. Your computer may appear to freeze for
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 with Ctrl-C (maybe hitting it more than once).
31 with Ctrl-C (maybe hitting it more than once).
32
32
33 If you encounter this kind of situation often, you may want to use the
33 If you encounter this kind of situation often, you may want to use the
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 variables (but otherwise includes the information and context given by
35 variables (but otherwise includes the information and context given by
36 Verbose).
36 Verbose).
37
37
38
38
39 Installation instructions for ColorTB:
39 Installation instructions for ColorTB:
40 import sys,ultraTB
40 import sys,ultraTB
41 sys.excepthook = ultraTB.VerboseTB()
41 sys.excepthook = ultraTB.VerboseTB()
42
42
43 Note: Much of the code in this module was lifted verbatim from the standard
43 Note: Much of the code in this module was lifted verbatim from the standard
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45
45
46 * Color schemes
46 * Color schemes
47 The colors are defined in the class TBTools through the use of the
47 The colors are defined in the class TBTools through the use of the
48 ColorSchemeTable class. Currently the following exist:
48 ColorSchemeTable class. Currently the following exist:
49
49
50 - NoColor: allows all of this module to be used in any terminal (the color
50 - NoColor: allows all of this module to be used in any terminal (the color
51 escapes are just dummy blank strings).
51 escapes are just dummy blank strings).
52
52
53 - Linux: is meant to look good in a terminal like the Linux console (black
53 - Linux: is meant to look good in a terminal like the Linux console (black
54 or very dark background).
54 or very dark background).
55
55
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 in light background terminals.
57 in light background terminals.
58
58
59 You can implement other color schemes easily, the syntax is fairly
59 You can implement other color schemes easily, the syntax is fairly
60 self-explanatory. Please send back new schemes you develop to the author for
60 self-explanatory. Please send back new schemes you develop to the author for
61 possible inclusion in future releases.
61 possible inclusion in future releases.
62
62
63 $Id: ultraTB.py 2908 2007-12-30 21:07:46Z vivainio $"""
63 $Id: ultraTB.py 2908 2007-12-30 21:07:46Z vivainio $"""
64
64
65 #*****************************************************************************
65 #*****************************************************************************
66 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
67 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
68 #
68 #
69 # Distributed under the terms of the BSD License. The full license is in
69 # Distributed under the terms of the BSD License. The full license is in
70 # the file COPYING, distributed as part of this software.
70 # the file COPYING, distributed as part of this software.
71 #*****************************************************************************
71 #*****************************************************************************
72
72
73 from IPython import Release
73 from IPython import Release
74 __author__ = '%s <%s>\n%s <%s>' % (Release.authors['Nathan']+
74 __author__ = '%s <%s>\n%s <%s>' % (Release.authors['Nathan']+
75 Release.authors['Fernando'])
75 Release.authors['Fernando'])
76 __license__ = Release.license
76 __license__ = Release.license
77
77
78 # Required modules
78 # Required modules
79 import inspect
79 import inspect
80 import keyword
80 import keyword
81 import linecache
81 import linecache
82 import os
82 import os
83 import pydoc
83 import pydoc
84 import re
84 import re
85 import string
85 import string
86 import sys
86 import sys
87 import time
87 import time
88 import tokenize
88 import tokenize
89 import traceback
89 import traceback
90 import types
90 import types
91
91
92 # For purposes of monkeypatching inspect to fix a bug in it.
92 # For purposes of monkeypatching inspect to fix a bug in it.
93 from inspect import getsourcefile, getfile, getmodule,\
93 from inspect import getsourcefile, getfile, getmodule,\
94 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
94 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
95
95
96
96
97 # IPython's own modules
97 # IPython's own modules
98 # Modified pdb which doesn't damage IPython's readline handling
98 # Modified pdb which doesn't damage IPython's readline handling
99 from IPython import Debugger, PyColorize
99 from IPython import Debugger, PyColorize
100 from IPython.ipstruct import Struct
100 from IPython.ipstruct import Struct
101 from IPython.excolors import ExceptionColors
101 from IPython.excolors import ExceptionColors
102 from IPython.genutils import Term,uniq_stable,error,info
102 from IPython.genutils import Term,uniq_stable,error,info
103
103
104 # Globals
104 # Globals
105 # amount of space to put line numbers before verbose tracebacks
105 # amount of space to put line numbers before verbose tracebacks
106 INDENT_SIZE = 8
106 INDENT_SIZE = 8
107
107
108 # Default color scheme. This is used, for example, by the traceback
108 # Default color scheme. This is used, for example, by the traceback
109 # formatter. When running in an actual IPython instance, the user's rc.colors
109 # formatter. When running in an actual IPython instance, the user's rc.colors
110 # value is used, but havinga module global makes this functionality available
110 # value is used, but havinga module global makes this functionality available
111 # to users of ultraTB who are NOT running inside ipython.
111 # to users of ultraTB who are NOT running inside ipython.
112 DEFAULT_SCHEME = 'NoColor'
112 DEFAULT_SCHEME = 'NoColor'
113
113
114 #---------------------------------------------------------------------------
114 #---------------------------------------------------------------------------
115 # Code begins
115 # Code begins
116
116
117 # Utility functions
117 # Utility functions
118 def inspect_error():
118 def inspect_error():
119 """Print a message about internal inspect errors.
119 """Print a message about internal inspect errors.
120
120
121 These are unfortunately quite common."""
121 These are unfortunately quite common."""
122
122
123 error('Internal Python error in the inspect module.\n'
123 error('Internal Python error in the inspect module.\n'
124 'Below is the traceback from this internal error.\n')
124 'Below is the traceback from this internal error.\n')
125
125
126
126
127 def findsource(object):
127 def findsource(object):
128 """Return the entire source file and starting line number for an object.
128 """Return the entire source file and starting line number for an object.
129
129
130 The argument may be a module, class, method, function, traceback, frame,
130 The argument may be a module, class, method, function, traceback, frame,
131 or code object. The source code is returned as a list of all the lines
131 or code object. The source code is returned as a list of all the lines
132 in the file and the line number indexes a line in that list. An IOError
132 in the file and the line number indexes a line in that list. An IOError
133 is raised if the source code cannot be retrieved.
133 is raised if the source code cannot be retrieved.
134
134
135 FIXED version with which we monkeypatch the stdlib to work around a bug."""
135 FIXED version with which we monkeypatch the stdlib to work around a bug."""
136
136
137 file = getsourcefile(object) or getfile(object)
137 file = getsourcefile(object) or getfile(object)
138 # If the object is a frame, then trying to get the globals dict from its
138 # If the object is a frame, then trying to get the globals dict from its
139 # module won't work. Instead, the frame object itself has the globals
139 # module won't work. Instead, the frame object itself has the globals
140 # dictionary.
140 # dictionary.
141 globals_dict = None
141 globals_dict = None
142 if inspect.isframe(object):
142 if inspect.isframe(object):
143 # XXX: can this ever be false?
143 # XXX: can this ever be false?
144 globals_dict = object.f_globals
144 globals_dict = object.f_globals
145 else:
145 else:
146 module = getmodule(object, file)
146 module = getmodule(object, file)
147 if module:
147 if module:
148 globals_dict = module.__dict__
148 globals_dict = module.__dict__
149 lines = linecache.getlines(file, globals_dict)
149 lines = linecache.getlines(file, globals_dict)
150 if not lines:
150 if not lines:
151 raise IOError('could not get source code')
151 raise IOError('could not get source code')
152
152
153 if ismodule(object):
153 if ismodule(object):
154 return lines, 0
154 return lines, 0
155
155
156 if isclass(object):
156 if isclass(object):
157 name = object.__name__
157 name = object.__name__
158 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
158 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
159 # make some effort to find the best matching class definition:
159 # make some effort to find the best matching class definition:
160 # use the one with the least indentation, which is the one
160 # use the one with the least indentation, which is the one
161 # that's most probably not inside a function definition.
161 # that's most probably not inside a function definition.
162 candidates = []
162 candidates = []
163 for i in range(len(lines)):
163 for i in range(len(lines)):
164 match = pat.match(lines[i])
164 match = pat.match(lines[i])
165 if match:
165 if match:
166 # if it's at toplevel, it's already the best one
166 # if it's at toplevel, it's already the best one
167 if lines[i][0] == 'c':
167 if lines[i][0] == 'c':
168 return lines, i
168 return lines, i
169 # else add whitespace to candidate list
169 # else add whitespace to candidate list
170 candidates.append((match.group(1), i))
170 candidates.append((match.group(1), i))
171 if candidates:
171 if candidates:
172 # this will sort by whitespace, and by line number,
172 # this will sort by whitespace, and by line number,
173 # less whitespace first
173 # less whitespace first
174 candidates.sort()
174 candidates.sort()
175 return lines, candidates[0][1]
175 return lines, candidates[0][1]
176 else:
176 else:
177 raise IOError('could not find class definition')
177 raise IOError('could not find class definition')
178
178
179 if ismethod(object):
179 if ismethod(object):
180 object = object.im_func
180 object = object.im_func
181 if isfunction(object):
181 if isfunction(object):
182 object = object.func_code
182 object = object.func_code
183 if istraceback(object):
183 if istraceback(object):
184 object = object.tb_frame
184 object = object.tb_frame
185 if isframe(object):
185 if isframe(object):
186 object = object.f_code
186 object = object.f_code
187 if iscode(object):
187 if iscode(object):
188 if not hasattr(object, 'co_firstlineno'):
188 if not hasattr(object, 'co_firstlineno'):
189 raise IOError('could not find function definition')
189 raise IOError('could not find function definition')
190 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
190 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
191 pmatch = pat.match
191 pmatch = pat.match
192 # fperez - fix: sometimes, co_firstlineno can give a number larger than
192 # fperez - fix: sometimes, co_firstlineno can give a number larger than
193 # the length of lines, which causes an error. Safeguard against that.
193 # the length of lines, which causes an error. Safeguard against that.
194 lnum = min(object.co_firstlineno,len(lines))-1
194 lnum = min(object.co_firstlineno,len(lines))-1
195 while lnum > 0:
195 while lnum > 0:
196 if pmatch(lines[lnum]): break
196 if pmatch(lines[lnum]): break
197 lnum -= 1
197 lnum -= 1
198
198
199 return lines, lnum
199 return lines, lnum
200 raise IOError('could not find code object')
200 raise IOError('could not find code object')
201
201
202 # Monkeypatch inspect to apply our bugfix. This code only works with py25
202 # Monkeypatch inspect to apply our bugfix. This code only works with py25
203 if sys.version_info[:2] >= (2,5):
203 if sys.version_info[:2] >= (2,5):
204 inspect.findsource = findsource
204 inspect.findsource = findsource
205
205
206 def fix_frame_records_filenames(records):
206 def fix_frame_records_filenames(records):
207 """Try to fix the filenames in each record from inspect.getinnerframes().
207 """Try to fix the filenames in each record from inspect.getinnerframes().
208
208
209 Particularly, modules loaded from within zip files have useless filenames
209 Particularly, modules loaded from within zip files have useless filenames
210 attached to their code object, and inspect.getinnerframes() just uses it.
210 attached to their code object, and inspect.getinnerframes() just uses it.
211 """
211 """
212 fixed_records = []
212 fixed_records = []
213 for frame, filename, line_no, func_name, lines, index in records:
213 for frame, filename, line_no, func_name, lines, index in records:
214 # Look inside the frame's globals dictionary for __file__, which should
214 # Look inside the frame's globals dictionary for __file__, which should
215 # be better.
215 # be better.
216 better_fn = frame.f_globals.get('__file__', None)
216 better_fn = frame.f_globals.get('__file__', None)
217 if isinstance(better_fn, str):
217 if isinstance(better_fn, str):
218 # Check the type just in case someone did something weird with
218 # Check the type just in case someone did something weird with
219 # __file__. It might also be None if the error occurred during
219 # __file__. It might also be None if the error occurred during
220 # import.
220 # import.
221 filename = better_fn
221 filename = better_fn
222 fixed_records.append((frame, filename, line_no, func_name, lines, index))
222 fixed_records.append((frame, filename, line_no, func_name, lines, index))
223 return fixed_records
223 return fixed_records
224
224
225
225
226 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
226 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
227 import linecache
227 import linecache
228 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
228 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
229
229
230 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
230 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
231
231
232 # If the error is at the console, don't build any context, since it would
232 # If the error is at the console, don't build any context, since it would
233 # otherwise produce 5 blank lines printed out (there is no file at the
233 # otherwise produce 5 blank lines printed out (there is no file at the
234 # console)
234 # console)
235 rec_check = records[tb_offset:]
235 rec_check = records[tb_offset:]
236 try:
236 try:
237 rname = rec_check[0][1]
237 rname = rec_check[0][1]
238 if rname == '<ipython console>' or rname.endswith('<string>'):
238 if rname == '<ipython console>' or rname.endswith('<string>'):
239 return rec_check
239 return rec_check
240 except IndexError:
240 except IndexError:
241 pass
241 pass
242
242
243 aux = traceback.extract_tb(etb)
243 aux = traceback.extract_tb(etb)
244 assert len(records) == len(aux)
244 assert len(records) == len(aux)
245 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
245 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
246 maybeStart = lnum-1 - context//2
246 maybeStart = lnum-1 - context//2
247 start = max(maybeStart, 0)
247 start = max(maybeStart, 0)
248 end = start + context
248 end = start + context
249 lines = linecache.getlines(file)[start:end]
249 lines = linecache.getlines(file)[start:end]
250 # pad with empty lines if necessary
250 # pad with empty lines if necessary
251 if maybeStart < 0:
251 if maybeStart < 0:
252 lines = (['\n'] * -maybeStart) + lines
252 lines = (['\n'] * -maybeStart) + lines
253 if len(lines) < context:
253 if len(lines) < context:
254 lines += ['\n'] * (context - len(lines))
254 lines += ['\n'] * (context - len(lines))
255 buf = list(records[i])
255 buf = list(records[i])
256 buf[LNUM_POS] = lnum
256 buf[LNUM_POS] = lnum
257 buf[INDEX_POS] = lnum - 1 - start
257 buf[INDEX_POS] = lnum - 1 - start
258 buf[LINES_POS] = lines
258 buf[LINES_POS] = lines
259 records[i] = tuple(buf)
259 records[i] = tuple(buf)
260 return records[tb_offset:]
260 return records[tb_offset:]
261
261
262 # Helper function -- largely belongs to VerboseTB, but we need the same
262 # Helper function -- largely belongs to VerboseTB, but we need the same
263 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
263 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
264 # can be recognized properly by ipython.el's py-traceback-line-re
264 # can be recognized properly by ipython.el's py-traceback-line-re
265 # (SyntaxErrors have to be treated specially because they have no traceback)
265 # (SyntaxErrors have to be treated specially because they have no traceback)
266
266
267 _parser = PyColorize.Parser()
267 _parser = PyColorize.Parser()
268
268
269 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
269 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
270 numbers_width = INDENT_SIZE - 1
270 numbers_width = INDENT_SIZE - 1
271 res = []
271 res = []
272 i = lnum - index
272 i = lnum - index
273
273
274 # This lets us get fully syntax-highlighted tracebacks.
274 # This lets us get fully syntax-highlighted tracebacks.
275 if scheme is None:
275 if scheme is None:
276 try:
276 try:
277 scheme = __IPYTHON__.rc.colors
277 scheme = __IPYTHON__.rc.colors
278 except:
278 except:
279 scheme = DEFAULT_SCHEME
279 scheme = DEFAULT_SCHEME
280 _line_format = _parser.format2
280 _line_format = _parser.format2
281
281
282 for line in lines:
282 for line in lines:
283 new_line, err = _line_format(line,'str',scheme)
283 new_line, err = _line_format(line,'str',scheme)
284 if not err: line = new_line
284 if not err: line = new_line
285
285
286 if i == lnum:
286 if i == lnum:
287 # This is the line with the error
287 # This is the line with the error
288 pad = numbers_width - len(str(i))
288 pad = numbers_width - len(str(i))
289 if pad >= 3:
289 if pad >= 3:
290 marker = '-'*(pad-3) + '-> '
290 marker = '-'*(pad-3) + '-> '
291 elif pad == 2:
291 elif pad == 2:
292 marker = '> '
292 marker = '> '
293 elif pad == 1:
293 elif pad == 1:
294 marker = '>'
294 marker = '>'
295 else:
295 else:
296 marker = ''
296 marker = ''
297 num = marker + str(i)
297 num = marker + str(i)
298 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
298 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
299 Colors.line, line, Colors.Normal)
299 Colors.line, line, Colors.Normal)
300 else:
300 else:
301 num = '%*s' % (numbers_width,i)
301 num = '%*s' % (numbers_width,i)
302 line = '%s%s%s %s' %(Colors.lineno, num,
302 line = '%s%s%s %s' %(Colors.lineno, num,
303 Colors.Normal, line)
303 Colors.Normal, line)
304
304
305 res.append(line)
305 res.append(line)
306 if lvals and i == lnum:
306 if lvals and i == lnum:
307 res.append(lvals + '\n')
307 res.append(lvals + '\n')
308 i = i + 1
308 i = i + 1
309 return res
309 return res
310
310
311
311
312 #---------------------------------------------------------------------------
312 #---------------------------------------------------------------------------
313 # Module classes
313 # Module classes
314 class TBTools:
314 class TBTools:
315 """Basic tools used by all traceback printer classes."""
315 """Basic tools used by all traceback printer classes."""
316
316
317 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
317 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
318 # Whether to call the interactive pdb debugger after printing
318 # Whether to call the interactive pdb debugger after printing
319 # tracebacks or not
319 # tracebacks or not
320 self.call_pdb = call_pdb
320 self.call_pdb = call_pdb
321
321
322 # Create color table
322 # Create color table
323 self.color_scheme_table = ExceptionColors
323 self.color_scheme_table = ExceptionColors
324
324
325 self.set_colors(color_scheme)
325 self.set_colors(color_scheme)
326 self.old_scheme = color_scheme # save initial value for toggles
326 self.old_scheme = color_scheme # save initial value for toggles
327
327
328 if call_pdb:
328 if call_pdb:
329 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
329 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
330 else:
330 else:
331 self.pdb = None
331 self.pdb = None
332
332
333 def set_colors(self,*args,**kw):
333 def set_colors(self,*args,**kw):
334 """Shorthand access to the color table scheme selector method."""
334 """Shorthand access to the color table scheme selector method."""
335
335
336 # Set own color table
336 # Set own color table
337 self.color_scheme_table.set_active_scheme(*args,**kw)
337 self.color_scheme_table.set_active_scheme(*args,**kw)
338 # for convenience, set Colors to the active scheme
338 # for convenience, set Colors to the active scheme
339 self.Colors = self.color_scheme_table.active_colors
339 self.Colors = self.color_scheme_table.active_colors
340 # Also set colors of debugger
340 # Also set colors of debugger
341 if hasattr(self,'pdb') and self.pdb is not None:
341 if hasattr(self,'pdb') and self.pdb is not None:
342 self.pdb.set_colors(*args,**kw)
342 self.pdb.set_colors(*args,**kw)
343
343
344 def color_toggle(self):
344 def color_toggle(self):
345 """Toggle between the currently active color scheme and NoColor."""
345 """Toggle between the currently active color scheme and NoColor."""
346
346
347 if self.color_scheme_table.active_scheme_name == 'NoColor':
347 if self.color_scheme_table.active_scheme_name == 'NoColor':
348 self.color_scheme_table.set_active_scheme(self.old_scheme)
348 self.color_scheme_table.set_active_scheme(self.old_scheme)
349 self.Colors = self.color_scheme_table.active_colors
349 self.Colors = self.color_scheme_table.active_colors
350 else:
350 else:
351 self.old_scheme = self.color_scheme_table.active_scheme_name
351 self.old_scheme = self.color_scheme_table.active_scheme_name
352 self.color_scheme_table.set_active_scheme('NoColor')
352 self.color_scheme_table.set_active_scheme('NoColor')
353 self.Colors = self.color_scheme_table.active_colors
353 self.Colors = self.color_scheme_table.active_colors
354
354
355 #---------------------------------------------------------------------------
355 #---------------------------------------------------------------------------
356 class ListTB(TBTools):
356 class ListTB(TBTools):
357 """Print traceback information from a traceback list, with optional color.
357 """Print traceback information from a traceback list, with optional color.
358
358
359 Calling: requires 3 arguments:
359 Calling: requires 3 arguments:
360 (etype, evalue, elist)
360 (etype, evalue, elist)
361 as would be obtained by:
361 as would be obtained by:
362 etype, evalue, tb = sys.exc_info()
362 etype, evalue, tb = sys.exc_info()
363 if tb:
363 if tb:
364 elist = traceback.extract_tb(tb)
364 elist = traceback.extract_tb(tb)
365 else:
365 else:
366 elist = None
366 elist = None
367
367
368 It can thus be used by programs which need to process the traceback before
368 It can thus be used by programs which need to process the traceback before
369 printing (such as console replacements based on the code module from the
369 printing (such as console replacements based on the code module from the
370 standard library).
370 standard library).
371
371
372 Because they are meant to be called without a full traceback (only a
372 Because they are meant to be called without a full traceback (only a
373 list), instances of this class can't call the interactive pdb debugger."""
373 list), instances of this class can't call the interactive pdb debugger."""
374
374
375 def __init__(self,color_scheme = 'NoColor'):
375 def __init__(self,color_scheme = 'NoColor'):
376 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
376 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
377
377
378 def __call__(self, etype, value, elist):
378 def __call__(self, etype, value, elist):
379 Term.cout.flush()
379 Term.cout.flush()
380 print >> Term.cerr, self.text(etype,value,elist)
380 print >> Term.cerr, self.text(etype,value,elist)
381 Term.cerr.flush()
381 Term.cerr.flush()
382
382
383 def text(self,etype, value, elist,context=5):
383 def text(self,etype, value, elist,context=5):
384 """Return a color formatted string with the traceback info."""
384 """Return a color formatted string with the traceback info."""
385
385
386 Colors = self.Colors
386 Colors = self.Colors
387 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
387 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
388 if elist:
388 if elist:
389 out_string.append('Traceback %s(most recent call last)%s:' % \
389 out_string.append('Traceback %s(most recent call last)%s:' % \
390 (Colors.normalEm, Colors.Normal) + '\n')
390 (Colors.normalEm, Colors.Normal) + '\n')
391 out_string.extend(self._format_list(elist))
391 out_string.extend(self._format_list(elist))
392 lines = self._format_exception_only(etype, value)
392 lines = self._format_exception_only(etype, value)
393 for line in lines[:-1]:
393 for line in lines[:-1]:
394 out_string.append(" "+line)
394 out_string.append(" "+line)
395 out_string.append(lines[-1])
395 out_string.append(lines[-1])
396 return ''.join(out_string)
396 return ''.join(out_string)
397
397
398 def _format_list(self, extracted_list):
398 def _format_list(self, extracted_list):
399 """Format a list of traceback entry tuples for printing.
399 """Format a list of traceback entry tuples for printing.
400
400
401 Given a list of tuples as returned by extract_tb() or
401 Given a list of tuples as returned by extract_tb() or
402 extract_stack(), return a list of strings ready for printing.
402 extract_stack(), return a list of strings ready for printing.
403 Each string in the resulting list corresponds to the item with the
403 Each string in the resulting list corresponds to the item with the
404 same index in the argument list. Each string ends in a newline;
404 same index in the argument list. Each string ends in a newline;
405 the strings may contain internal newlines as well, for those items
405 the strings may contain internal newlines as well, for those items
406 whose source text line is not None.
406 whose source text line is not None.
407
407
408 Lifted almost verbatim from traceback.py
408 Lifted almost verbatim from traceback.py
409 """
409 """
410
410
411 Colors = self.Colors
411 Colors = self.Colors
412 list = []
412 list = []
413 for filename, lineno, name, line in extracted_list[:-1]:
413 for filename, lineno, name, line in extracted_list[:-1]:
414 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
414 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
415 (Colors.filename, filename, Colors.Normal,
415 (Colors.filename, filename, Colors.Normal,
416 Colors.lineno, lineno, Colors.Normal,
416 Colors.lineno, lineno, Colors.Normal,
417 Colors.name, name, Colors.Normal)
417 Colors.name, name, Colors.Normal)
418 if line:
418 if line:
419 item = item + ' %s\n' % line.strip()
419 item = item + ' %s\n' % line.strip()
420 list.append(item)
420 list.append(item)
421 # Emphasize the last entry
421 # Emphasize the last entry
422 filename, lineno, name, line = extracted_list[-1]
422 filename, lineno, name, line = extracted_list[-1]
423 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
423 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
424 (Colors.normalEm,
424 (Colors.normalEm,
425 Colors.filenameEm, filename, Colors.normalEm,
425 Colors.filenameEm, filename, Colors.normalEm,
426 Colors.linenoEm, lineno, Colors.normalEm,
426 Colors.linenoEm, lineno, Colors.normalEm,
427 Colors.nameEm, name, Colors.normalEm,
427 Colors.nameEm, name, Colors.normalEm,
428 Colors.Normal)
428 Colors.Normal)
429 if line:
429 if line:
430 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
430 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
431 Colors.Normal)
431 Colors.Normal)
432 list.append(item)
432 list.append(item)
433 return list
433 return list
434
434
435 def _format_exception_only(self, etype, value):
435 def _format_exception_only(self, etype, value):
436 """Format the exception part of a traceback.
436 """Format the exception part of a traceback.
437
437
438 The arguments are the exception type and value such as given by
438 The arguments are the exception type and value such as given by
439 sys.exc_info()[:2]. The return value is a list of strings, each ending
439 sys.exc_info()[:2]. The return value is a list of strings, each ending
440 in a newline. Normally, the list contains a single string; however,
440 in a newline. Normally, the list contains a single string; however,
441 for SyntaxError exceptions, it contains several lines that (when
441 for SyntaxError exceptions, it contains several lines that (when
442 printed) display detailed information about where the syntax error
442 printed) display detailed information about where the syntax error
443 occurred. The message indicating which exception occurred is the
443 occurred. The message indicating which exception occurred is the
444 always last string in the list.
444 always last string in the list.
445
445
446 Also lifted nearly verbatim from traceback.py
446 Also lifted nearly verbatim from traceback.py
447 """
447 """
448
448
449 Colors = self.Colors
449 Colors = self.Colors
450 list = []
450 list = []
451 try:
451 try:
452 stype = Colors.excName + etype.__name__ + Colors.Normal
452 stype = Colors.excName + etype.__name__ + Colors.Normal
453 except AttributeError:
453 except AttributeError:
454 stype = etype # String exceptions don't get special coloring
454 stype = etype # String exceptions don't get special coloring
455 if value is None:
455 if value is None:
456 list.append( str(stype) + '\n')
456 list.append( str(stype) + '\n')
457 else:
457 else:
458 if etype is SyntaxError:
458 if etype is SyntaxError:
459 try:
459 try:
460 msg, (filename, lineno, offset, line) = value
460 msg, (filename, lineno, offset, line) = value
461 except:
461 except:
462 pass
462 pass
463 else:
463 else:
464 #print 'filename is',filename # dbg
464 #print 'filename is',filename # dbg
465 if not filename: filename = "<string>"
465 if not filename: filename = "<string>"
466 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
466 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
467 (Colors.normalEm,
467 (Colors.normalEm,
468 Colors.filenameEm, filename, Colors.normalEm,
468 Colors.filenameEm, filename, Colors.normalEm,
469 Colors.linenoEm, lineno, Colors.Normal ))
469 Colors.linenoEm, lineno, Colors.Normal ))
470 if line is not None:
470 if line is not None:
471 i = 0
471 i = 0
472 while i < len(line) and line[i].isspace():
472 while i < len(line) and line[i].isspace():
473 i = i+1
473 i = i+1
474 list.append('%s %s%s\n' % (Colors.line,
474 list.append('%s %s%s\n' % (Colors.line,
475 line.strip(),
475 line.strip(),
476 Colors.Normal))
476 Colors.Normal))
477 if offset is not None:
477 if offset is not None:
478 s = ' '
478 s = ' '
479 for c in line[i:offset-1]:
479 for c in line[i:offset-1]:
480 if c.isspace():
480 if c.isspace():
481 s = s + c
481 s = s + c
482 else:
482 else:
483 s = s + ' '
483 s = s + ' '
484 list.append('%s%s^%s\n' % (Colors.caret, s,
484 list.append('%s%s^%s\n' % (Colors.caret, s,
485 Colors.Normal) )
485 Colors.Normal) )
486 value = msg
486 value = msg
487 s = self._some_str(value)
487 s = self._some_str(value)
488 if s:
488 if s:
489 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
489 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
490 Colors.Normal, s))
490 Colors.Normal, s))
491 else:
491 else:
492 list.append('%s\n' % str(stype))
492 list.append('%s\n' % str(stype))
493
494 # vds:>>
495 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
496 # vds:<<
497
493 return list
498 return list
494
499
495 def _some_str(self, value):
500 def _some_str(self, value):
496 # Lifted from traceback.py
501 # Lifted from traceback.py
497 try:
502 try:
498 return str(value)
503 return str(value)
499 except:
504 except:
500 return '<unprintable %s object>' % type(value).__name__
505 return '<unprintable %s object>' % type(value).__name__
501
506
502 #----------------------------------------------------------------------------
507 #----------------------------------------------------------------------------
503 class VerboseTB(TBTools):
508 class VerboseTB(TBTools):
504 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
509 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
505 of HTML. Requires inspect and pydoc. Crazy, man.
510 of HTML. Requires inspect and pydoc. Crazy, man.
506
511
507 Modified version which optionally strips the topmost entries from the
512 Modified version which optionally strips the topmost entries from the
508 traceback, to be used with alternate interpreters (because their own code
513 traceback, to be used with alternate interpreters (because their own code
509 would appear in the traceback)."""
514 would appear in the traceback)."""
510
515
511 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
516 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
512 call_pdb = 0, include_vars=1):
517 call_pdb = 0, include_vars=1):
513 """Specify traceback offset, headers and color scheme.
518 """Specify traceback offset, headers and color scheme.
514
519
515 Define how many frames to drop from the tracebacks. Calling it with
520 Define how many frames to drop from the tracebacks. Calling it with
516 tb_offset=1 allows use of this handler in interpreters which will have
521 tb_offset=1 allows use of this handler in interpreters which will have
517 their own code at the top of the traceback (VerboseTB will first
522 their own code at the top of the traceback (VerboseTB will first
518 remove that frame before printing the traceback info)."""
523 remove that frame before printing the traceback info)."""
519 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
524 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
520 self.tb_offset = tb_offset
525 self.tb_offset = tb_offset
521 self.long_header = long_header
526 self.long_header = long_header
522 self.include_vars = include_vars
527 self.include_vars = include_vars
523
528
524 def text(self, etype, evalue, etb, context=5):
529 def text(self, etype, evalue, etb, context=5):
525 """Return a nice text document describing the traceback."""
530 """Return a nice text document describing the traceback."""
526
531
527 # some locals
532 # some locals
528 try:
533 try:
529 etype = etype.__name__
534 etype = etype.__name__
530 except AttributeError:
535 except AttributeError:
531 pass
536 pass
532 Colors = self.Colors # just a shorthand + quicker name lookup
537 Colors = self.Colors # just a shorthand + quicker name lookup
533 ColorsNormal = Colors.Normal # used a lot
538 ColorsNormal = Colors.Normal # used a lot
534 col_scheme = self.color_scheme_table.active_scheme_name
539 col_scheme = self.color_scheme_table.active_scheme_name
535 indent = ' '*INDENT_SIZE
540 indent = ' '*INDENT_SIZE
536 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
541 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
537 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
542 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
538 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
543 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
539
544
540 # some internal-use functions
545 # some internal-use functions
541 def text_repr(value):
546 def text_repr(value):
542 """Hopefully pretty robust repr equivalent."""
547 """Hopefully pretty robust repr equivalent."""
543 # this is pretty horrible but should always return *something*
548 # this is pretty horrible but should always return *something*
544 try:
549 try:
545 return pydoc.text.repr(value)
550 return pydoc.text.repr(value)
546 except KeyboardInterrupt:
551 except KeyboardInterrupt:
547 raise
552 raise
548 except:
553 except:
549 try:
554 try:
550 return repr(value)
555 return repr(value)
551 except KeyboardInterrupt:
556 except KeyboardInterrupt:
552 raise
557 raise
553 except:
558 except:
554 try:
559 try:
555 # all still in an except block so we catch
560 # all still in an except block so we catch
556 # getattr raising
561 # getattr raising
557 name = getattr(value, '__name__', None)
562 name = getattr(value, '__name__', None)
558 if name:
563 if name:
559 # ick, recursion
564 # ick, recursion
560 return text_repr(name)
565 return text_repr(name)
561 klass = getattr(value, '__class__', None)
566 klass = getattr(value, '__class__', None)
562 if klass:
567 if klass:
563 return '%s instance' % text_repr(klass)
568 return '%s instance' % text_repr(klass)
564 except KeyboardInterrupt:
569 except KeyboardInterrupt:
565 raise
570 raise
566 except:
571 except:
567 return 'UNRECOVERABLE REPR FAILURE'
572 return 'UNRECOVERABLE REPR FAILURE'
568 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
573 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
569 def nullrepr(value, repr=text_repr): return ''
574 def nullrepr(value, repr=text_repr): return ''
570
575
571 # meat of the code begins
576 # meat of the code begins
572 try:
577 try:
573 etype = etype.__name__
578 etype = etype.__name__
574 except AttributeError:
579 except AttributeError:
575 pass
580 pass
576
581
577 if self.long_header:
582 if self.long_header:
578 # Header with the exception type, python version, and date
583 # Header with the exception type, python version, and date
579 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
584 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
580 date = time.ctime(time.time())
585 date = time.ctime(time.time())
581
586
582 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
587 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
583 exc, ' '*(75-len(str(etype))-len(pyver)),
588 exc, ' '*(75-len(str(etype))-len(pyver)),
584 pyver, string.rjust(date, 75) )
589 pyver, string.rjust(date, 75) )
585 head += "\nA problem occured executing Python code. Here is the sequence of function"\
590 head += "\nA problem occured executing Python code. Here is the sequence of function"\
586 "\ncalls leading up to the error, with the most recent (innermost) call last."
591 "\ncalls leading up to the error, with the most recent (innermost) call last."
587 else:
592 else:
588 # Simplified header
593 # Simplified header
589 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
594 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
590 string.rjust('Traceback (most recent call last)',
595 string.rjust('Traceback (most recent call last)',
591 75 - len(str(etype)) ) )
596 75 - len(str(etype)) ) )
592 frames = []
597 frames = []
593 # Flush cache before calling inspect. This helps alleviate some of the
598 # Flush cache before calling inspect. This helps alleviate some of the
594 # problems with python 2.3's inspect.py.
599 # problems with python 2.3's inspect.py.
595 linecache.checkcache()
600 linecache.checkcache()
596 # Drop topmost frames if requested
601 # Drop topmost frames if requested
597 try:
602 try:
598 # Try the default getinnerframes and Alex's: Alex's fixes some
603 # Try the default getinnerframes and Alex's: Alex's fixes some
599 # problems, but it generates empty tracebacks for console errors
604 # problems, but it generates empty tracebacks for console errors
600 # (5 blanks lines) where none should be returned.
605 # (5 blanks lines) where none should be returned.
601 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
606 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
602 #print 'python records:', records # dbg
607 #print 'python records:', records # dbg
603 records = _fixed_getinnerframes(etb, context,self.tb_offset)
608 records = _fixed_getinnerframes(etb, context,self.tb_offset)
604 #print 'alex records:', records # dbg
609 #print 'alex records:', records # dbg
605 except:
610 except:
606
611
607 # FIXME: I've been getting many crash reports from python 2.3
612 # FIXME: I've been getting many crash reports from python 2.3
608 # users, traceable to inspect.py. If I can find a small test-case
613 # users, traceable to inspect.py. If I can find a small test-case
609 # to reproduce this, I should either write a better workaround or
614 # to reproduce this, I should either write a better workaround or
610 # file a bug report against inspect (if that's the real problem).
615 # file a bug report against inspect (if that's the real problem).
611 # So far, I haven't been able to find an isolated example to
616 # So far, I haven't been able to find an isolated example to
612 # reproduce the problem.
617 # reproduce the problem.
613 inspect_error()
618 inspect_error()
614 traceback.print_exc(file=Term.cerr)
619 traceback.print_exc(file=Term.cerr)
615 info('\nUnfortunately, your original traceback can not be constructed.\n')
620 info('\nUnfortunately, your original traceback can not be constructed.\n')
616 return ''
621 return ''
617
622
618 # build some color string templates outside these nested loops
623 # build some color string templates outside these nested loops
619 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
624 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
620 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
625 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
621 ColorsNormal)
626 ColorsNormal)
622 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
627 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
623 (Colors.vName, Colors.valEm, ColorsNormal)
628 (Colors.vName, Colors.valEm, ColorsNormal)
624 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
629 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
625 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
630 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
626 Colors.vName, ColorsNormal)
631 Colors.vName, ColorsNormal)
627 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
632 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
628 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
633 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
629 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
634 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
630 ColorsNormal)
635 ColorsNormal)
631
636
632 # now, loop over all records printing context and info
637 # now, loop over all records printing context and info
633 abspath = os.path.abspath
638 abspath = os.path.abspath
634 for frame, file, lnum, func, lines, index in records:
639 for frame, file, lnum, func, lines, index in records:
635 #print '*** record:',file,lnum,func,lines,index # dbg
640 #print '*** record:',file,lnum,func,lines,index # dbg
636 try:
641 try:
637 file = file and abspath(file) or '?'
642 file = file and abspath(file) or '?'
638 except OSError:
643 except OSError:
639 # if file is '<console>' or something not in the filesystem,
644 # if file is '<console>' or something not in the filesystem,
640 # the abspath call will throw an OSError. Just ignore it and
645 # the abspath call will throw an OSError. Just ignore it and
641 # keep the original file string.
646 # keep the original file string.
642 pass
647 pass
643 link = tpl_link % file
648 link = tpl_link % file
644 try:
649 try:
645 args, varargs, varkw, locals = inspect.getargvalues(frame)
650 args, varargs, varkw, locals = inspect.getargvalues(frame)
646 except:
651 except:
647 # This can happen due to a bug in python2.3. We should be
652 # This can happen due to a bug in python2.3. We should be
648 # able to remove this try/except when 2.4 becomes a
653 # able to remove this try/except when 2.4 becomes a
649 # requirement. Bug details at http://python.org/sf/1005466
654 # requirement. Bug details at http://python.org/sf/1005466
650 inspect_error()
655 inspect_error()
651 traceback.print_exc(file=Term.cerr)
656 traceback.print_exc(file=Term.cerr)
652 info("\nIPython's exception reporting continues...\n")
657 info("\nIPython's exception reporting continues...\n")
653
658
654 if func == '?':
659 if func == '?':
655 call = ''
660 call = ''
656 else:
661 else:
657 # Decide whether to include variable details or not
662 # Decide whether to include variable details or not
658 var_repr = self.include_vars and eqrepr or nullrepr
663 var_repr = self.include_vars and eqrepr or nullrepr
659 try:
664 try:
660 call = tpl_call % (func,inspect.formatargvalues(args,
665 call = tpl_call % (func,inspect.formatargvalues(args,
661 varargs, varkw,
666 varargs, varkw,
662 locals,formatvalue=var_repr))
667 locals,formatvalue=var_repr))
663 except KeyError:
668 except KeyError:
664 # Very odd crash from inspect.formatargvalues(). The
669 # Very odd crash from inspect.formatargvalues(). The
665 # scenario under which it appeared was a call to
670 # scenario under which it appeared was a call to
666 # view(array,scale) in NumTut.view.view(), where scale had
671 # view(array,scale) in NumTut.view.view(), where scale had
667 # been defined as a scalar (it should be a tuple). Somehow
672 # been defined as a scalar (it should be a tuple). Somehow
668 # inspect messes up resolving the argument list of view()
673 # inspect messes up resolving the argument list of view()
669 # and barfs out. At some point I should dig into this one
674 # and barfs out. At some point I should dig into this one
670 # and file a bug report about it.
675 # and file a bug report about it.
671 inspect_error()
676 inspect_error()
672 traceback.print_exc(file=Term.cerr)
677 traceback.print_exc(file=Term.cerr)
673 info("\nIPython's exception reporting continues...\n")
678 info("\nIPython's exception reporting continues...\n")
674 call = tpl_call_fail % func
679 call = tpl_call_fail % func
675
680
676 # Initialize a list of names on the current line, which the
681 # Initialize a list of names on the current line, which the
677 # tokenizer below will populate.
682 # tokenizer below will populate.
678 names = []
683 names = []
679
684
680 def tokeneater(token_type, token, start, end, line):
685 def tokeneater(token_type, token, start, end, line):
681 """Stateful tokeneater which builds dotted names.
686 """Stateful tokeneater which builds dotted names.
682
687
683 The list of names it appends to (from the enclosing scope) can
688 The list of names it appends to (from the enclosing scope) can
684 contain repeated composite names. This is unavoidable, since
689 contain repeated composite names. This is unavoidable, since
685 there is no way to disambguate partial dotted structures until
690 there is no way to disambguate partial dotted structures until
686 the full list is known. The caller is responsible for pruning
691 the full list is known. The caller is responsible for pruning
687 the final list of duplicates before using it."""
692 the final list of duplicates before using it."""
688
693
689 # build composite names
694 # build composite names
690 if token == '.':
695 if token == '.':
691 try:
696 try:
692 names[-1] += '.'
697 names[-1] += '.'
693 # store state so the next token is added for x.y.z names
698 # store state so the next token is added for x.y.z names
694 tokeneater.name_cont = True
699 tokeneater.name_cont = True
695 return
700 return
696 except IndexError:
701 except IndexError:
697 pass
702 pass
698 if token_type == tokenize.NAME and token not in keyword.kwlist:
703 if token_type == tokenize.NAME and token not in keyword.kwlist:
699 if tokeneater.name_cont:
704 if tokeneater.name_cont:
700 # Dotted names
705 # Dotted names
701 names[-1] += token
706 names[-1] += token
702 tokeneater.name_cont = False
707 tokeneater.name_cont = False
703 else:
708 else:
704 # Regular new names. We append everything, the caller
709 # Regular new names. We append everything, the caller
705 # will be responsible for pruning the list later. It's
710 # will be responsible for pruning the list later. It's
706 # very tricky to try to prune as we go, b/c composite
711 # very tricky to try to prune as we go, b/c composite
707 # names can fool us. The pruning at the end is easy
712 # names can fool us. The pruning at the end is easy
708 # to do (or the caller can print a list with repeated
713 # to do (or the caller can print a list with repeated
709 # names if so desired.
714 # names if so desired.
710 names.append(token)
715 names.append(token)
711 elif token_type == tokenize.NEWLINE:
716 elif token_type == tokenize.NEWLINE:
712 raise IndexError
717 raise IndexError
713 # we need to store a bit of state in the tokenizer to build
718 # we need to store a bit of state in the tokenizer to build
714 # dotted names
719 # dotted names
715 tokeneater.name_cont = False
720 tokeneater.name_cont = False
716
721
717 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
722 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
718 line = getline(file, lnum[0])
723 line = getline(file, lnum[0])
719 lnum[0] += 1
724 lnum[0] += 1
720 return line
725 return line
721
726
722 # Build the list of names on this line of code where the exception
727 # Build the list of names on this line of code where the exception
723 # occurred.
728 # occurred.
724 try:
729 try:
725 # This builds the names list in-place by capturing it from the
730 # This builds the names list in-place by capturing it from the
726 # enclosing scope.
731 # enclosing scope.
727 tokenize.tokenize(linereader, tokeneater)
732 tokenize.tokenize(linereader, tokeneater)
728 except IndexError:
733 except IndexError:
729 # signals exit of tokenizer
734 # signals exit of tokenizer
730 pass
735 pass
731 except tokenize.TokenError,msg:
736 except tokenize.TokenError,msg:
732 _m = ("An unexpected error occurred while tokenizing input\n"
737 _m = ("An unexpected error occurred while tokenizing input\n"
733 "The following traceback may be corrupted or invalid\n"
738 "The following traceback may be corrupted or invalid\n"
734 "The error message is: %s\n" % msg)
739 "The error message is: %s\n" % msg)
735 error(_m)
740 error(_m)
736
741
737 # prune names list of duplicates, but keep the right order
742 # prune names list of duplicates, but keep the right order
738 unique_names = uniq_stable(names)
743 unique_names = uniq_stable(names)
739
744
740 # Start loop over vars
745 # Start loop over vars
741 lvals = []
746 lvals = []
742 if self.include_vars:
747 if self.include_vars:
743 for name_full in unique_names:
748 for name_full in unique_names:
744 name_base = name_full.split('.',1)[0]
749 name_base = name_full.split('.',1)[0]
745 if name_base in frame.f_code.co_varnames:
750 if name_base in frame.f_code.co_varnames:
746 if locals.has_key(name_base):
751 if locals.has_key(name_base):
747 try:
752 try:
748 value = repr(eval(name_full,locals))
753 value = repr(eval(name_full,locals))
749 except:
754 except:
750 value = undefined
755 value = undefined
751 else:
756 else:
752 value = undefined
757 value = undefined
753 name = tpl_local_var % name_full
758 name = tpl_local_var % name_full
754 else:
759 else:
755 if frame.f_globals.has_key(name_base):
760 if frame.f_globals.has_key(name_base):
756 try:
761 try:
757 value = repr(eval(name_full,frame.f_globals))
762 value = repr(eval(name_full,frame.f_globals))
758 except:
763 except:
759 value = undefined
764 value = undefined
760 else:
765 else:
761 value = undefined
766 value = undefined
762 name = tpl_global_var % name_full
767 name = tpl_global_var % name_full
763 lvals.append(tpl_name_val % (name,value))
768 lvals.append(tpl_name_val % (name,value))
764 if lvals:
769 if lvals:
765 lvals = '%s%s' % (indent,em_normal.join(lvals))
770 lvals = '%s%s' % (indent,em_normal.join(lvals))
766 else:
771 else:
767 lvals = ''
772 lvals = ''
768
773
769 level = '%s %s\n' % (link,call)
774 level = '%s %s\n' % (link,call)
770
775
771 if index is None:
776 if index is None:
772 frames.append(level)
777 frames.append(level)
773 else:
778 else:
774 frames.append('%s%s' % (level,''.join(
779 frames.append('%s%s' % (level,''.join(
775 _formatTracebackLines(lnum,index,lines,Colors,lvals,
780 _formatTracebackLines(lnum,index,lines,Colors,lvals,
776 col_scheme))))
781 col_scheme))))
777
782
778 # Get (safely) a string form of the exception info
783 # Get (safely) a string form of the exception info
779 try:
784 try:
780 etype_str,evalue_str = map(str,(etype,evalue))
785 etype_str,evalue_str = map(str,(etype,evalue))
781 except:
786 except:
782 # User exception is improperly defined.
787 # User exception is improperly defined.
783 etype,evalue = str,sys.exc_info()[:2]
788 etype,evalue = str,sys.exc_info()[:2]
784 etype_str,evalue_str = map(str,(etype,evalue))
789 etype_str,evalue_str = map(str,(etype,evalue))
785 # ... and format it
790 # ... and format it
786 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
791 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
787 ColorsNormal, evalue_str)]
792 ColorsNormal, evalue_str)]
788 if type(evalue) is types.InstanceType:
793 if type(evalue) is types.InstanceType:
789 try:
794 try:
790 names = [w for w in dir(evalue) if isinstance(w, basestring)]
795 names = [w for w in dir(evalue) if isinstance(w, basestring)]
791 except:
796 except:
792 # Every now and then, an object with funny inernals blows up
797 # Every now and then, an object with funny inernals blows up
793 # when dir() is called on it. We do the best we can to report
798 # when dir() is called on it. We do the best we can to report
794 # the problem and continue
799 # the problem and continue
795 _m = '%sException reporting error (object with broken dir())%s:'
800 _m = '%sException reporting error (object with broken dir())%s:'
796 exception.append(_m % (Colors.excName,ColorsNormal))
801 exception.append(_m % (Colors.excName,ColorsNormal))
797 etype_str,evalue_str = map(str,sys.exc_info()[:2])
802 etype_str,evalue_str = map(str,sys.exc_info()[:2])
798 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
803 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
799 ColorsNormal, evalue_str))
804 ColorsNormal, evalue_str))
800 names = []
805 names = []
801 for name in names:
806 for name in names:
802 value = text_repr(getattr(evalue, name))
807 value = text_repr(getattr(evalue, name))
803 exception.append('\n%s%s = %s' % (indent, name, value))
808 exception.append('\n%s%s = %s' % (indent, name, value))
809
810 # vds: >>
811 if records:
812 frame, file, lnum, func, lines, index = records[-1]
813 #print "file:", str(file), "linenb", str(lnum)
814 file = abspath(file)
815 __IPYTHON__.hooks.synchronize_with_editor(file, lnum, 0)
816 # vds: <<
817
804 # return all our info assembled as a single string
818 # return all our info assembled as a single string
805 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
819 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
806
820
807 def debugger(self,force=False):
821 def debugger(self,force=False):
808 """Call up the pdb debugger if desired, always clean up the tb
822 """Call up the pdb debugger if desired, always clean up the tb
809 reference.
823 reference.
810
824
811 Keywords:
825 Keywords:
812
826
813 - force(False): by default, this routine checks the instance call_pdb
827 - force(False): by default, this routine checks the instance call_pdb
814 flag and does not actually invoke the debugger if the flag is false.
828 flag and does not actually invoke the debugger if the flag is false.
815 The 'force' option forces the debugger to activate even if the flag
829 The 'force' option forces the debugger to activate even if the flag
816 is false.
830 is false.
817
831
818 If the call_pdb flag is set, the pdb interactive debugger is
832 If the call_pdb flag is set, the pdb interactive debugger is
819 invoked. In all cases, the self.tb reference to the current traceback
833 invoked. In all cases, the self.tb reference to the current traceback
820 is deleted to prevent lingering references which hamper memory
834 is deleted to prevent lingering references which hamper memory
821 management.
835 management.
822
836
823 Note that each call to pdb() does an 'import readline', so if your app
837 Note that each call to pdb() does an 'import readline', so if your app
824 requires a special setup for the readline completers, you'll have to
838 requires a special setup for the readline completers, you'll have to
825 fix that by hand after invoking the exception handler."""
839 fix that by hand after invoking the exception handler."""
826
840
827 if force or self.call_pdb:
841 if force or self.call_pdb:
828 if self.pdb is None:
842 if self.pdb is None:
829 self.pdb = Debugger.Pdb(
843 self.pdb = Debugger.Pdb(
830 self.color_scheme_table.active_scheme_name)
844 self.color_scheme_table.active_scheme_name)
831 # the system displayhook may have changed, restore the original
845 # the system displayhook may have changed, restore the original
832 # for pdb
846 # for pdb
833 dhook = sys.displayhook
847 dhook = sys.displayhook
834 sys.displayhook = sys.__displayhook__
848 sys.displayhook = sys.__displayhook__
835 self.pdb.reset()
849 self.pdb.reset()
836 # Find the right frame so we don't pop up inside ipython itself
850 # Find the right frame so we don't pop up inside ipython itself
837 if hasattr(self,'tb'):
851 if hasattr(self,'tb'):
838 etb = self.tb
852 etb = self.tb
839 else:
853 else:
840 etb = self.tb = sys.last_traceback
854 etb = self.tb = sys.last_traceback
841 while self.tb.tb_next is not None:
855 while self.tb.tb_next is not None:
842 self.tb = self.tb.tb_next
856 self.tb = self.tb.tb_next
843 try:
857 try:
844 if etb and etb.tb_next:
858 if etb and etb.tb_next:
845 etb = etb.tb_next
859 etb = etb.tb_next
846 self.pdb.botframe = etb.tb_frame
860 self.pdb.botframe = etb.tb_frame
847 self.pdb.interaction(self.tb.tb_frame, self.tb)
861 self.pdb.interaction(self.tb.tb_frame, self.tb)
848 finally:
862 finally:
849 sys.displayhook = dhook
863 sys.displayhook = dhook
850
864
851 if hasattr(self,'tb'):
865 if hasattr(self,'tb'):
852 del self.tb
866 del self.tb
853
867
854 def handler(self, info=None):
868 def handler(self, info=None):
855 (etype, evalue, etb) = info or sys.exc_info()
869 (etype, evalue, etb) = info or sys.exc_info()
856 self.tb = etb
870 self.tb = etb
857 Term.cout.flush()
871 Term.cout.flush()
858 print >> Term.cerr, self.text(etype, evalue, etb)
872 print >> Term.cerr, self.text(etype, evalue, etb)
859 Term.cerr.flush()
873 Term.cerr.flush()
860
874
861 # Changed so an instance can just be called as VerboseTB_inst() and print
875 # Changed so an instance can just be called as VerboseTB_inst() and print
862 # out the right info on its own.
876 # out the right info on its own.
863 def __call__(self, etype=None, evalue=None, etb=None):
877 def __call__(self, etype=None, evalue=None, etb=None):
864 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
878 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
865 if etb is None:
879 if etb is None:
866 self.handler()
880 self.handler()
867 else:
881 else:
868 self.handler((etype, evalue, etb))
882 self.handler((etype, evalue, etb))
869 try:
883 try:
870 self.debugger()
884 self.debugger()
871 except KeyboardInterrupt:
885 except KeyboardInterrupt:
872 print "\nKeyboardInterrupt"
886 print "\nKeyboardInterrupt"
873
887
874 #----------------------------------------------------------------------------
888 #----------------------------------------------------------------------------
875 class FormattedTB(VerboseTB,ListTB):
889 class FormattedTB(VerboseTB,ListTB):
876 """Subclass ListTB but allow calling with a traceback.
890 """Subclass ListTB but allow calling with a traceback.
877
891
878 It can thus be used as a sys.excepthook for Python > 2.1.
892 It can thus be used as a sys.excepthook for Python > 2.1.
879
893
880 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
894 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
881
895
882 Allows a tb_offset to be specified. This is useful for situations where
896 Allows a tb_offset to be specified. This is useful for situations where
883 one needs to remove a number of topmost frames from the traceback (such as
897 one needs to remove a number of topmost frames from the traceback (such as
884 occurs with python programs that themselves execute other python code,
898 occurs with python programs that themselves execute other python code,
885 like Python shells). """
899 like Python shells). """
886
900
887 def __init__(self, mode = 'Plain', color_scheme='Linux',
901 def __init__(self, mode = 'Plain', color_scheme='Linux',
888 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
902 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
889
903
890 # NEVER change the order of this list. Put new modes at the end:
904 # NEVER change the order of this list. Put new modes at the end:
891 self.valid_modes = ['Plain','Context','Verbose']
905 self.valid_modes = ['Plain','Context','Verbose']
892 self.verbose_modes = self.valid_modes[1:3]
906 self.verbose_modes = self.valid_modes[1:3]
893
907
894 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
908 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
895 call_pdb=call_pdb,include_vars=include_vars)
909 call_pdb=call_pdb,include_vars=include_vars)
896 self.set_mode(mode)
910 self.set_mode(mode)
897
911
898 def _extract_tb(self,tb):
912 def _extract_tb(self,tb):
899 if tb:
913 if tb:
900 return traceback.extract_tb(tb)
914 return traceback.extract_tb(tb)
901 else:
915 else:
902 return None
916 return None
903
917
904 def text(self, etype, value, tb,context=5,mode=None):
918 def text(self, etype, value, tb,context=5,mode=None):
905 """Return formatted traceback.
919 """Return formatted traceback.
906
920
907 If the optional mode parameter is given, it overrides the current
921 If the optional mode parameter is given, it overrides the current
908 mode."""
922 mode."""
909
923
910 if mode is None:
924 if mode is None:
911 mode = self.mode
925 mode = self.mode
912 if mode in self.verbose_modes:
926 if mode in self.verbose_modes:
913 # verbose modes need a full traceback
927 # verbose modes need a full traceback
914 return VerboseTB.text(self,etype, value, tb,context=5)
928 return VerboseTB.text(self,etype, value, tb,context=5)
915 else:
929 else:
916 # We must check the source cache because otherwise we can print
930 # We must check the source cache because otherwise we can print
917 # out-of-date source code.
931 # out-of-date source code.
918 linecache.checkcache()
932 linecache.checkcache()
919 # Now we can extract and format the exception
933 # Now we can extract and format the exception
920 elist = self._extract_tb(tb)
934 elist = self._extract_tb(tb)
921 if len(elist) > self.tb_offset:
935 if len(elist) > self.tb_offset:
922 del elist[:self.tb_offset]
936 del elist[:self.tb_offset]
923 return ListTB.text(self,etype,value,elist)
937 return ListTB.text(self,etype,value,elist)
924
938
925 def set_mode(self,mode=None):
939 def set_mode(self,mode=None):
926 """Switch to the desired mode.
940 """Switch to the desired mode.
927
941
928 If mode is not specified, cycles through the available modes."""
942 If mode is not specified, cycles through the available modes."""
929
943
930 if not mode:
944 if not mode:
931 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
945 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
932 len(self.valid_modes)
946 len(self.valid_modes)
933 self.mode = self.valid_modes[new_idx]
947 self.mode = self.valid_modes[new_idx]
934 elif mode not in self.valid_modes:
948 elif mode not in self.valid_modes:
935 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
949 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
936 'Valid modes: '+str(self.valid_modes)
950 'Valid modes: '+str(self.valid_modes)
937 else:
951 else:
938 self.mode = mode
952 self.mode = mode
939 # include variable details only in 'Verbose' mode
953 # include variable details only in 'Verbose' mode
940 self.include_vars = (self.mode == self.valid_modes[2])
954 self.include_vars = (self.mode == self.valid_modes[2])
941
955
942 # some convenient shorcuts
956 # some convenient shorcuts
943 def plain(self):
957 def plain(self):
944 self.set_mode(self.valid_modes[0])
958 self.set_mode(self.valid_modes[0])
945
959
946 def context(self):
960 def context(self):
947 self.set_mode(self.valid_modes[1])
961 self.set_mode(self.valid_modes[1])
948
962
949 def verbose(self):
963 def verbose(self):
950 self.set_mode(self.valid_modes[2])
964 self.set_mode(self.valid_modes[2])
951
965
952 #----------------------------------------------------------------------------
966 #----------------------------------------------------------------------------
953 class AutoFormattedTB(FormattedTB):
967 class AutoFormattedTB(FormattedTB):
954 """A traceback printer which can be called on the fly.
968 """A traceback printer which can be called on the fly.
955
969
956 It will find out about exceptions by itself.
970 It will find out about exceptions by itself.
957
971
958 A brief example:
972 A brief example:
959
973
960 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
974 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
961 try:
975 try:
962 ...
976 ...
963 except:
977 except:
964 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
978 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
965 """
979 """
966 def __call__(self,etype=None,evalue=None,etb=None,
980 def __call__(self,etype=None,evalue=None,etb=None,
967 out=None,tb_offset=None):
981 out=None,tb_offset=None):
968 """Print out a formatted exception traceback.
982 """Print out a formatted exception traceback.
969
983
970 Optional arguments:
984 Optional arguments:
971 - out: an open file-like object to direct output to.
985 - out: an open file-like object to direct output to.
972
986
973 - tb_offset: the number of frames to skip over in the stack, on a
987 - tb_offset: the number of frames to skip over in the stack, on a
974 per-call basis (this overrides temporarily the instance's tb_offset
988 per-call basis (this overrides temporarily the instance's tb_offset
975 given at initialization time. """
989 given at initialization time. """
976
990
977 if out is None:
991 if out is None:
978 out = Term.cerr
992 out = Term.cerr
979 Term.cout.flush()
993 Term.cout.flush()
980 if tb_offset is not None:
994 if tb_offset is not None:
981 tb_offset, self.tb_offset = self.tb_offset, tb_offset
995 tb_offset, self.tb_offset = self.tb_offset, tb_offset
982 print >> out, self.text(etype, evalue, etb)
996 print >> out, self.text(etype, evalue, etb)
983 self.tb_offset = tb_offset
997 self.tb_offset = tb_offset
984 else:
998 else:
985 print >> out, self.text(etype, evalue, etb)
999 print >> out, self.text(etype, evalue, etb)
986 out.flush()
1000 out.flush()
987 try:
1001 try:
988 self.debugger()
1002 self.debugger()
989 except KeyboardInterrupt:
1003 except KeyboardInterrupt:
990 print "\nKeyboardInterrupt"
1004 print "\nKeyboardInterrupt"
991
1005
992 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1006 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
993 if etype is None:
1007 if etype is None:
994 etype,value,tb = sys.exc_info()
1008 etype,value,tb = sys.exc_info()
995 self.tb = tb
1009 self.tb = tb
996 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1010 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
997
1011
998 #---------------------------------------------------------------------------
1012 #---------------------------------------------------------------------------
999 # A simple class to preserve Nathan's original functionality.
1013 # A simple class to preserve Nathan's original functionality.
1000 class ColorTB(FormattedTB):
1014 class ColorTB(FormattedTB):
1001 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1015 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1002 def __init__(self,color_scheme='Linux',call_pdb=0):
1016 def __init__(self,color_scheme='Linux',call_pdb=0):
1003 FormattedTB.__init__(self,color_scheme=color_scheme,
1017 FormattedTB.__init__(self,color_scheme=color_scheme,
1004 call_pdb=call_pdb)
1018 call_pdb=call_pdb)
1005
1019
1006 #----------------------------------------------------------------------------
1020 #----------------------------------------------------------------------------
1007 # module testing (minimal)
1021 # module testing (minimal)
1008 if __name__ == "__main__":
1022 if __name__ == "__main__":
1009 def spam(c, (d, e)):
1023 def spam(c, (d, e)):
1010 x = c + d
1024 x = c + d
1011 y = c * d
1025 y = c * d
1012 foo(x, y)
1026 foo(x, y)
1013
1027
1014 def foo(a, b, bar=1):
1028 def foo(a, b, bar=1):
1015 eggs(a, b + bar)
1029 eggs(a, b + bar)
1016
1030
1017 def eggs(f, g, z=globals()):
1031 def eggs(f, g, z=globals()):
1018 h = f + g
1032 h = f + g
1019 i = f - g
1033 i = f - g
1020 return h / i
1034 return h / i
1021
1035
1022 print ''
1036 print ''
1023 print '*** Before ***'
1037 print '*** Before ***'
1024 try:
1038 try:
1025 print spam(1, (2, 3))
1039 print spam(1, (2, 3))
1026 except:
1040 except:
1027 traceback.print_exc()
1041 traceback.print_exc()
1028 print ''
1042 print ''
1029
1043
1030 handler = ColorTB()
1044 handler = ColorTB()
1031 print '*** ColorTB ***'
1045 print '*** ColorTB ***'
1032 try:
1046 try:
1033 print spam(1, (2, 3))
1047 print spam(1, (2, 3))
1034 except:
1048 except:
1035 apply(handler, sys.exc_info() )
1049 apply(handler, sys.exc_info() )
1036 print ''
1050 print ''
1037
1051
1038 handler = VerboseTB()
1052 handler = VerboseTB()
1039 print '*** VerboseTB ***'
1053 print '*** VerboseTB ***'
1040 try:
1054 try:
1041 print spam(1, (2, 3))
1055 print spam(1, (2, 3))
1042 except:
1056 except:
1043 apply(handler, sys.exc_info() )
1057 apply(handler, sys.exc_info() )
1044 print ''
1058 print ''
1045
1059
General Comments 0
You need to be logged in to leave comments. Login now