##// END OF EJS Templates
Fixing two minor bugs....
Brian Granger -
Show More
@@ -1,30 +1,30 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 This module is *completely* deprecated and should no longer be used for
4 This module is *completely* deprecated and should no longer be used for
5 any purpose. Currently, we have a few parts of the core that have
5 any purpose. Currently, we have a few parts of the core that have
6 not been componentized and thus, still rely on this module. When everything
6 not been componentized and thus, still rely on this module. When everything
7 has been made into a component, this module will be sent to deathrow.
7 has been made into a component, this module will be sent to deathrow.
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2009 The IPython Development Team
11 # Copyright (C) 2008-2009 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Classes and functions
22 # Classes and functions
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25
25
26 def get():
26 def get():
27 """Get the global InteractiveShell instance."""
27 """Get the global InteractiveShell instance."""
28 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
28 from IPython.core.interactiveshell import InteractiveShell
29 return TerminalInteractiveShell.instance()
29 return InteractiveShell.instance()
30
30
@@ -1,1156 +1,1156 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
63
64 #*****************************************************************************
64 #*****************************************************************************
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 #
67 #
68 # Distributed under the terms of the BSD License. The full license is in
68 # Distributed under the terms of the BSD License. The full license is in
69 # the file COPYING, distributed as part of this software.
69 # the file COPYING, distributed as part of this software.
70 #*****************************************************************************
70 #*****************************************************************************
71
71
72 from __future__ import with_statement
72 from __future__ import with_statement
73
73
74 import inspect
74 import inspect
75 import keyword
75 import keyword
76 import linecache
76 import linecache
77 import os
77 import os
78 import pydoc
78 import pydoc
79 import re
79 import re
80 import string
80 import string
81 import sys
81 import sys
82 import time
82 import time
83 import tokenize
83 import tokenize
84 import traceback
84 import traceback
85 import types
85 import types
86
86
87 # For purposes of monkeypatching inspect to fix a bug in it.
87 # For purposes of monkeypatching inspect to fix a bug in it.
88 from inspect import getsourcefile, getfile, getmodule,\
88 from inspect import getsourcefile, getfile, getmodule,\
89 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
90
90
91 # IPython's own modules
91 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
92 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython.utils import PyColorize
93 from IPython.utils import PyColorize
94 from IPython.core import debugger, ipapi
94 from IPython.core import debugger, ipapi
95 from IPython.core.display_trap import DisplayTrap
95 from IPython.core.display_trap import DisplayTrap
96 from IPython.core.excolors import exception_colors
96 from IPython.core.excolors import exception_colors
97 from IPython.utils.data import uniq_stable
97 from IPython.utils.data import uniq_stable
98 import IPython.utils.io
98 import IPython.utils.io
99 from IPython.utils.warn import info, error
99 from IPython.utils.warn import info, error
100
100
101 # Globals
101 # Globals
102 # amount of space to put line numbers before verbose tracebacks
102 # amount of space to put line numbers before verbose tracebacks
103 INDENT_SIZE = 8
103 INDENT_SIZE = 8
104
104
105 # Default color scheme. This is used, for example, by the traceback
105 # Default color scheme. This is used, for example, by the traceback
106 # formatter. When running in an actual IPython instance, the user's rc.colors
106 # formatter. When running in an actual IPython instance, the user's rc.colors
107 # value is used, but havinga module global makes this functionality available
107 # value is used, but havinga module global makes this functionality available
108 # to users of ultratb who are NOT running inside ipython.
108 # to users of ultratb who are NOT running inside ipython.
109 DEFAULT_SCHEME = 'NoColor'
109 DEFAULT_SCHEME = 'NoColor'
110
110
111 #---------------------------------------------------------------------------
111 #---------------------------------------------------------------------------
112 # Code begins
112 # Code begins
113
113
114 # Utility functions
114 # Utility functions
115 def inspect_error():
115 def inspect_error():
116 """Print a message about internal inspect errors.
116 """Print a message about internal inspect errors.
117
117
118 These are unfortunately quite common."""
118 These are unfortunately quite common."""
119
119
120 error('Internal Python error in the inspect module.\n'
120 error('Internal Python error in the inspect module.\n'
121 'Below is the traceback from this internal error.\n')
121 'Below is the traceback from this internal error.\n')
122
122
123
123
124 def findsource(object):
124 def findsource(object):
125 """Return the entire source file and starting line number for an object.
125 """Return the entire source file and starting line number for an object.
126
126
127 The argument may be a module, class, method, function, traceback, frame,
127 The argument may be a module, class, method, function, traceback, frame,
128 or code object. The source code is returned as a list of all the lines
128 or code object. The source code is returned as a list of all the lines
129 in the file and the line number indexes a line in that list. An IOError
129 in the file and the line number indexes a line in that list. An IOError
130 is raised if the source code cannot be retrieved.
130 is raised if the source code cannot be retrieved.
131
131
132 FIXED version with which we monkeypatch the stdlib to work around a bug."""
132 FIXED version with which we monkeypatch the stdlib to work around a bug."""
133
133
134 file = getsourcefile(object) or getfile(object)
134 file = getsourcefile(object) or getfile(object)
135 # If the object is a frame, then trying to get the globals dict from its
135 # If the object is a frame, then trying to get the globals dict from its
136 # module won't work. Instead, the frame object itself has the globals
136 # module won't work. Instead, the frame object itself has the globals
137 # dictionary.
137 # dictionary.
138 globals_dict = None
138 globals_dict = None
139 if inspect.isframe(object):
139 if inspect.isframe(object):
140 # XXX: can this ever be false?
140 # XXX: can this ever be false?
141 globals_dict = object.f_globals
141 globals_dict = object.f_globals
142 else:
142 else:
143 module = getmodule(object, file)
143 module = getmodule(object, file)
144 if module:
144 if module:
145 globals_dict = module.__dict__
145 globals_dict = module.__dict__
146 lines = linecache.getlines(file, globals_dict)
146 lines = linecache.getlines(file, globals_dict)
147 if not lines:
147 if not lines:
148 raise IOError('could not get source code')
148 raise IOError('could not get source code')
149
149
150 if ismodule(object):
150 if ismodule(object):
151 return lines, 0
151 return lines, 0
152
152
153 if isclass(object):
153 if isclass(object):
154 name = object.__name__
154 name = object.__name__
155 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
155 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
156 # make some effort to find the best matching class definition:
156 # make some effort to find the best matching class definition:
157 # use the one with the least indentation, which is the one
157 # use the one with the least indentation, which is the one
158 # that's most probably not inside a function definition.
158 # that's most probably not inside a function definition.
159 candidates = []
159 candidates = []
160 for i in range(len(lines)):
160 for i in range(len(lines)):
161 match = pat.match(lines[i])
161 match = pat.match(lines[i])
162 if match:
162 if match:
163 # if it's at toplevel, it's already the best one
163 # if it's at toplevel, it's already the best one
164 if lines[i][0] == 'c':
164 if lines[i][0] == 'c':
165 return lines, i
165 return lines, i
166 # else add whitespace to candidate list
166 # else add whitespace to candidate list
167 candidates.append((match.group(1), i))
167 candidates.append((match.group(1), i))
168 if candidates:
168 if candidates:
169 # this will sort by whitespace, and by line number,
169 # this will sort by whitespace, and by line number,
170 # less whitespace first
170 # less whitespace first
171 candidates.sort()
171 candidates.sort()
172 return lines, candidates[0][1]
172 return lines, candidates[0][1]
173 else:
173 else:
174 raise IOError('could not find class definition')
174 raise IOError('could not find class definition')
175
175
176 if ismethod(object):
176 if ismethod(object):
177 object = object.im_func
177 object = object.im_func
178 if isfunction(object):
178 if isfunction(object):
179 object = object.func_code
179 object = object.func_code
180 if istraceback(object):
180 if istraceback(object):
181 object = object.tb_frame
181 object = object.tb_frame
182 if isframe(object):
182 if isframe(object):
183 object = object.f_code
183 object = object.f_code
184 if iscode(object):
184 if iscode(object):
185 if not hasattr(object, 'co_firstlineno'):
185 if not hasattr(object, 'co_firstlineno'):
186 raise IOError('could not find function definition')
186 raise IOError('could not find function definition')
187 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
187 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
188 pmatch = pat.match
188 pmatch = pat.match
189 # fperez - fix: sometimes, co_firstlineno can give a number larger than
189 # fperez - fix: sometimes, co_firstlineno can give a number larger than
190 # the length of lines, which causes an error. Safeguard against that.
190 # the length of lines, which causes an error. Safeguard against that.
191 lnum = min(object.co_firstlineno,len(lines))-1
191 lnum = min(object.co_firstlineno,len(lines))-1
192 while lnum > 0:
192 while lnum > 0:
193 if pmatch(lines[lnum]): break
193 if pmatch(lines[lnum]): break
194 lnum -= 1
194 lnum -= 1
195
195
196 return lines, lnum
196 return lines, lnum
197 raise IOError('could not find code object')
197 raise IOError('could not find code object')
198
198
199 # Monkeypatch inspect to apply our bugfix. This code only works with py25
199 # Monkeypatch inspect to apply our bugfix. This code only works with py25
200 if sys.version_info[:2] >= (2,5):
200 if sys.version_info[:2] >= (2,5):
201 inspect.findsource = findsource
201 inspect.findsource = findsource
202
202
203 def fix_frame_records_filenames(records):
203 def fix_frame_records_filenames(records):
204 """Try to fix the filenames in each record from inspect.getinnerframes().
204 """Try to fix the filenames in each record from inspect.getinnerframes().
205
205
206 Particularly, modules loaded from within zip files have useless filenames
206 Particularly, modules loaded from within zip files have useless filenames
207 attached to their code object, and inspect.getinnerframes() just uses it.
207 attached to their code object, and inspect.getinnerframes() just uses it.
208 """
208 """
209 fixed_records = []
209 fixed_records = []
210 for frame, filename, line_no, func_name, lines, index in records:
210 for frame, filename, line_no, func_name, lines, index in records:
211 # Look inside the frame's globals dictionary for __file__, which should
211 # Look inside the frame's globals dictionary for __file__, which should
212 # be better.
212 # be better.
213 better_fn = frame.f_globals.get('__file__', None)
213 better_fn = frame.f_globals.get('__file__', None)
214 if isinstance(better_fn, str):
214 if isinstance(better_fn, str):
215 # Check the type just in case someone did something weird with
215 # Check the type just in case someone did something weird with
216 # __file__. It might also be None if the error occurred during
216 # __file__. It might also be None if the error occurred during
217 # import.
217 # import.
218 filename = better_fn
218 filename = better_fn
219 fixed_records.append((frame, filename, line_no, func_name, lines, index))
219 fixed_records.append((frame, filename, line_no, func_name, lines, index))
220 return fixed_records
220 return fixed_records
221
221
222
222
223 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
223 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
224 import linecache
224 import linecache
225 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
225 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
226
226
227 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
227 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
228
228
229 # If the error is at the console, don't build any context, since it would
229 # If the error is at the console, don't build any context, since it would
230 # otherwise produce 5 blank lines printed out (there is no file at the
230 # otherwise produce 5 blank lines printed out (there is no file at the
231 # console)
231 # console)
232 rec_check = records[tb_offset:]
232 rec_check = records[tb_offset:]
233 try:
233 try:
234 rname = rec_check[0][1]
234 rname = rec_check[0][1]
235 if rname == '<ipython console>' or rname.endswith('<string>'):
235 if rname == '<ipython console>' or rname.endswith('<string>'):
236 return rec_check
236 return rec_check
237 except IndexError:
237 except IndexError:
238 pass
238 pass
239
239
240 aux = traceback.extract_tb(etb)
240 aux = traceback.extract_tb(etb)
241 assert len(records) == len(aux)
241 assert len(records) == len(aux)
242 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
242 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
243 maybeStart = lnum-1 - context//2
243 maybeStart = lnum-1 - context//2
244 start = max(maybeStart, 0)
244 start = max(maybeStart, 0)
245 end = start + context
245 end = start + context
246 lines = linecache.getlines(file)[start:end]
246 lines = linecache.getlines(file)[start:end]
247 # pad with empty lines if necessary
247 # pad with empty lines if necessary
248 if maybeStart < 0:
248 if maybeStart < 0:
249 lines = (['\n'] * -maybeStart) + lines
249 lines = (['\n'] * -maybeStart) + lines
250 if len(lines) < context:
250 if len(lines) < context:
251 lines += ['\n'] * (context - len(lines))
251 lines += ['\n'] * (context - len(lines))
252 buf = list(records[i])
252 buf = list(records[i])
253 buf[LNUM_POS] = lnum
253 buf[LNUM_POS] = lnum
254 buf[INDEX_POS] = lnum - 1 - start
254 buf[INDEX_POS] = lnum - 1 - start
255 buf[LINES_POS] = lines
255 buf[LINES_POS] = lines
256 records[i] = tuple(buf)
256 records[i] = tuple(buf)
257 return records[tb_offset:]
257 return records[tb_offset:]
258
258
259 # Helper function -- largely belongs to VerboseTB, but we need the same
259 # Helper function -- largely belongs to VerboseTB, but we need the same
260 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
260 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
261 # can be recognized properly by ipython.el's py-traceback-line-re
261 # can be recognized properly by ipython.el's py-traceback-line-re
262 # (SyntaxErrors have to be treated specially because they have no traceback)
262 # (SyntaxErrors have to be treated specially because they have no traceback)
263
263
264 _parser = PyColorize.Parser()
264 _parser = PyColorize.Parser()
265
265
266 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
266 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
267 numbers_width = INDENT_SIZE - 1
267 numbers_width = INDENT_SIZE - 1
268 res = []
268 res = []
269 i = lnum - index
269 i = lnum - index
270
270
271 # This lets us get fully syntax-highlighted tracebacks.
271 # This lets us get fully syntax-highlighted tracebacks.
272 if scheme is None:
272 if scheme is None:
273 ipinst = ipapi.get()
273 ipinst = ipapi.get()
274 if ipinst is not None:
274 if ipinst is not None:
275 scheme = ipinst.colors
275 scheme = ipinst.colors
276 else:
276 else:
277 scheme = DEFAULT_SCHEME
277 scheme = DEFAULT_SCHEME
278
278
279 _line_format = _parser.format2
279 _line_format = _parser.format2
280
280
281 for line in lines:
281 for line in lines:
282 new_line, err = _line_format(line,'str',scheme)
282 new_line, err = _line_format(line,'str',scheme)
283 if not err: line = new_line
283 if not err: line = new_line
284
284
285 if i == lnum:
285 if i == lnum:
286 # This is the line with the error
286 # This is the line with the error
287 pad = numbers_width - len(str(i))
287 pad = numbers_width - len(str(i))
288 if pad >= 3:
288 if pad >= 3:
289 marker = '-'*(pad-3) + '-> '
289 marker = '-'*(pad-3) + '-> '
290 elif pad == 2:
290 elif pad == 2:
291 marker = '> '
291 marker = '> '
292 elif pad == 1:
292 elif pad == 1:
293 marker = '>'
293 marker = '>'
294 else:
294 else:
295 marker = ''
295 marker = ''
296 num = marker + str(i)
296 num = marker + str(i)
297 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
297 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
298 Colors.line, line, Colors.Normal)
298 Colors.line, line, Colors.Normal)
299 else:
299 else:
300 num = '%*s' % (numbers_width,i)
300 num = '%*s' % (numbers_width,i)
301 line = '%s%s%s %s' %(Colors.lineno, num,
301 line = '%s%s%s %s' %(Colors.lineno, num,
302 Colors.Normal, line)
302 Colors.Normal, line)
303
303
304 res.append(line)
304 res.append(line)
305 if lvals and i == lnum:
305 if lvals and i == lnum:
306 res.append(lvals + '\n')
306 res.append(lvals + '\n')
307 i = i + 1
307 i = i + 1
308 return res
308 return res
309
309
310
310
311 #---------------------------------------------------------------------------
311 #---------------------------------------------------------------------------
312 # Module classes
312 # Module classes
313 class TBTools:
313 class TBTools:
314 """Basic tools used by all traceback printer classes."""
314 """Basic tools used by all traceback printer classes."""
315
315
316 # This attribute us used in globalipapp.py to have stdout used for
316 # This attribute us used in globalipapp.py to have stdout used for
317 # writting exceptions. This is needed so nose can trap them. This attribute
317 # writting exceptions. This is needed so nose can trap them. This attribute
318 # should be None (the default, which will use IPython.utils.io.Term) or
318 # should be None (the default, which will use IPython.utils.io.Term) or
319 # the string 'stdout' which will cause the override to sys.stdout.
319 # the string 'stdout' which will cause the override to sys.stdout.
320 out_stream = None
320 out_stream = None
321
321
322 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
322 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
323 # Whether to call the interactive pdb debugger after printing
323 # Whether to call the interactive pdb debugger after printing
324 # tracebacks or not
324 # tracebacks or not
325 self.call_pdb = call_pdb
325 self.call_pdb = call_pdb
326
326
327 # Create color table
327 # Create color table
328 self.color_scheme_table = exception_colors()
328 self.color_scheme_table = exception_colors()
329
329
330 self.set_colors(color_scheme)
330 self.set_colors(color_scheme)
331 self.old_scheme = color_scheme # save initial value for toggles
331 self.old_scheme = color_scheme # save initial value for toggles
332
332
333 if call_pdb:
333 if call_pdb:
334 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
334 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
335 else:
335 else:
336 self.pdb = None
336 self.pdb = None
337
337
338 def set_colors(self,*args,**kw):
338 def set_colors(self,*args,**kw):
339 """Shorthand access to the color table scheme selector method."""
339 """Shorthand access to the color table scheme selector method."""
340
340
341 # Set own color table
341 # Set own color table
342 self.color_scheme_table.set_active_scheme(*args,**kw)
342 self.color_scheme_table.set_active_scheme(*args,**kw)
343 # for convenience, set Colors to the active scheme
343 # for convenience, set Colors to the active scheme
344 self.Colors = self.color_scheme_table.active_colors
344 self.Colors = self.color_scheme_table.active_colors
345 # Also set colors of debugger
345 # Also set colors of debugger
346 if hasattr(self,'pdb') and self.pdb is not None:
346 if hasattr(self,'pdb') and self.pdb is not None:
347 self.pdb.set_colors(*args,**kw)
347 self.pdb.set_colors(*args,**kw)
348
348
349 def color_toggle(self):
349 def color_toggle(self):
350 """Toggle between the currently active color scheme and NoColor."""
350 """Toggle between the currently active color scheme and NoColor."""
351
351
352 if self.color_scheme_table.active_scheme_name == 'NoColor':
352 if self.color_scheme_table.active_scheme_name == 'NoColor':
353 self.color_scheme_table.set_active_scheme(self.old_scheme)
353 self.color_scheme_table.set_active_scheme(self.old_scheme)
354 self.Colors = self.color_scheme_table.active_colors
354 self.Colors = self.color_scheme_table.active_colors
355 else:
355 else:
356 self.old_scheme = self.color_scheme_table.active_scheme_name
356 self.old_scheme = self.color_scheme_table.active_scheme_name
357 self.color_scheme_table.set_active_scheme('NoColor')
357 self.color_scheme_table.set_active_scheme('NoColor')
358 self.Colors = self.color_scheme_table.active_colors
358 self.Colors = self.color_scheme_table.active_colors
359
359
360 #---------------------------------------------------------------------------
360 #---------------------------------------------------------------------------
361 class ListTB(TBTools):
361 class ListTB(TBTools):
362 """Print traceback information from a traceback list, with optional color.
362 """Print traceback information from a traceback list, with optional color.
363
363
364 Calling: requires 3 arguments:
364 Calling: requires 3 arguments:
365 (etype, evalue, elist)
365 (etype, evalue, elist)
366 as would be obtained by:
366 as would be obtained by:
367 etype, evalue, tb = sys.exc_info()
367 etype, evalue, tb = sys.exc_info()
368 if tb:
368 if tb:
369 elist = traceback.extract_tb(tb)
369 elist = traceback.extract_tb(tb)
370 else:
370 else:
371 elist = None
371 elist = None
372
372
373 It can thus be used by programs which need to process the traceback before
373 It can thus be used by programs which need to process the traceback before
374 printing (such as console replacements based on the code module from the
374 printing (such as console replacements based on the code module from the
375 standard library).
375 standard library).
376
376
377 Because they are meant to be called without a full traceback (only a
377 Because they are meant to be called without a full traceback (only a
378 list), instances of this class can't call the interactive pdb debugger."""
378 list), instances of this class can't call the interactive pdb debugger."""
379
379
380 def __init__(self,color_scheme = 'NoColor'):
380 def __init__(self,color_scheme = 'NoColor'):
381 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
381 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
382
382
383 def __call__(self, etype, value, elist):
383 def __call__(self, etype, value, elist):
384 IPython.utils.io.Term.cout.flush()
384 IPython.utils.io.Term.cout.flush()
385 IPython.utils.io.Term.cerr.write(self.text(etype,value,elist))
385 IPython.utils.io.Term.cerr.write(self.text(etype,value,elist))
386 IPython.utils.io.Term.cerr.write('\n')
386 IPython.utils.io.Term.cerr.write('\n')
387
387
388 def structured_traceback(self, etype, value, elist, context=5):
388 def structured_traceback(self, etype, value, elist, context=5):
389 """Return a color formatted string with the traceback info.
389 """Return a color formatted string with the traceback info.
390
390
391 Parameters
391 Parameters
392 ----------
392 ----------
393 etype : exception type
393 etype : exception type
394 Type of the exception raised.
394 Type of the exception raised.
395
395
396 value : object
396 value : object
397 Data stored in the exception
397 Data stored in the exception
398
398
399 elist : list
399 elist : list
400 List of frames, see class docstring for details.
400 List of frames, see class docstring for details.
401
401
402 Returns
402 Returns
403 -------
403 -------
404 String with formatted exception.
404 String with formatted exception.
405 """
405 """
406
406
407 Colors = self.Colors
407 Colors = self.Colors
408 out_string = []
408 out_string = []
409 if elist:
409 if elist:
410 out_string.append('Traceback %s(most recent call last)%s:' %
410 out_string.append('Traceback %s(most recent call last)%s:' %
411 (Colors.normalEm, Colors.Normal) + '\n')
411 (Colors.normalEm, Colors.Normal) + '\n')
412 out_string.extend(self._format_list(elist))
412 out_string.extend(self._format_list(elist))
413 lines = self._format_exception_only(etype, value)
413 lines = self._format_exception_only(etype, value)
414 for line in lines[:-1]:
414 for line in lines[:-1]:
415 out_string.append(" "+line)
415 out_string.append(" "+line)
416 out_string.append(lines[-1])
416 out_string.append(lines[-1])
417 return out_string
417 return out_string
418
418
419 def text(self, etype, value, elist, context=5):
419 def text(self, etype, value, elist, context=5):
420 out_string = ListTB.structured_traceback(
420 out_string = ListTB.structured_traceback(
421 self, etype, value, elist, context
421 self, etype, value, elist, context
422 )
422 )
423 return ''.join(out_string)
423 return ''.join(out_string)
424
424
425 def _format_list(self, extracted_list):
425 def _format_list(self, extracted_list):
426 """Format a list of traceback entry tuples for printing.
426 """Format a list of traceback entry tuples for printing.
427
427
428 Given a list of tuples as returned by extract_tb() or
428 Given a list of tuples as returned by extract_tb() or
429 extract_stack(), return a list of strings ready for printing.
429 extract_stack(), return a list of strings ready for printing.
430 Each string in the resulting list corresponds to the item with the
430 Each string in the resulting list corresponds to the item with the
431 same index in the argument list. Each string ends in a newline;
431 same index in the argument list. Each string ends in a newline;
432 the strings may contain internal newlines as well, for those items
432 the strings may contain internal newlines as well, for those items
433 whose source text line is not None.
433 whose source text line is not None.
434
434
435 Lifted almost verbatim from traceback.py
435 Lifted almost verbatim from traceback.py
436 """
436 """
437
437
438 Colors = self.Colors
438 Colors = self.Colors
439 list = []
439 list = []
440 for filename, lineno, name, line in extracted_list[:-1]:
440 for filename, lineno, name, line in extracted_list[:-1]:
441 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
441 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
442 (Colors.filename, filename, Colors.Normal,
442 (Colors.filename, filename, Colors.Normal,
443 Colors.lineno, lineno, Colors.Normal,
443 Colors.lineno, lineno, Colors.Normal,
444 Colors.name, name, Colors.Normal)
444 Colors.name, name, Colors.Normal)
445 if line:
445 if line:
446 item = item + ' %s\n' % line.strip()
446 item = item + ' %s\n' % line.strip()
447 list.append(item)
447 list.append(item)
448 # Emphasize the last entry
448 # Emphasize the last entry
449 filename, lineno, name, line = extracted_list[-1]
449 filename, lineno, name, line = extracted_list[-1]
450 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
450 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
451 (Colors.normalEm,
451 (Colors.normalEm,
452 Colors.filenameEm, filename, Colors.normalEm,
452 Colors.filenameEm, filename, Colors.normalEm,
453 Colors.linenoEm, lineno, Colors.normalEm,
453 Colors.linenoEm, lineno, Colors.normalEm,
454 Colors.nameEm, name, Colors.normalEm,
454 Colors.nameEm, name, Colors.normalEm,
455 Colors.Normal)
455 Colors.Normal)
456 if line:
456 if line:
457 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
457 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
458 Colors.Normal)
458 Colors.Normal)
459 list.append(item)
459 list.append(item)
460 return list
460 return list
461
461
462 def _format_exception_only(self, etype, value):
462 def _format_exception_only(self, etype, value):
463 """Format the exception part of a traceback.
463 """Format the exception part of a traceback.
464
464
465 The arguments are the exception type and value such as given by
465 The arguments are the exception type and value such as given by
466 sys.exc_info()[:2]. The return value is a list of strings, each ending
466 sys.exc_info()[:2]. The return value is a list of strings, each ending
467 in a newline. Normally, the list contains a single string; however,
467 in a newline. Normally, the list contains a single string; however,
468 for SyntaxError exceptions, it contains several lines that (when
468 for SyntaxError exceptions, it contains several lines that (when
469 printed) display detailed information about where the syntax error
469 printed) display detailed information about where the syntax error
470 occurred. The message indicating which exception occurred is the
470 occurred. The message indicating which exception occurred is the
471 always last string in the list.
471 always last string in the list.
472
472
473 Also lifted nearly verbatim from traceback.py
473 Also lifted nearly verbatim from traceback.py
474 """
474 """
475
475
476 have_filedata = False
476 have_filedata = False
477 Colors = self.Colors
477 Colors = self.Colors
478 list = []
478 list = []
479 try:
479 try:
480 stype = Colors.excName + etype.__name__ + Colors.Normal
480 stype = Colors.excName + etype.__name__ + Colors.Normal
481 except AttributeError:
481 except AttributeError:
482 stype = etype # String exceptions don't get special coloring
482 stype = etype # String exceptions don't get special coloring
483 if value is None:
483 if value is None:
484 list.append( str(stype) + '\n')
484 list.append( str(stype) + '\n')
485 else:
485 else:
486 if etype is SyntaxError:
486 if etype is SyntaxError:
487 try:
487 try:
488 msg, (filename, lineno, offset, line) = value
488 msg, (filename, lineno, offset, line) = value
489 except:
489 except:
490 have_filedata = False
490 have_filedata = False
491 else:
491 else:
492 have_filedata = True
492 have_filedata = True
493 #print 'filename is',filename # dbg
493 #print 'filename is',filename # dbg
494 if not filename: filename = "<string>"
494 if not filename: filename = "<string>"
495 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
495 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
496 (Colors.normalEm,
496 (Colors.normalEm,
497 Colors.filenameEm, filename, Colors.normalEm,
497 Colors.filenameEm, filename, Colors.normalEm,
498 Colors.linenoEm, lineno, Colors.Normal ))
498 Colors.linenoEm, lineno, Colors.Normal ))
499 if line is not None:
499 if line is not None:
500 i = 0
500 i = 0
501 while i < len(line) and line[i].isspace():
501 while i < len(line) and line[i].isspace():
502 i = i+1
502 i = i+1
503 list.append('%s %s%s\n' % (Colors.line,
503 list.append('%s %s%s\n' % (Colors.line,
504 line.strip(),
504 line.strip(),
505 Colors.Normal))
505 Colors.Normal))
506 if offset is not None:
506 if offset is not None:
507 s = ' '
507 s = ' '
508 for c in line[i:offset-1]:
508 for c in line[i:offset-1]:
509 if c.isspace():
509 if c.isspace():
510 s = s + c
510 s = s + c
511 else:
511 else:
512 s = s + ' '
512 s = s + ' '
513 list.append('%s%s^%s\n' % (Colors.caret, s,
513 list.append('%s%s^%s\n' % (Colors.caret, s,
514 Colors.Normal) )
514 Colors.Normal) )
515 value = msg
515 value = msg
516 s = self._some_str(value)
516 s = self._some_str(value)
517 if s:
517 if s:
518 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
518 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
519 Colors.Normal, s))
519 Colors.Normal, s))
520 else:
520 else:
521 list.append('%s\n' % str(stype))
521 list.append('%s\n' % str(stype))
522
522
523 # sync with user hooks
523 # sync with user hooks
524 if have_filedata:
524 if have_filedata:
525 ipinst = ipapi.get()
525 ipinst = ipapi.get()
526 if ipinst is not None:
526 if ipinst is not None:
527 ipinst.hooks.synchronize_with_editor(filename, lineno, 0)
527 ipinst.hooks.synchronize_with_editor(filename, lineno, 0)
528
528
529 return list
529 return list
530
530
531 def show_exception_only(self, etype, value):
531 def show_exception_only(self, etype, value):
532 """Only print the exception type and message, without a traceback.
532 """Only print the exception type and message, without a traceback.
533
533
534 Parameters
534 Parameters
535 ----------
535 ----------
536 etype : exception type
536 etype : exception type
537 value : exception value
537 value : exception value
538 """
538 """
539 # This method needs to use __call__ from *this* class, not the one from
539 # This method needs to use __call__ from *this* class, not the one from
540 # a subclass whose signature or behavior may be different
540 # a subclass whose signature or behavior may be different
541 if self.out_stream == 'stdout':
541 if self.out_stream == 'stdout':
542 ostream = sys.stdout
542 ostream = sys.stdout
543 else:
543 else:
544 ostream = IPython.utils.io.Term.cerr
544 ostream = IPython.utils.io.Term.cerr
545 ostream.flush()
545 ostream.flush()
546 ostream.write(ListTB.text(self, etype, value, []))
546 ostream.write(ListTB.text(self, etype, value, []))
547 ostream.flush()
547 ostream.flush()
548
548
549 def _some_str(self, value):
549 def _some_str(self, value):
550 # Lifted from traceback.py
550 # Lifted from traceback.py
551 try:
551 try:
552 return str(value)
552 return str(value)
553 except:
553 except:
554 return '<unprintable %s object>' % type(value).__name__
554 return '<unprintable %s object>' % type(value).__name__
555
555
556 #----------------------------------------------------------------------------
556 #----------------------------------------------------------------------------
557 class VerboseTB(TBTools):
557 class VerboseTB(TBTools):
558 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
558 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
559 of HTML. Requires inspect and pydoc. Crazy, man.
559 of HTML. Requires inspect and pydoc. Crazy, man.
560
560
561 Modified version which optionally strips the topmost entries from the
561 Modified version which optionally strips the topmost entries from the
562 traceback, to be used with alternate interpreters (because their own code
562 traceback, to be used with alternate interpreters (because their own code
563 would appear in the traceback)."""
563 would appear in the traceback)."""
564
564
565 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
565 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
566 call_pdb = 0, include_vars=1):
566 call_pdb = 0, include_vars=1):
567 """Specify traceback offset, headers and color scheme.
567 """Specify traceback offset, headers and color scheme.
568
568
569 Define how many frames to drop from the tracebacks. Calling it with
569 Define how many frames to drop from the tracebacks. Calling it with
570 tb_offset=1 allows use of this handler in interpreters which will have
570 tb_offset=1 allows use of this handler in interpreters which will have
571 their own code at the top of the traceback (VerboseTB will first
571 their own code at the top of the traceback (VerboseTB will first
572 remove that frame before printing the traceback info)."""
572 remove that frame before printing the traceback info)."""
573 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
573 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
574 self.tb_offset = tb_offset
574 self.tb_offset = tb_offset
575 self.long_header = long_header
575 self.long_header = long_header
576 self.include_vars = include_vars
576 self.include_vars = include_vars
577
577
578 def structured_traceback(self, etype, evalue, etb, context=5):
578 def structured_traceback(self, etype, evalue, etb, context=5):
579 """Return a nice text document describing the traceback."""
579 """Return a nice text document describing the traceback."""
580
580
581 # some locals
581 # some locals
582 try:
582 try:
583 etype = etype.__name__
583 etype = etype.__name__
584 except AttributeError:
584 except AttributeError:
585 pass
585 pass
586 Colors = self.Colors # just a shorthand + quicker name lookup
586 Colors = self.Colors # just a shorthand + quicker name lookup
587 ColorsNormal = Colors.Normal # used a lot
587 ColorsNormal = Colors.Normal # used a lot
588 col_scheme = self.color_scheme_table.active_scheme_name
588 col_scheme = self.color_scheme_table.active_scheme_name
589 indent = ' '*INDENT_SIZE
589 indent = ' '*INDENT_SIZE
590 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
590 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
591 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
591 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
592 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
592 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
593
593
594 # some internal-use functions
594 # some internal-use functions
595 def text_repr(value):
595 def text_repr(value):
596 """Hopefully pretty robust repr equivalent."""
596 """Hopefully pretty robust repr equivalent."""
597 # this is pretty horrible but should always return *something*
597 # this is pretty horrible but should always return *something*
598 try:
598 try:
599 return pydoc.text.repr(value)
599 return pydoc.text.repr(value)
600 except KeyboardInterrupt:
600 except KeyboardInterrupt:
601 raise
601 raise
602 except:
602 except:
603 try:
603 try:
604 return repr(value)
604 return repr(value)
605 except KeyboardInterrupt:
605 except KeyboardInterrupt:
606 raise
606 raise
607 except:
607 except:
608 try:
608 try:
609 # all still in an except block so we catch
609 # all still in an except block so we catch
610 # getattr raising
610 # getattr raising
611 name = getattr(value, '__name__', None)
611 name = getattr(value, '__name__', None)
612 if name:
612 if name:
613 # ick, recursion
613 # ick, recursion
614 return text_repr(name)
614 return text_repr(name)
615 klass = getattr(value, '__class__', None)
615 klass = getattr(value, '__class__', None)
616 if klass:
616 if klass:
617 return '%s instance' % text_repr(klass)
617 return '%s instance' % text_repr(klass)
618 except KeyboardInterrupt:
618 except KeyboardInterrupt:
619 raise
619 raise
620 except:
620 except:
621 return 'UNRECOVERABLE REPR FAILURE'
621 return 'UNRECOVERABLE REPR FAILURE'
622 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
622 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
623 def nullrepr(value, repr=text_repr): return ''
623 def nullrepr(value, repr=text_repr): return ''
624
624
625 # meat of the code begins
625 # meat of the code begins
626 try:
626 try:
627 etype = etype.__name__
627 etype = etype.__name__
628 except AttributeError:
628 except AttributeError:
629 pass
629 pass
630
630
631 if self.long_header:
631 if self.long_header:
632 # Header with the exception type, python version, and date
632 # Header with the exception type, python version, and date
633 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
633 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
634 date = time.ctime(time.time())
634 date = time.ctime(time.time())
635
635
636 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
636 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
637 exc, ' '*(75-len(str(etype))-len(pyver)),
637 exc, ' '*(75-len(str(etype))-len(pyver)),
638 pyver, string.rjust(date, 75) )
638 pyver, string.rjust(date, 75) )
639 head += "\nA problem occured executing Python code. Here is the sequence of function"\
639 head += "\nA problem occured executing Python code. Here is the sequence of function"\
640 "\ncalls leading up to the error, with the most recent (innermost) call last."
640 "\ncalls leading up to the error, with the most recent (innermost) call last."
641 else:
641 else:
642 # Simplified header
642 # Simplified header
643 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
643 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
644 string.rjust('Traceback (most recent call last)',
644 string.rjust('Traceback (most recent call last)',
645 75 - len(str(etype)) ) )
645 75 - len(str(etype)) ) )
646 frames = []
646 frames = []
647 # Flush cache before calling inspect. This helps alleviate some of the
647 # Flush cache before calling inspect. This helps alleviate some of the
648 # problems with python 2.3's inspect.py.
648 # problems with python 2.3's inspect.py.
649 linecache.checkcache()
649 linecache.checkcache()
650 # Drop topmost frames if requested
650 # Drop topmost frames if requested
651 try:
651 try:
652 # Try the default getinnerframes and Alex's: Alex's fixes some
652 # Try the default getinnerframes and Alex's: Alex's fixes some
653 # problems, but it generates empty tracebacks for console errors
653 # problems, but it generates empty tracebacks for console errors
654 # (5 blanks lines) where none should be returned.
654 # (5 blanks lines) where none should be returned.
655 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
655 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
656 #print 'python records:', records # dbg
656 #print 'python records:', records # dbg
657 records = _fixed_getinnerframes(etb, context,self.tb_offset)
657 records = _fixed_getinnerframes(etb, context,self.tb_offset)
658 #print 'alex records:', records # dbg
658 #print 'alex records:', records # dbg
659 except:
659 except:
660
660
661 # FIXME: I've been getting many crash reports from python 2.3
661 # FIXME: I've been getting many crash reports from python 2.3
662 # users, traceable to inspect.py. If I can find a small test-case
662 # users, traceable to inspect.py. If I can find a small test-case
663 # to reproduce this, I should either write a better workaround or
663 # to reproduce this, I should either write a better workaround or
664 # file a bug report against inspect (if that's the real problem).
664 # file a bug report against inspect (if that's the real problem).
665 # So far, I haven't been able to find an isolated example to
665 # So far, I haven't been able to find an isolated example to
666 # reproduce the problem.
666 # reproduce the problem.
667 inspect_error()
667 inspect_error()
668 traceback.print_exc(file=IPython.utils.io.Term.cerr)
668 traceback.print_exc(file=IPython.utils.io.Term.cerr)
669 info('\nUnfortunately, your original traceback can not be constructed.\n')
669 info('\nUnfortunately, your original traceback can not be constructed.\n')
670 return ''
670 return ''
671
671
672 # build some color string templates outside these nested loops
672 # build some color string templates outside these nested loops
673 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
673 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
674 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
674 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
675 ColorsNormal)
675 ColorsNormal)
676 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
676 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
677 (Colors.vName, Colors.valEm, ColorsNormal)
677 (Colors.vName, Colors.valEm, ColorsNormal)
678 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
678 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
679 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
679 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
680 Colors.vName, ColorsNormal)
680 Colors.vName, ColorsNormal)
681 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
681 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
682 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
682 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
683 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
683 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
684 ColorsNormal)
684 ColorsNormal)
685
685
686 # now, loop over all records printing context and info
686 # now, loop over all records printing context and info
687 abspath = os.path.abspath
687 abspath = os.path.abspath
688 for frame, file, lnum, func, lines, index in records:
688 for frame, file, lnum, func, lines, index in records:
689 #print '*** record:',file,lnum,func,lines,index # dbg
689 #print '*** record:',file,lnum,func,lines,index # dbg
690 try:
690 try:
691 file = file and abspath(file) or '?'
691 file = file and abspath(file) or '?'
692 except OSError:
692 except OSError:
693 # if file is '<console>' or something not in the filesystem,
693 # if file is '<console>' or something not in the filesystem,
694 # the abspath call will throw an OSError. Just ignore it and
694 # the abspath call will throw an OSError. Just ignore it and
695 # keep the original file string.
695 # keep the original file string.
696 pass
696 pass
697 link = tpl_link % file
697 link = tpl_link % file
698 try:
698 try:
699 args, varargs, varkw, locals = inspect.getargvalues(frame)
699 args, varargs, varkw, locals = inspect.getargvalues(frame)
700 except:
700 except:
701 # This can happen due to a bug in python2.3. We should be
701 # This can happen due to a bug in python2.3. We should be
702 # able to remove this try/except when 2.4 becomes a
702 # able to remove this try/except when 2.4 becomes a
703 # requirement. Bug details at http://python.org/sf/1005466
703 # requirement. Bug details at http://python.org/sf/1005466
704 inspect_error()
704 inspect_error()
705 traceback.print_exc(file=IPython.utils.io.Term.cerr)
705 traceback.print_exc(file=IPython.utils.io.Term.cerr)
706 info("\nIPython's exception reporting continues...\n")
706 info("\nIPython's exception reporting continues...\n")
707
707
708 if func == '?':
708 if func == '?':
709 call = ''
709 call = ''
710 else:
710 else:
711 # Decide whether to include variable details or not
711 # Decide whether to include variable details or not
712 var_repr = self.include_vars and eqrepr or nullrepr
712 var_repr = self.include_vars and eqrepr or nullrepr
713 try:
713 try:
714 call = tpl_call % (func,inspect.formatargvalues(args,
714 call = tpl_call % (func,inspect.formatargvalues(args,
715 varargs, varkw,
715 varargs, varkw,
716 locals,formatvalue=var_repr))
716 locals,formatvalue=var_repr))
717 except KeyError:
717 except KeyError:
718 # Very odd crash from inspect.formatargvalues(). The
718 # Very odd crash from inspect.formatargvalues(). The
719 # scenario under which it appeared was a call to
719 # scenario under which it appeared was a call to
720 # view(array,scale) in NumTut.view.view(), where scale had
720 # view(array,scale) in NumTut.view.view(), where scale had
721 # been defined as a scalar (it should be a tuple). Somehow
721 # been defined as a scalar (it should be a tuple). Somehow
722 # inspect messes up resolving the argument list of view()
722 # inspect messes up resolving the argument list of view()
723 # and barfs out. At some point I should dig into this one
723 # and barfs out. At some point I should dig into this one
724 # and file a bug report about it.
724 # and file a bug report about it.
725 inspect_error()
725 inspect_error()
726 traceback.print_exc(file=IPython.utils.io.Term.cerr)
726 traceback.print_exc(file=IPython.utils.io.Term.cerr)
727 info("\nIPython's exception reporting continues...\n")
727 info("\nIPython's exception reporting continues...\n")
728 call = tpl_call_fail % func
728 call = tpl_call_fail % func
729
729
730 # Initialize a list of names on the current line, which the
730 # Initialize a list of names on the current line, which the
731 # tokenizer below will populate.
731 # tokenizer below will populate.
732 names = []
732 names = []
733
733
734 def tokeneater(token_type, token, start, end, line):
734 def tokeneater(token_type, token, start, end, line):
735 """Stateful tokeneater which builds dotted names.
735 """Stateful tokeneater which builds dotted names.
736
736
737 The list of names it appends to (from the enclosing scope) can
737 The list of names it appends to (from the enclosing scope) can
738 contain repeated composite names. This is unavoidable, since
738 contain repeated composite names. This is unavoidable, since
739 there is no way to disambguate partial dotted structures until
739 there is no way to disambguate partial dotted structures until
740 the full list is known. The caller is responsible for pruning
740 the full list is known. The caller is responsible for pruning
741 the final list of duplicates before using it."""
741 the final list of duplicates before using it."""
742
742
743 # build composite names
743 # build composite names
744 if token == '.':
744 if token == '.':
745 try:
745 try:
746 names[-1] += '.'
746 names[-1] += '.'
747 # store state so the next token is added for x.y.z names
747 # store state so the next token is added for x.y.z names
748 tokeneater.name_cont = True
748 tokeneater.name_cont = True
749 return
749 return
750 except IndexError:
750 except IndexError:
751 pass
751 pass
752 if token_type == tokenize.NAME and token not in keyword.kwlist:
752 if token_type == tokenize.NAME and token not in keyword.kwlist:
753 if tokeneater.name_cont:
753 if tokeneater.name_cont:
754 # Dotted names
754 # Dotted names
755 names[-1] += token
755 names[-1] += token
756 tokeneater.name_cont = False
756 tokeneater.name_cont = False
757 else:
757 else:
758 # Regular new names. We append everything, the caller
758 # Regular new names. We append everything, the caller
759 # will be responsible for pruning the list later. It's
759 # will be responsible for pruning the list later. It's
760 # very tricky to try to prune as we go, b/c composite
760 # very tricky to try to prune as we go, b/c composite
761 # names can fool us. The pruning at the end is easy
761 # names can fool us. The pruning at the end is easy
762 # to do (or the caller can print a list with repeated
762 # to do (or the caller can print a list with repeated
763 # names if so desired.
763 # names if so desired.
764 names.append(token)
764 names.append(token)
765 elif token_type == tokenize.NEWLINE:
765 elif token_type == tokenize.NEWLINE:
766 raise IndexError
766 raise IndexError
767 # we need to store a bit of state in the tokenizer to build
767 # we need to store a bit of state in the tokenizer to build
768 # dotted names
768 # dotted names
769 tokeneater.name_cont = False
769 tokeneater.name_cont = False
770
770
771 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
771 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
772 line = getline(file, lnum[0])
772 line = getline(file, lnum[0])
773 lnum[0] += 1
773 lnum[0] += 1
774 return line
774 return line
775
775
776 # Build the list of names on this line of code where the exception
776 # Build the list of names on this line of code where the exception
777 # occurred.
777 # occurred.
778 try:
778 try:
779 # This builds the names list in-place by capturing it from the
779 # This builds the names list in-place by capturing it from the
780 # enclosing scope.
780 # enclosing scope.
781 tokenize.tokenize(linereader, tokeneater)
781 tokenize.tokenize(linereader, tokeneater)
782 except IndexError:
782 except IndexError:
783 # signals exit of tokenizer
783 # signals exit of tokenizer
784 pass
784 pass
785 except tokenize.TokenError,msg:
785 except tokenize.TokenError,msg:
786 _m = ("An unexpected error occurred while tokenizing input\n"
786 _m = ("An unexpected error occurred while tokenizing input\n"
787 "The following traceback may be corrupted or invalid\n"
787 "The following traceback may be corrupted or invalid\n"
788 "The error message is: %s\n" % msg)
788 "The error message is: %s\n" % msg)
789 error(_m)
789 error(_m)
790
790
791 # prune names list of duplicates, but keep the right order
791 # prune names list of duplicates, but keep the right order
792 unique_names = uniq_stable(names)
792 unique_names = uniq_stable(names)
793
793
794 # Start loop over vars
794 # Start loop over vars
795 lvals = []
795 lvals = []
796 if self.include_vars:
796 if self.include_vars:
797 for name_full in unique_names:
797 for name_full in unique_names:
798 name_base = name_full.split('.',1)[0]
798 name_base = name_full.split('.',1)[0]
799 if name_base in frame.f_code.co_varnames:
799 if name_base in frame.f_code.co_varnames:
800 if locals.has_key(name_base):
800 if locals.has_key(name_base):
801 try:
801 try:
802 value = repr(eval(name_full,locals))
802 value = repr(eval(name_full,locals))
803 except:
803 except:
804 value = undefined
804 value = undefined
805 else:
805 else:
806 value = undefined
806 value = undefined
807 name = tpl_local_var % name_full
807 name = tpl_local_var % name_full
808 else:
808 else:
809 if frame.f_globals.has_key(name_base):
809 if frame.f_globals.has_key(name_base):
810 try:
810 try:
811 value = repr(eval(name_full,frame.f_globals))
811 value = repr(eval(name_full,frame.f_globals))
812 except:
812 except:
813 value = undefined
813 value = undefined
814 else:
814 else:
815 value = undefined
815 value = undefined
816 name = tpl_global_var % name_full
816 name = tpl_global_var % name_full
817 lvals.append(tpl_name_val % (name,value))
817 lvals.append(tpl_name_val % (name,value))
818 if lvals:
818 if lvals:
819 lvals = '%s%s' % (indent,em_normal.join(lvals))
819 lvals = '%s%s' % (indent,em_normal.join(lvals))
820 else:
820 else:
821 lvals = ''
821 lvals = ''
822
822
823 level = '%s %s\n' % (link,call)
823 level = '%s %s\n' % (link,call)
824
824
825 if index is None:
825 if index is None:
826 frames.append(level)
826 frames.append(level)
827 else:
827 else:
828 frames.append('%s%s' % (level,''.join(
828 frames.append('%s%s' % (level,''.join(
829 _format_traceback_lines(lnum,index,lines,Colors,lvals,
829 _format_traceback_lines(lnum,index,lines,Colors,lvals,
830 col_scheme))))
830 col_scheme))))
831
831
832 # Get (safely) a string form of the exception info
832 # Get (safely) a string form of the exception info
833 try:
833 try:
834 etype_str,evalue_str = map(str,(etype,evalue))
834 etype_str,evalue_str = map(str,(etype,evalue))
835 except:
835 except:
836 # User exception is improperly defined.
836 # User exception is improperly defined.
837 etype,evalue = str,sys.exc_info()[:2]
837 etype,evalue = str,sys.exc_info()[:2]
838 etype_str,evalue_str = map(str,(etype,evalue))
838 etype_str,evalue_str = map(str,(etype,evalue))
839 # ... and format it
839 # ... and format it
840 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
840 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
841 ColorsNormal, evalue_str)]
841 ColorsNormal, evalue_str)]
842 if type(evalue) is types.InstanceType:
842 if type(evalue) is types.InstanceType:
843 try:
843 try:
844 names = [w for w in dir(evalue) if isinstance(w, basestring)]
844 names = [w for w in dir(evalue) if isinstance(w, basestring)]
845 except:
845 except:
846 # Every now and then, an object with funny inernals blows up
846 # Every now and then, an object with funny inernals blows up
847 # when dir() is called on it. We do the best we can to report
847 # when dir() is called on it. We do the best we can to report
848 # the problem and continue
848 # the problem and continue
849 _m = '%sException reporting error (object with broken dir())%s:'
849 _m = '%sException reporting error (object with broken dir())%s:'
850 exception.append(_m % (Colors.excName,ColorsNormal))
850 exception.append(_m % (Colors.excName,ColorsNormal))
851 etype_str,evalue_str = map(str,sys.exc_info()[:2])
851 etype_str,evalue_str = map(str,sys.exc_info()[:2])
852 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
852 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
853 ColorsNormal, evalue_str))
853 ColorsNormal, evalue_str))
854 names = []
854 names = []
855 for name in names:
855 for name in names:
856 value = text_repr(getattr(evalue, name))
856 value = text_repr(getattr(evalue, name))
857 exception.append('\n%s%s = %s' % (indent, name, value))
857 exception.append('\n%s%s = %s' % (indent, name, value))
858
858
859 # vds: >>
859 # vds: >>
860 if records:
860 if records:
861 filepath, lnum = records[-1][1:3]
861 filepath, lnum = records[-1][1:3]
862 #print "file:", str(file), "linenb", str(lnum) # dbg
862 #print "file:", str(file), "linenb", str(lnum) # dbg
863 filepath = os.path.abspath(filepath)
863 filepath = os.path.abspath(filepath)
864 ipinst = ipapi.get()
864 ipinst = ipapi.get()
865 if ipinst is not None:
865 if ipinst is not None:
866 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
866 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
867 # vds: <<
867 # vds: <<
868
868
869 # return all our info assembled as a single string
869 # return all our info assembled as a single string
870 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
870 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
871 return [head] + frames + [''.join(exception[0])]
871 return [head] + frames + [''.join(exception[0])]
872
872
873 def text(self, etype, evalue, etb, context=5):
873 def text(self, etype, evalue, etb, context=5):
874 tb_list = VerboseTB.structured_traceback(
874 tb_list = VerboseTB.structured_traceback(
875 self, etype, evalue, etb, context
875 self, etype, evalue, etb, context
876 )
876 )
877 return '\n'.join(tb_list)
877 return '\n'.join(tb_list)
878
878
879 def debugger(self,force=False):
879 def debugger(self,force=False):
880 """Call up the pdb debugger if desired, always clean up the tb
880 """Call up the pdb debugger if desired, always clean up the tb
881 reference.
881 reference.
882
882
883 Keywords:
883 Keywords:
884
884
885 - force(False): by default, this routine checks the instance call_pdb
885 - force(False): by default, this routine checks the instance call_pdb
886 flag and does not actually invoke the debugger if the flag is false.
886 flag and does not actually invoke the debugger if the flag is false.
887 The 'force' option forces the debugger to activate even if the flag
887 The 'force' option forces the debugger to activate even if the flag
888 is false.
888 is false.
889
889
890 If the call_pdb flag is set, the pdb interactive debugger is
890 If the call_pdb flag is set, the pdb interactive debugger is
891 invoked. In all cases, the self.tb reference to the current traceback
891 invoked. In all cases, the self.tb reference to the current traceback
892 is deleted to prevent lingering references which hamper memory
892 is deleted to prevent lingering references which hamper memory
893 management.
893 management.
894
894
895 Note that each call to pdb() does an 'import readline', so if your app
895 Note that each call to pdb() does an 'import readline', so if your app
896 requires a special setup for the readline completers, you'll have to
896 requires a special setup for the readline completers, you'll have to
897 fix that by hand after invoking the exception handler."""
897 fix that by hand after invoking the exception handler."""
898
898
899 if force or self.call_pdb:
899 if force or self.call_pdb:
900 if self.pdb is None:
900 if self.pdb is None:
901 self.pdb = debugger.Pdb(
901 self.pdb = debugger.Pdb(
902 self.color_scheme_table.active_scheme_name)
902 self.color_scheme_table.active_scheme_name)
903 # the system displayhook may have changed, restore the original
903 # the system displayhook may have changed, restore the original
904 # for pdb
904 # for pdb
905 display_trap = DisplayTrap(None, sys.__displayhook__)
905 display_trap = DisplayTrap(hook=sys.__displayhook__)
906 with display_trap:
906 with display_trap:
907 self.pdb.reset()
907 self.pdb.reset()
908 # Find the right frame so we don't pop up inside ipython itself
908 # Find the right frame so we don't pop up inside ipython itself
909 if hasattr(self,'tb') and self.tb is not None:
909 if hasattr(self,'tb') and self.tb is not None:
910 etb = self.tb
910 etb = self.tb
911 else:
911 else:
912 etb = self.tb = sys.last_traceback
912 etb = self.tb = sys.last_traceback
913 while self.tb is not None and self.tb.tb_next is not None:
913 while self.tb is not None and self.tb.tb_next is not None:
914 self.tb = self.tb.tb_next
914 self.tb = self.tb.tb_next
915 if etb and etb.tb_next:
915 if etb and etb.tb_next:
916 etb = etb.tb_next
916 etb = etb.tb_next
917 self.pdb.botframe = etb.tb_frame
917 self.pdb.botframe = etb.tb_frame
918 self.pdb.interaction(self.tb.tb_frame, self.tb)
918 self.pdb.interaction(self.tb.tb_frame, self.tb)
919
919
920 if hasattr(self,'tb'):
920 if hasattr(self,'tb'):
921 del self.tb
921 del self.tb
922
922
923 def handler(self, info=None):
923 def handler(self, info=None):
924 (etype, evalue, etb) = info or sys.exc_info()
924 (etype, evalue, etb) = info or sys.exc_info()
925 self.tb = etb
925 self.tb = etb
926 IPython.utils.io.Term.cout.flush()
926 IPython.utils.io.Term.cout.flush()
927 IPython.utils.io.Term.cerr.write(self.text(etype, evalue, etb))
927 IPython.utils.io.Term.cerr.write(self.text(etype, evalue, etb))
928 IPython.utils.io.Term.cerr.write('\n')
928 IPython.utils.io.Term.cerr.write('\n')
929
929
930 # Changed so an instance can just be called as VerboseTB_inst() and print
930 # Changed so an instance can just be called as VerboseTB_inst() and print
931 # out the right info on its own.
931 # out the right info on its own.
932 def __call__(self, etype=None, evalue=None, etb=None):
932 def __call__(self, etype=None, evalue=None, etb=None):
933 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
933 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
934 if etb is None:
934 if etb is None:
935 self.handler()
935 self.handler()
936 else:
936 else:
937 self.handler((etype, evalue, etb))
937 self.handler((etype, evalue, etb))
938 try:
938 try:
939 self.debugger()
939 self.debugger()
940 except KeyboardInterrupt:
940 except KeyboardInterrupt:
941 print "\nKeyboardInterrupt"
941 print "\nKeyboardInterrupt"
942
942
943 #----------------------------------------------------------------------------
943 #----------------------------------------------------------------------------
944 class FormattedTB(VerboseTB,ListTB):
944 class FormattedTB(VerboseTB,ListTB):
945 """Subclass ListTB but allow calling with a traceback.
945 """Subclass ListTB but allow calling with a traceback.
946
946
947 It can thus be used as a sys.excepthook for Python > 2.1.
947 It can thus be used as a sys.excepthook for Python > 2.1.
948
948
949 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
949 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
950
950
951 Allows a tb_offset to be specified. This is useful for situations where
951 Allows a tb_offset to be specified. This is useful for situations where
952 one needs to remove a number of topmost frames from the traceback (such as
952 one needs to remove a number of topmost frames from the traceback (such as
953 occurs with python programs that themselves execute other python code,
953 occurs with python programs that themselves execute other python code,
954 like Python shells). """
954 like Python shells). """
955
955
956 def __init__(self, mode = 'Plain', color_scheme='Linux',
956 def __init__(self, mode = 'Plain', color_scheme='Linux',
957 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
957 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
958
958
959 # NEVER change the order of this list. Put new modes at the end:
959 # NEVER change the order of this list. Put new modes at the end:
960 self.valid_modes = ['Plain','Context','Verbose']
960 self.valid_modes = ['Plain','Context','Verbose']
961 self.verbose_modes = self.valid_modes[1:3]
961 self.verbose_modes = self.valid_modes[1:3]
962
962
963 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
963 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
964 call_pdb=call_pdb,include_vars=include_vars)
964 call_pdb=call_pdb,include_vars=include_vars)
965 self.set_mode(mode)
965 self.set_mode(mode)
966
966
967 def _extract_tb(self,tb):
967 def _extract_tb(self,tb):
968 if tb:
968 if tb:
969 return traceback.extract_tb(tb)
969 return traceback.extract_tb(tb)
970 else:
970 else:
971 return None
971 return None
972
972
973 def structured_traceback(self, etype, value, tb, context=5, mode=None):
973 def structured_traceback(self, etype, value, tb, context=5, mode=None):
974 mode = self.mode if mode is None else mode
974 mode = self.mode if mode is None else mode
975 if mode in self.verbose_modes:
975 if mode in self.verbose_modes:
976 # Verbose modes need a full traceback
976 # Verbose modes need a full traceback
977 return VerboseTB.structured_traceback(
977 return VerboseTB.structured_traceback(
978 self, etype, value, tb, context
978 self, etype, value, tb, context
979 )
979 )
980 else:
980 else:
981 # We must check the source cache because otherwise we can print
981 # We must check the source cache because otherwise we can print
982 # out-of-date source code.
982 # out-of-date source code.
983 linecache.checkcache()
983 linecache.checkcache()
984 # Now we can extract and format the exception
984 # Now we can extract and format the exception
985 elist = self._extract_tb(tb)
985 elist = self._extract_tb(tb)
986 if len(elist) > self.tb_offset:
986 if len(elist) > self.tb_offset:
987 del elist[:self.tb_offset]
987 del elist[:self.tb_offset]
988 return ListTB.structured_traceback(
988 return ListTB.structured_traceback(
989 self, etype, value, elist, context
989 self, etype, value, elist, context
990 )
990 )
991
991
992 def text(self, etype, value, tb, context=5, mode=None):
992 def text(self, etype, value, tb, context=5, mode=None):
993 """Return formatted traceback.
993 """Return formatted traceback.
994
994
995 If the optional mode parameter is given, it overrides the current
995 If the optional mode parameter is given, it overrides the current
996 mode."""
996 mode."""
997 tb_list = FormattedTB.structured_traceback(
997 tb_list = FormattedTB.structured_traceback(
998 self, etype, value, tb, context, mode
998 self, etype, value, tb, context, mode
999 )
999 )
1000 return '\n'.join(tb_list)
1000 return '\n'.join(tb_list)
1001
1001
1002 def set_mode(self,mode=None):
1002 def set_mode(self,mode=None):
1003 """Switch to the desired mode.
1003 """Switch to the desired mode.
1004
1004
1005 If mode is not specified, cycles through the available modes."""
1005 If mode is not specified, cycles through the available modes."""
1006
1006
1007 if not mode:
1007 if not mode:
1008 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1008 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1009 len(self.valid_modes)
1009 len(self.valid_modes)
1010 self.mode = self.valid_modes[new_idx]
1010 self.mode = self.valid_modes[new_idx]
1011 elif mode not in self.valid_modes:
1011 elif mode not in self.valid_modes:
1012 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1012 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1013 'Valid modes: '+str(self.valid_modes)
1013 'Valid modes: '+str(self.valid_modes)
1014 else:
1014 else:
1015 self.mode = mode
1015 self.mode = mode
1016 # include variable details only in 'Verbose' mode
1016 # include variable details only in 'Verbose' mode
1017 self.include_vars = (self.mode == self.valid_modes[2])
1017 self.include_vars = (self.mode == self.valid_modes[2])
1018
1018
1019 # some convenient shorcuts
1019 # some convenient shorcuts
1020 def plain(self):
1020 def plain(self):
1021 self.set_mode(self.valid_modes[0])
1021 self.set_mode(self.valid_modes[0])
1022
1022
1023 def context(self):
1023 def context(self):
1024 self.set_mode(self.valid_modes[1])
1024 self.set_mode(self.valid_modes[1])
1025
1025
1026 def verbose(self):
1026 def verbose(self):
1027 self.set_mode(self.valid_modes[2])
1027 self.set_mode(self.valid_modes[2])
1028
1028
1029 #----------------------------------------------------------------------------
1029 #----------------------------------------------------------------------------
1030 class AutoFormattedTB(FormattedTB):
1030 class AutoFormattedTB(FormattedTB):
1031 """A traceback printer which can be called on the fly.
1031 """A traceback printer which can be called on the fly.
1032
1032
1033 It will find out about exceptions by itself.
1033 It will find out about exceptions by itself.
1034
1034
1035 A brief example:
1035 A brief example:
1036
1036
1037 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1037 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1038 try:
1038 try:
1039 ...
1039 ...
1040 except:
1040 except:
1041 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1041 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1042 """
1042 """
1043
1043
1044 def __call__(self,etype=None,evalue=None,etb=None,
1044 def __call__(self,etype=None,evalue=None,etb=None,
1045 out=None,tb_offset=None):
1045 out=None,tb_offset=None):
1046 """Print out a formatted exception traceback.
1046 """Print out a formatted exception traceback.
1047
1047
1048 Optional arguments:
1048 Optional arguments:
1049 - out: an open file-like object to direct output to.
1049 - out: an open file-like object to direct output to.
1050
1050
1051 - tb_offset: the number of frames to skip over in the stack, on a
1051 - tb_offset: the number of frames to skip over in the stack, on a
1052 per-call basis (this overrides temporarily the instance's tb_offset
1052 per-call basis (this overrides temporarily the instance's tb_offset
1053 given at initialization time. """
1053 given at initialization time. """
1054
1054
1055 if out is None:
1055 if out is None:
1056 if self.out_stream == 'stdout':
1056 if self.out_stream == 'stdout':
1057 out = sys.stdout
1057 out = sys.stdout
1058 else:
1058 else:
1059 out = IPython.utils.io.Term.cerr
1059 out = IPython.utils.io.Term.cerr
1060 out.flush()
1060 out.flush()
1061 if tb_offset is not None:
1061 if tb_offset is not None:
1062 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1062 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1063 out.write(self.text(etype, evalue, etb))
1063 out.write(self.text(etype, evalue, etb))
1064 out.write('\n')
1064 out.write('\n')
1065 self.tb_offset = tb_offset
1065 self.tb_offset = tb_offset
1066 else:
1066 else:
1067 out.write(self.text(etype, evalue, etb))
1067 out.write(self.text(etype, evalue, etb))
1068 out.write('\n')
1068 out.write('\n')
1069 out.flush()
1069 out.flush()
1070 try:
1070 try:
1071 self.debugger()
1071 self.debugger()
1072 except KeyboardInterrupt:
1072 except KeyboardInterrupt:
1073 print "\nKeyboardInterrupt"
1073 print "\nKeyboardInterrupt"
1074
1074
1075 def structured_traceback(self, etype=None, value=None, tb=None,
1075 def structured_traceback(self, etype=None, value=None, tb=None,
1076 context=5, mode=None):
1076 context=5, mode=None):
1077 if etype is None:
1077 if etype is None:
1078 etype,value,tb = sys.exc_info()
1078 etype,value,tb = sys.exc_info()
1079 self.tb = tb
1079 self.tb = tb
1080 return FormattedTB.structured_traceback(
1080 return FormattedTB.structured_traceback(
1081 self, etype, value, tb, context, mode
1081 self, etype, value, tb, context, mode
1082 )
1082 )
1083
1083
1084 def text(self, etype=None, value=None, tb=None, context=5, mode=None):
1084 def text(self, etype=None, value=None, tb=None, context=5, mode=None):
1085 tb_list = AutoFormattedTB.structured_traceback(
1085 tb_list = AutoFormattedTB.structured_traceback(
1086 self, etype, value, tb, context, mode
1086 self, etype, value, tb, context, mode
1087 )
1087 )
1088 return '\n'.join(tb_list)
1088 return '\n'.join(tb_list)
1089
1089
1090 #---------------------------------------------------------------------------
1090 #---------------------------------------------------------------------------
1091
1091
1092 # A simple class to preserve Nathan's original functionality.
1092 # A simple class to preserve Nathan's original functionality.
1093 class ColorTB(FormattedTB):
1093 class ColorTB(FormattedTB):
1094 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1094 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1095 def __init__(self,color_scheme='Linux',call_pdb=0):
1095 def __init__(self,color_scheme='Linux',call_pdb=0):
1096 FormattedTB.__init__(self,color_scheme=color_scheme,
1096 FormattedTB.__init__(self,color_scheme=color_scheme,
1097 call_pdb=call_pdb)
1097 call_pdb=call_pdb)
1098
1098
1099
1099
1100 class SyntaxTB(ListTB):
1100 class SyntaxTB(ListTB):
1101 """Extension which holds some state: the last exception value"""
1101 """Extension which holds some state: the last exception value"""
1102
1102
1103 def __init__(self,color_scheme = 'NoColor'):
1103 def __init__(self,color_scheme = 'NoColor'):
1104 ListTB.__init__(self,color_scheme)
1104 ListTB.__init__(self,color_scheme)
1105 self.last_syntax_error = None
1105 self.last_syntax_error = None
1106
1106
1107 def __call__(self, etype, value, elist):
1107 def __call__(self, etype, value, elist):
1108 self.last_syntax_error = value
1108 self.last_syntax_error = value
1109 ListTB.__call__(self,etype,value,elist)
1109 ListTB.__call__(self,etype,value,elist)
1110
1110
1111 def clear_err_state(self):
1111 def clear_err_state(self):
1112 """Return the current error state and clear it"""
1112 """Return the current error state and clear it"""
1113 e = self.last_syntax_error
1113 e = self.last_syntax_error
1114 self.last_syntax_error = None
1114 self.last_syntax_error = None
1115 return e
1115 return e
1116
1116
1117 #----------------------------------------------------------------------------
1117 #----------------------------------------------------------------------------
1118 # module testing (minimal)
1118 # module testing (minimal)
1119 if __name__ == "__main__":
1119 if __name__ == "__main__":
1120 def spam(c, (d, e)):
1120 def spam(c, (d, e)):
1121 x = c + d
1121 x = c + d
1122 y = c * d
1122 y = c * d
1123 foo(x, y)
1123 foo(x, y)
1124
1124
1125 def foo(a, b, bar=1):
1125 def foo(a, b, bar=1):
1126 eggs(a, b + bar)
1126 eggs(a, b + bar)
1127
1127
1128 def eggs(f, g, z=globals()):
1128 def eggs(f, g, z=globals()):
1129 h = f + g
1129 h = f + g
1130 i = f - g
1130 i = f - g
1131 return h / i
1131 return h / i
1132
1132
1133 print ''
1133 print ''
1134 print '*** Before ***'
1134 print '*** Before ***'
1135 try:
1135 try:
1136 print spam(1, (2, 3))
1136 print spam(1, (2, 3))
1137 except:
1137 except:
1138 traceback.print_exc()
1138 traceback.print_exc()
1139 print ''
1139 print ''
1140
1140
1141 handler = ColorTB()
1141 handler = ColorTB()
1142 print '*** ColorTB ***'
1142 print '*** ColorTB ***'
1143 try:
1143 try:
1144 print spam(1, (2, 3))
1144 print spam(1, (2, 3))
1145 except:
1145 except:
1146 apply(handler, sys.exc_info() )
1146 apply(handler, sys.exc_info() )
1147 print ''
1147 print ''
1148
1148
1149 handler = VerboseTB()
1149 handler = VerboseTB()
1150 print '*** VerboseTB ***'
1150 print '*** VerboseTB ***'
1151 try:
1151 try:
1152 print spam(1, (2, 3))
1152 print spam(1, (2, 3))
1153 except:
1153 except:
1154 apply(handler, sys.exc_info() )
1154 apply(handler, sys.exc_info() )
1155 print ''
1155 print ''
1156
1156
General Comments 0
You need to be logged in to leave comments. Login now