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