##// END OF EJS Templates
Finish doc/build tools cleanup....
Fernando Perez -
Show More

The requested changes are too big and content was truncated. Show full diff

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