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