##// END OF EJS Templates
Use term width to determine header length
Vincent Woo -
Show More
@@ -1,1483 +1,1485 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41 .. note::
41 .. note::
42
42
43 The verbose mode print all variables in the stack, which means it can
43 The verbose mode print all variables in the stack, which means it can
44 potentially leak sensitive information like access keys, or unencryted
44 potentially leak sensitive information like access keys, or unencryted
45 password.
45 password.
46
46
47 Installation instructions for VerboseTB::
47 Installation instructions for VerboseTB::
48
48
49 import sys,ultratb
49 import sys,ultratb
50 sys.excepthook = ultratb.VerboseTB()
50 sys.excepthook = ultratb.VerboseTB()
51
51
52 Note: Much of the code in this module was lifted verbatim from the standard
52 Note: Much of the code in this module was lifted verbatim from the standard
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54
54
55 Color schemes
55 Color schemes
56 -------------
56 -------------
57
57
58 The colors are defined in the class TBTools through the use of the
58 The colors are defined in the class TBTools through the use of the
59 ColorSchemeTable class. Currently the following exist:
59 ColorSchemeTable class. Currently the following exist:
60
60
61 - NoColor: allows all of this module to be used in any terminal (the color
61 - NoColor: allows all of this module to be used in any terminal (the color
62 escapes are just dummy blank strings).
62 escapes are just dummy blank strings).
63
63
64 - Linux: is meant to look good in a terminal like the Linux console (black
64 - Linux: is meant to look good in a terminal like the Linux console (black
65 or very dark background).
65 or very dark background).
66
66
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 in light background terminals.
68 in light background terminals.
69
69
70 You can implement other color schemes easily, the syntax is fairly
70 You can implement other color schemes easily, the syntax is fairly
71 self-explanatory. Please send back new schemes you develop to the author for
71 self-explanatory. Please send back new schemes you develop to the author for
72 possible inclusion in future releases.
72 possible inclusion in future releases.
73
73
74 Inheritance diagram:
74 Inheritance diagram:
75
75
76 .. inheritance-diagram:: IPython.core.ultratb
76 .. inheritance-diagram:: IPython.core.ultratb
77 :parts: 3
77 :parts: 3
78 """
78 """
79
79
80 #*****************************************************************************
80 #*****************************************************************************
81 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
81 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
82 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
82 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
83 #
83 #
84 # Distributed under the terms of the BSD License. The full license is in
84 # Distributed under the terms of the BSD License. The full license is in
85 # the file COPYING, distributed as part of this software.
85 # the file COPYING, distributed as part of this software.
86 #*****************************************************************************
86 #*****************************************************************************
87
87
88 from __future__ import absolute_import
88 from __future__ import absolute_import
89 from __future__ import unicode_literals
89 from __future__ import unicode_literals
90 from __future__ import print_function
90 from __future__ import print_function
91
91
92 import dis
92 import dis
93 import inspect
93 import inspect
94 import keyword
94 import keyword
95 import linecache
95 import linecache
96 import os
96 import os
97 import pydoc
97 import pydoc
98 import re
98 import re
99 import sys
99 import sys
100 import time
100 import time
101 import tokenize
101 import tokenize
102 import traceback
102 import traceback
103 import types
103 import types
104
104
105 try: # Python 2
105 try: # Python 2
106 generate_tokens = tokenize.generate_tokens
106 generate_tokens = tokenize.generate_tokens
107 except AttributeError: # Python 3
107 except AttributeError: # Python 3
108 generate_tokens = tokenize.tokenize
108 generate_tokens = tokenize.tokenize
109
109
110 # For purposes of monkeypatching inspect to fix a bug in it.
110 # For purposes of monkeypatching inspect to fix a bug in it.
111 from inspect import getsourcefile, getfile, getmodule, \
111 from inspect import getsourcefile, getfile, getmodule, \
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113
113
114 # IPython's own modules
114 # IPython's own modules
115 # Modified pdb which doesn't damage IPython's readline handling
115 # Modified pdb which doesn't damage IPython's readline handling
116 from IPython import get_ipython
116 from IPython import get_ipython
117 from IPython.core import debugger
117 from IPython.core import debugger
118 from IPython.core.display_trap import DisplayTrap
118 from IPython.core.display_trap import DisplayTrap
119 from IPython.core.excolors import exception_colors
119 from IPython.core.excolors import exception_colors
120 from IPython.utils import PyColorize
120 from IPython.utils import PyColorize
121 from IPython.utils import io
121 from IPython.utils import io
122 from IPython.utils import openpy
122 from IPython.utils import openpy
123 from IPython.utils import path as util_path
123 from IPython.utils import path as util_path
124 from IPython.utils import py3compat
124 from IPython.utils import py3compat
125 from IPython.utils import ulinecache
125 from IPython.utils import ulinecache
126 from IPython.utils.data import uniq_stable
126 from IPython.utils.data import uniq_stable
127 from IPython.utils.terminal import get_terminal_size
127 from logging import info, error
128 from logging import info, error
128
129
129 import IPython.utils.colorable as colorable
130 import IPython.utils.colorable as colorable
130
131
131 # Globals
132 # Globals
132 # amount of space to put line numbers before verbose tracebacks
133 # amount of space to put line numbers before verbose tracebacks
133 INDENT_SIZE = 8
134 INDENT_SIZE = 8
134
135
135 # Default color scheme. This is used, for example, by the traceback
136 # Default color scheme. This is used, for example, by the traceback
136 # formatter. When running in an actual IPython instance, the user's rc.colors
137 # formatter. When running in an actual IPython instance, the user's rc.colors
137 # value is used, but having a module global makes this functionality available
138 # value is used, but having a module global makes this functionality available
138 # to users of ultratb who are NOT running inside ipython.
139 # to users of ultratb who are NOT running inside ipython.
139 DEFAULT_SCHEME = 'NoColor'
140 DEFAULT_SCHEME = 'NoColor'
140
141
141 # ---------------------------------------------------------------------------
142 # ---------------------------------------------------------------------------
142 # Code begins
143 # Code begins
143
144
144 # Utility functions
145 # Utility functions
145 def inspect_error():
146 def inspect_error():
146 """Print a message about internal inspect errors.
147 """Print a message about internal inspect errors.
147
148
148 These are unfortunately quite common."""
149 These are unfortunately quite common."""
149
150
150 error('Internal Python error in the inspect module.\n'
151 error('Internal Python error in the inspect module.\n'
151 'Below is the traceback from this internal error.\n')
152 'Below is the traceback from this internal error.\n')
152
153
153
154
154 # This function is a monkeypatch we apply to the Python inspect module. We have
155 # This function is a monkeypatch we apply to the Python inspect module. We have
155 # now found when it's needed (see discussion on issue gh-1456), and we have a
156 # now found when it's needed (see discussion on issue gh-1456), and we have a
156 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
157 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
157 # the monkeypatch is not applied. TK, Aug 2012.
158 # the monkeypatch is not applied. TK, Aug 2012.
158 def findsource(object):
159 def findsource(object):
159 """Return the entire source file and starting line number for an object.
160 """Return the entire source file and starting line number for an object.
160
161
161 The argument may be a module, class, method, function, traceback, frame,
162 The argument may be a module, class, method, function, traceback, frame,
162 or code object. The source code is returned as a list of all the lines
163 or code object. The source code is returned as a list of all the lines
163 in the file and the line number indexes a line in that list. An IOError
164 in the file and the line number indexes a line in that list. An IOError
164 is raised if the source code cannot be retrieved.
165 is raised if the source code cannot be retrieved.
165
166
166 FIXED version with which we monkeypatch the stdlib to work around a bug."""
167 FIXED version with which we monkeypatch the stdlib to work around a bug."""
167
168
168 file = getsourcefile(object) or getfile(object)
169 file = getsourcefile(object) or getfile(object)
169 # If the object is a frame, then trying to get the globals dict from its
170 # If the object is a frame, then trying to get the globals dict from its
170 # module won't work. Instead, the frame object itself has the globals
171 # module won't work. Instead, the frame object itself has the globals
171 # dictionary.
172 # dictionary.
172 globals_dict = None
173 globals_dict = None
173 if inspect.isframe(object):
174 if inspect.isframe(object):
174 # XXX: can this ever be false?
175 # XXX: can this ever be false?
175 globals_dict = object.f_globals
176 globals_dict = object.f_globals
176 else:
177 else:
177 module = getmodule(object, file)
178 module = getmodule(object, file)
178 if module:
179 if module:
179 globals_dict = module.__dict__
180 globals_dict = module.__dict__
180 lines = linecache.getlines(file, globals_dict)
181 lines = linecache.getlines(file, globals_dict)
181 if not lines:
182 if not lines:
182 raise IOError('could not get source code')
183 raise IOError('could not get source code')
183
184
184 if ismodule(object):
185 if ismodule(object):
185 return lines, 0
186 return lines, 0
186
187
187 if isclass(object):
188 if isclass(object):
188 name = object.__name__
189 name = object.__name__
189 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
190 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
190 # make some effort to find the best matching class definition:
191 # make some effort to find the best matching class definition:
191 # use the one with the least indentation, which is the one
192 # use the one with the least indentation, which is the one
192 # that's most probably not inside a function definition.
193 # that's most probably not inside a function definition.
193 candidates = []
194 candidates = []
194 for i in range(len(lines)):
195 for i in range(len(lines)):
195 match = pat.match(lines[i])
196 match = pat.match(lines[i])
196 if match:
197 if match:
197 # if it's at toplevel, it's already the best one
198 # if it's at toplevel, it's already the best one
198 if lines[i][0] == 'c':
199 if lines[i][0] == 'c':
199 return lines, i
200 return lines, i
200 # else add whitespace to candidate list
201 # else add whitespace to candidate list
201 candidates.append((match.group(1), i))
202 candidates.append((match.group(1), i))
202 if candidates:
203 if candidates:
203 # this will sort by whitespace, and by line number,
204 # this will sort by whitespace, and by line number,
204 # less whitespace first
205 # less whitespace first
205 candidates.sort()
206 candidates.sort()
206 return lines, candidates[0][1]
207 return lines, candidates[0][1]
207 else:
208 else:
208 raise IOError('could not find class definition')
209 raise IOError('could not find class definition')
209
210
210 if ismethod(object):
211 if ismethod(object):
211 object = object.__func__
212 object = object.__func__
212 if isfunction(object):
213 if isfunction(object):
213 object = object.__code__
214 object = object.__code__
214 if istraceback(object):
215 if istraceback(object):
215 object = object.tb_frame
216 object = object.tb_frame
216 if isframe(object):
217 if isframe(object):
217 object = object.f_code
218 object = object.f_code
218 if iscode(object):
219 if iscode(object):
219 if not hasattr(object, 'co_firstlineno'):
220 if not hasattr(object, 'co_firstlineno'):
220 raise IOError('could not find function definition')
221 raise IOError('could not find function definition')
221 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
222 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
222 pmatch = pat.match
223 pmatch = pat.match
223 # fperez - fix: sometimes, co_firstlineno can give a number larger than
224 # fperez - fix: sometimes, co_firstlineno can give a number larger than
224 # the length of lines, which causes an error. Safeguard against that.
225 # the length of lines, which causes an error. Safeguard against that.
225 lnum = min(object.co_firstlineno, len(lines)) - 1
226 lnum = min(object.co_firstlineno, len(lines)) - 1
226 while lnum > 0:
227 while lnum > 0:
227 if pmatch(lines[lnum]):
228 if pmatch(lines[lnum]):
228 break
229 break
229 lnum -= 1
230 lnum -= 1
230
231
231 return lines, lnum
232 return lines, lnum
232 raise IOError('could not find code object')
233 raise IOError('could not find code object')
233
234
234
235
235 # This is a patched version of inspect.getargs that applies the (unmerged)
236 # This is a patched version of inspect.getargs that applies the (unmerged)
236 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
237 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
237 # https://github.com/ipython/ipython/issues/8205 and
238 # https://github.com/ipython/ipython/issues/8205 and
238 # https://github.com/ipython/ipython/issues/8293
239 # https://github.com/ipython/ipython/issues/8293
239 def getargs(co):
240 def getargs(co):
240 """Get information about the arguments accepted by a code object.
241 """Get information about the arguments accepted by a code object.
241
242
242 Three things are returned: (args, varargs, varkw), where 'args' is
243 Three things are returned: (args, varargs, varkw), where 'args' is
243 a list of argument names (possibly containing nested lists), and
244 a list of argument names (possibly containing nested lists), and
244 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
245 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
245 if not iscode(co):
246 if not iscode(co):
246 raise TypeError('{!r} is not a code object'.format(co))
247 raise TypeError('{!r} is not a code object'.format(co))
247
248
248 nargs = co.co_argcount
249 nargs = co.co_argcount
249 names = co.co_varnames
250 names = co.co_varnames
250 args = list(names[:nargs])
251 args = list(names[:nargs])
251 step = 0
252 step = 0
252
253
253 # The following acrobatics are for anonymous (tuple) arguments.
254 # The following acrobatics are for anonymous (tuple) arguments.
254 for i in range(nargs):
255 for i in range(nargs):
255 if args[i][:1] in ('', '.'):
256 if args[i][:1] in ('', '.'):
256 stack, remain, count = [], [], []
257 stack, remain, count = [], [], []
257 while step < len(co.co_code):
258 while step < len(co.co_code):
258 op = ord(co.co_code[step])
259 op = ord(co.co_code[step])
259 step = step + 1
260 step = step + 1
260 if op >= dis.HAVE_ARGUMENT:
261 if op >= dis.HAVE_ARGUMENT:
261 opname = dis.opname[op]
262 opname = dis.opname[op]
262 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
263 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
263 step = step + 2
264 step = step + 2
264 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
265 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
265 remain.append(value)
266 remain.append(value)
266 count.append(value)
267 count.append(value)
267 elif opname in ('STORE_FAST', 'STORE_DEREF'):
268 elif opname in ('STORE_FAST', 'STORE_DEREF'):
268 if op in dis.haslocal:
269 if op in dis.haslocal:
269 stack.append(co.co_varnames[value])
270 stack.append(co.co_varnames[value])
270 elif op in dis.hasfree:
271 elif op in dis.hasfree:
271 stack.append((co.co_cellvars + co.co_freevars)[value])
272 stack.append((co.co_cellvars + co.co_freevars)[value])
272 # Special case for sublists of length 1: def foo((bar))
273 # Special case for sublists of length 1: def foo((bar))
273 # doesn't generate the UNPACK_TUPLE bytecode, so if
274 # doesn't generate the UNPACK_TUPLE bytecode, so if
274 # `remain` is empty here, we have such a sublist.
275 # `remain` is empty here, we have such a sublist.
275 if not remain:
276 if not remain:
276 stack[0] = [stack[0]]
277 stack[0] = [stack[0]]
277 break
278 break
278 else:
279 else:
279 remain[-1] = remain[-1] - 1
280 remain[-1] = remain[-1] - 1
280 while remain[-1] == 0:
281 while remain[-1] == 0:
281 remain.pop()
282 remain.pop()
282 size = count.pop()
283 size = count.pop()
283 stack[-size:] = [stack[-size:]]
284 stack[-size:] = [stack[-size:]]
284 if not remain:
285 if not remain:
285 break
286 break
286 remain[-1] = remain[-1] - 1
287 remain[-1] = remain[-1] - 1
287 if not remain:
288 if not remain:
288 break
289 break
289 args[i] = stack[0]
290 args[i] = stack[0]
290
291
291 varargs = None
292 varargs = None
292 if co.co_flags & inspect.CO_VARARGS:
293 if co.co_flags & inspect.CO_VARARGS:
293 varargs = co.co_varnames[nargs]
294 varargs = co.co_varnames[nargs]
294 nargs = nargs + 1
295 nargs = nargs + 1
295 varkw = None
296 varkw = None
296 if co.co_flags & inspect.CO_VARKEYWORDS:
297 if co.co_flags & inspect.CO_VARKEYWORDS:
297 varkw = co.co_varnames[nargs]
298 varkw = co.co_varnames[nargs]
298 return inspect.Arguments(args, varargs, varkw)
299 return inspect.Arguments(args, varargs, varkw)
299
300
300
301
301 # Monkeypatch inspect to apply our bugfix.
302 # Monkeypatch inspect to apply our bugfix.
302 def with_patch_inspect(f):
303 def with_patch_inspect(f):
303 """decorator for monkeypatching inspect.findsource"""
304 """decorator for monkeypatching inspect.findsource"""
304
305
305 def wrapped(*args, **kwargs):
306 def wrapped(*args, **kwargs):
306 save_findsource = inspect.findsource
307 save_findsource = inspect.findsource
307 save_getargs = inspect.getargs
308 save_getargs = inspect.getargs
308 inspect.findsource = findsource
309 inspect.findsource = findsource
309 inspect.getargs = getargs
310 inspect.getargs = getargs
310 try:
311 try:
311 return f(*args, **kwargs)
312 return f(*args, **kwargs)
312 finally:
313 finally:
313 inspect.findsource = save_findsource
314 inspect.findsource = save_findsource
314 inspect.getargs = save_getargs
315 inspect.getargs = save_getargs
315
316
316 return wrapped
317 return wrapped
317
318
318
319
319 if py3compat.PY3:
320 if py3compat.PY3:
320 fixed_getargvalues = inspect.getargvalues
321 fixed_getargvalues = inspect.getargvalues
321 else:
322 else:
322 # Fixes for https://github.com/ipython/ipython/issues/8293
323 # Fixes for https://github.com/ipython/ipython/issues/8293
323 # and https://github.com/ipython/ipython/issues/8205.
324 # and https://github.com/ipython/ipython/issues/8205.
324 # The relevant bug is caused by failure to correctly handle anonymous tuple
325 # The relevant bug is caused by failure to correctly handle anonymous tuple
325 # unpacking, which only exists in Python 2.
326 # unpacking, which only exists in Python 2.
326 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
327 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
327
328
328
329
329 def fix_frame_records_filenames(records):
330 def fix_frame_records_filenames(records):
330 """Try to fix the filenames in each record from inspect.getinnerframes().
331 """Try to fix the filenames in each record from inspect.getinnerframes().
331
332
332 Particularly, modules loaded from within zip files have useless filenames
333 Particularly, modules loaded from within zip files have useless filenames
333 attached to their code object, and inspect.getinnerframes() just uses it.
334 attached to their code object, and inspect.getinnerframes() just uses it.
334 """
335 """
335 fixed_records = []
336 fixed_records = []
336 for frame, filename, line_no, func_name, lines, index in records:
337 for frame, filename, line_no, func_name, lines, index in records:
337 # Look inside the frame's globals dictionary for __file__,
338 # Look inside the frame's globals dictionary for __file__,
338 # which should be better. However, keep Cython filenames since
339 # which should be better. However, keep Cython filenames since
339 # we prefer the source filenames over the compiled .so file.
340 # we prefer the source filenames over the compiled .so file.
340 filename = py3compat.cast_unicode_py2(filename, "utf-8")
341 filename = py3compat.cast_unicode_py2(filename, "utf-8")
341 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
342 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
342 better_fn = frame.f_globals.get('__file__', None)
343 better_fn = frame.f_globals.get('__file__', None)
343 if isinstance(better_fn, str):
344 if isinstance(better_fn, str):
344 # Check the type just in case someone did something weird with
345 # Check the type just in case someone did something weird with
345 # __file__. It might also be None if the error occurred during
346 # __file__. It might also be None if the error occurred during
346 # import.
347 # import.
347 filename = better_fn
348 filename = better_fn
348 fixed_records.append((frame, filename, line_no, func_name, lines, index))
349 fixed_records.append((frame, filename, line_no, func_name, lines, index))
349 return fixed_records
350 return fixed_records
350
351
351
352
352 @with_patch_inspect
353 @with_patch_inspect
353 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
354 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
354 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
355 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
355
356
356 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
357 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
357 # If the error is at the console, don't build any context, since it would
358 # If the error is at the console, don't build any context, since it would
358 # otherwise produce 5 blank lines printed out (there is no file at the
359 # otherwise produce 5 blank lines printed out (there is no file at the
359 # console)
360 # console)
360 rec_check = records[tb_offset:]
361 rec_check = records[tb_offset:]
361 try:
362 try:
362 rname = rec_check[0][1]
363 rname = rec_check[0][1]
363 if rname == '<ipython console>' or rname.endswith('<string>'):
364 if rname == '<ipython console>' or rname.endswith('<string>'):
364 return rec_check
365 return rec_check
365 except IndexError:
366 except IndexError:
366 pass
367 pass
367
368
368 aux = traceback.extract_tb(etb)
369 aux = traceback.extract_tb(etb)
369 assert len(records) == len(aux)
370 assert len(records) == len(aux)
370 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
371 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
371 maybeStart = lnum - 1 - context // 2
372 maybeStart = lnum - 1 - context // 2
372 start = max(maybeStart, 0)
373 start = max(maybeStart, 0)
373 end = start + context
374 end = start + context
374 lines = ulinecache.getlines(file)[start:end]
375 lines = ulinecache.getlines(file)[start:end]
375 buf = list(records[i])
376 buf = list(records[i])
376 buf[LNUM_POS] = lnum
377 buf[LNUM_POS] = lnum
377 buf[INDEX_POS] = lnum - 1 - start
378 buf[INDEX_POS] = lnum - 1 - start
378 buf[LINES_POS] = lines
379 buf[LINES_POS] = lines
379 records[i] = tuple(buf)
380 records[i] = tuple(buf)
380 return records[tb_offset:]
381 return records[tb_offset:]
381
382
382 # Helper function -- largely belongs to VerboseTB, but we need the same
383 # Helper function -- largely belongs to VerboseTB, but we need the same
383 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
384 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
384 # can be recognized properly by ipython.el's py-traceback-line-re
385 # can be recognized properly by ipython.el's py-traceback-line-re
385 # (SyntaxErrors have to be treated specially because they have no traceback)
386 # (SyntaxErrors have to be treated specially because they have no traceback)
386
387
387 _parser = PyColorize.Parser()
388 _parser = PyColorize.Parser()
388
389
389
390
390 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
391 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
391 numbers_width = INDENT_SIZE - 1
392 numbers_width = INDENT_SIZE - 1
392 res = []
393 res = []
393 i = lnum - index
394 i = lnum - index
394
395
395 # This lets us get fully syntax-highlighted tracebacks.
396 # This lets us get fully syntax-highlighted tracebacks.
396 if scheme is None:
397 if scheme is None:
397 ipinst = get_ipython()
398 ipinst = get_ipython()
398 if ipinst is not None:
399 if ipinst is not None:
399 scheme = ipinst.colors
400 scheme = ipinst.colors
400 else:
401 else:
401 scheme = DEFAULT_SCHEME
402 scheme = DEFAULT_SCHEME
402
403
403 _line_format = _parser.format2
404 _line_format = _parser.format2
404
405
405 for line in lines:
406 for line in lines:
406 line = py3compat.cast_unicode(line)
407 line = py3compat.cast_unicode(line)
407
408
408 new_line, err = _line_format(line, 'str', scheme)
409 new_line, err = _line_format(line, 'str', scheme)
409 if not err: line = new_line
410 if not err: line = new_line
410
411
411 if i == lnum:
412 if i == lnum:
412 # This is the line with the error
413 # This is the line with the error
413 pad = numbers_width - len(str(i))
414 pad = numbers_width - len(str(i))
414 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
415 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
415 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
416 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
416 Colors.line, line, Colors.Normal)
417 Colors.line, line, Colors.Normal)
417 else:
418 else:
418 num = '%*s' % (numbers_width, i)
419 num = '%*s' % (numbers_width, i)
419 line = '%s%s%s %s' % (Colors.lineno, num,
420 line = '%s%s%s %s' % (Colors.lineno, num,
420 Colors.Normal, line)
421 Colors.Normal, line)
421
422
422 res.append(line)
423 res.append(line)
423 if lvals and i == lnum:
424 if lvals and i == lnum:
424 res.append(lvals + '\n')
425 res.append(lvals + '\n')
425 i = i + 1
426 i = i + 1
426 return res
427 return res
427
428
428 def is_recursion_error(etype, value, records):
429 def is_recursion_error(etype, value, records):
429 try:
430 try:
430 # RecursionError is new in Python 3.5
431 # RecursionError is new in Python 3.5
431 recursion_error_type = RecursionError
432 recursion_error_type = RecursionError
432 except NameError:
433 except NameError:
433 recursion_error_type = RuntimeError
434 recursion_error_type = RuntimeError
434
435
435 # The default recursion limit is 1000, but some of that will be taken up
436 # The default recursion limit is 1000, but some of that will be taken up
436 # by stack frames in IPython itself. >500 frames probably indicates
437 # by stack frames in IPython itself. >500 frames probably indicates
437 # a recursion error.
438 # a recursion error.
438 return (etype is recursion_error_type) \
439 return (etype is recursion_error_type) \
439 and "recursion" in str(value).lower() \
440 and "recursion" in str(value).lower() \
440 and len(records) > 500
441 and len(records) > 500
441
442
442 def find_recursion(etype, value, records):
443 def find_recursion(etype, value, records):
443 """Identify the repeating stack frames from a RecursionError traceback
444 """Identify the repeating stack frames from a RecursionError traceback
444
445
445 'records' is a list as returned by VerboseTB.get_records()
446 'records' is a list as returned by VerboseTB.get_records()
446
447
447 Returns (last_unique, repeat_length)
448 Returns (last_unique, repeat_length)
448 """
449 """
449 # This involves a bit of guesswork - we want to show enough of the traceback
450 # This involves a bit of guesswork - we want to show enough of the traceback
450 # to indicate where the recursion is occurring. We guess that the innermost
451 # to indicate where the recursion is occurring. We guess that the innermost
451 # quarter of the traceback (250 frames by default) is repeats, and find the
452 # quarter of the traceback (250 frames by default) is repeats, and find the
452 # first frame (from in to out) that looks different.
453 # first frame (from in to out) that looks different.
453 if not is_recursion_error(etype, value, records):
454 if not is_recursion_error(etype, value, records):
454 return len(records), 0
455 return len(records), 0
455
456
456 # Select filename, lineno, func_name to track frames with
457 # Select filename, lineno, func_name to track frames with
457 records = [r[1:4] for r in records]
458 records = [r[1:4] for r in records]
458 inner_frames = records[-(len(records)//4):]
459 inner_frames = records[-(len(records)//4):]
459 frames_repeated = set(inner_frames)
460 frames_repeated = set(inner_frames)
460
461
461 last_seen_at = {}
462 last_seen_at = {}
462 longest_repeat = 0
463 longest_repeat = 0
463 i = len(records)
464 i = len(records)
464 for frame in reversed(records):
465 for frame in reversed(records):
465 i -= 1
466 i -= 1
466 if frame not in frames_repeated:
467 if frame not in frames_repeated:
467 last_unique = i
468 last_unique = i
468 break
469 break
469
470
470 if frame in last_seen_at:
471 if frame in last_seen_at:
471 distance = last_seen_at[frame] - i
472 distance = last_seen_at[frame] - i
472 longest_repeat = max(longest_repeat, distance)
473 longest_repeat = max(longest_repeat, distance)
473
474
474 last_seen_at[frame] = i
475 last_seen_at[frame] = i
475 else:
476 else:
476 last_unique = 0 # The whole traceback was recursion
477 last_unique = 0 # The whole traceback was recursion
477
478
478 return last_unique, longest_repeat
479 return last_unique, longest_repeat
479
480
480 #---------------------------------------------------------------------------
481 #---------------------------------------------------------------------------
481 # Module classes
482 # Module classes
482 class TBTools(colorable.Colorable):
483 class TBTools(colorable.Colorable):
483 """Basic tools used by all traceback printer classes."""
484 """Basic tools used by all traceback printer classes."""
484
485
485 # Number of frames to skip when reporting tracebacks
486 # Number of frames to skip when reporting tracebacks
486 tb_offset = 0
487 tb_offset = 0
487
488
488 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
489 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
489 # Whether to call the interactive pdb debugger after printing
490 # Whether to call the interactive pdb debugger after printing
490 # tracebacks or not
491 # tracebacks or not
491 super(TBTools, self).__init__(parent=parent, config=config)
492 super(TBTools, self).__init__(parent=parent, config=config)
492 self.call_pdb = call_pdb
493 self.call_pdb = call_pdb
493
494
494 # Output stream to write to. Note that we store the original value in
495 # Output stream to write to. Note that we store the original value in
495 # a private attribute and then make the public ostream a property, so
496 # a private attribute and then make the public ostream a property, so
496 # that we can delay accessing io.stdout until runtime. The way
497 # that we can delay accessing io.stdout until runtime. The way
497 # things are written now, the io.stdout object is dynamically managed
498 # things are written now, the io.stdout object is dynamically managed
498 # so a reference to it should NEVER be stored statically. This
499 # so a reference to it should NEVER be stored statically. This
499 # property approach confines this detail to a single location, and all
500 # property approach confines this detail to a single location, and all
500 # subclasses can simply access self.ostream for writing.
501 # subclasses can simply access self.ostream for writing.
501 self._ostream = ostream
502 self._ostream = ostream
502
503
503 # Create color table
504 # Create color table
504 self.color_scheme_table = exception_colors()
505 self.color_scheme_table = exception_colors()
505
506
506 self.set_colors(color_scheme)
507 self.set_colors(color_scheme)
507 self.old_scheme = color_scheme # save initial value for toggles
508 self.old_scheme = color_scheme # save initial value for toggles
508
509
509 if call_pdb:
510 if call_pdb:
510 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
511 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
511 else:
512 else:
512 self.pdb = None
513 self.pdb = None
513
514
514 def _get_ostream(self):
515 def _get_ostream(self):
515 """Output stream that exceptions are written to.
516 """Output stream that exceptions are written to.
516
517
517 Valid values are:
518 Valid values are:
518
519
519 - None: the default, which means that IPython will dynamically resolve
520 - None: the default, which means that IPython will dynamically resolve
520 to io.stdout. This ensures compatibility with most tools, including
521 to io.stdout. This ensures compatibility with most tools, including
521 Windows (where plain stdout doesn't recognize ANSI escapes).
522 Windows (where plain stdout doesn't recognize ANSI escapes).
522
523
523 - Any object with 'write' and 'flush' attributes.
524 - Any object with 'write' and 'flush' attributes.
524 """
525 """
525 return io.stdout if self._ostream is None else self._ostream
526 return io.stdout if self._ostream is None else self._ostream
526
527
527 def _set_ostream(self, val):
528 def _set_ostream(self, val):
528 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
529 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
529 self._ostream = val
530 self._ostream = val
530
531
531 ostream = property(_get_ostream, _set_ostream)
532 ostream = property(_get_ostream, _set_ostream)
532
533
533 def set_colors(self, *args, **kw):
534 def set_colors(self, *args, **kw):
534 """Shorthand access to the color table scheme selector method."""
535 """Shorthand access to the color table scheme selector method."""
535
536
536 # Set own color table
537 # Set own color table
537 self.color_scheme_table.set_active_scheme(*args, **kw)
538 self.color_scheme_table.set_active_scheme(*args, **kw)
538 # for convenience, set Colors to the active scheme
539 # for convenience, set Colors to the active scheme
539 self.Colors = self.color_scheme_table.active_colors
540 self.Colors = self.color_scheme_table.active_colors
540 # Also set colors of debugger
541 # Also set colors of debugger
541 if hasattr(self, 'pdb') and self.pdb is not None:
542 if hasattr(self, 'pdb') and self.pdb is not None:
542 self.pdb.set_colors(*args, **kw)
543 self.pdb.set_colors(*args, **kw)
543
544
544 def color_toggle(self):
545 def color_toggle(self):
545 """Toggle between the currently active color scheme and NoColor."""
546 """Toggle between the currently active color scheme and NoColor."""
546
547
547 if self.color_scheme_table.active_scheme_name == 'NoColor':
548 if self.color_scheme_table.active_scheme_name == 'NoColor':
548 self.color_scheme_table.set_active_scheme(self.old_scheme)
549 self.color_scheme_table.set_active_scheme(self.old_scheme)
549 self.Colors = self.color_scheme_table.active_colors
550 self.Colors = self.color_scheme_table.active_colors
550 else:
551 else:
551 self.old_scheme = self.color_scheme_table.active_scheme_name
552 self.old_scheme = self.color_scheme_table.active_scheme_name
552 self.color_scheme_table.set_active_scheme('NoColor')
553 self.color_scheme_table.set_active_scheme('NoColor')
553 self.Colors = self.color_scheme_table.active_colors
554 self.Colors = self.color_scheme_table.active_colors
554
555
555 def stb2text(self, stb):
556 def stb2text(self, stb):
556 """Convert a structured traceback (a list) to a string."""
557 """Convert a structured traceback (a list) to a string."""
557 return '\n'.join(stb)
558 return '\n'.join(stb)
558
559
559 def text(self, etype, value, tb, tb_offset=None, context=5):
560 def text(self, etype, value, tb, tb_offset=None, context=5):
560 """Return formatted traceback.
561 """Return formatted traceback.
561
562
562 Subclasses may override this if they add extra arguments.
563 Subclasses may override this if they add extra arguments.
563 """
564 """
564 tb_list = self.structured_traceback(etype, value, tb,
565 tb_list = self.structured_traceback(etype, value, tb,
565 tb_offset, context)
566 tb_offset, context)
566 return self.stb2text(tb_list)
567 return self.stb2text(tb_list)
567
568
568 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
569 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
569 context=5, mode=None):
570 context=5, mode=None):
570 """Return a list of traceback frames.
571 """Return a list of traceback frames.
571
572
572 Must be implemented by each class.
573 Must be implemented by each class.
573 """
574 """
574 raise NotImplementedError()
575 raise NotImplementedError()
575
576
576
577
577 #---------------------------------------------------------------------------
578 #---------------------------------------------------------------------------
578 class ListTB(TBTools):
579 class ListTB(TBTools):
579 """Print traceback information from a traceback list, with optional color.
580 """Print traceback information from a traceback list, with optional color.
580
581
581 Calling requires 3 arguments: (etype, evalue, elist)
582 Calling requires 3 arguments: (etype, evalue, elist)
582 as would be obtained by::
583 as would be obtained by::
583
584
584 etype, evalue, tb = sys.exc_info()
585 etype, evalue, tb = sys.exc_info()
585 if tb:
586 if tb:
586 elist = traceback.extract_tb(tb)
587 elist = traceback.extract_tb(tb)
587 else:
588 else:
588 elist = None
589 elist = None
589
590
590 It can thus be used by programs which need to process the traceback before
591 It can thus be used by programs which need to process the traceback before
591 printing (such as console replacements based on the code module from the
592 printing (such as console replacements based on the code module from the
592 standard library).
593 standard library).
593
594
594 Because they are meant to be called without a full traceback (only a
595 Because they are meant to be called without a full traceback (only a
595 list), instances of this class can't call the interactive pdb debugger."""
596 list), instances of this class can't call the interactive pdb debugger."""
596
597
597 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None):
598 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None):
598 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
599 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
599 ostream=ostream, parent=parent)
600 ostream=ostream, parent=parent)
600
601
601 def __call__(self, etype, value, elist):
602 def __call__(self, etype, value, elist):
602 self.ostream.flush()
603 self.ostream.flush()
603 self.ostream.write(self.text(etype, value, elist))
604 self.ostream.write(self.text(etype, value, elist))
604 self.ostream.write('\n')
605 self.ostream.write('\n')
605
606
606 def structured_traceback(self, etype, value, elist, tb_offset=None,
607 def structured_traceback(self, etype, value, elist, tb_offset=None,
607 context=5):
608 context=5):
608 """Return a color formatted string with the traceback info.
609 """Return a color formatted string with the traceback info.
609
610
610 Parameters
611 Parameters
611 ----------
612 ----------
612 etype : exception type
613 etype : exception type
613 Type of the exception raised.
614 Type of the exception raised.
614
615
615 value : object
616 value : object
616 Data stored in the exception
617 Data stored in the exception
617
618
618 elist : list
619 elist : list
619 List of frames, see class docstring for details.
620 List of frames, see class docstring for details.
620
621
621 tb_offset : int, optional
622 tb_offset : int, optional
622 Number of frames in the traceback to skip. If not given, the
623 Number of frames in the traceback to skip. If not given, the
623 instance value is used (set in constructor).
624 instance value is used (set in constructor).
624
625
625 context : int, optional
626 context : int, optional
626 Number of lines of context information to print.
627 Number of lines of context information to print.
627
628
628 Returns
629 Returns
629 -------
630 -------
630 String with formatted exception.
631 String with formatted exception.
631 """
632 """
632 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 Colors = self.Colors
634 Colors = self.Colors
634 out_list = []
635 out_list = []
635 if elist:
636 if elist:
636
637
637 if tb_offset and len(elist) > tb_offset:
638 if tb_offset and len(elist) > tb_offset:
638 elist = elist[tb_offset:]
639 elist = elist[tb_offset:]
639
640
640 out_list.append('Traceback %s(most recent call last)%s:' %
641 out_list.append('Traceback %s(most recent call last)%s:' %
641 (Colors.normalEm, Colors.Normal) + '\n')
642 (Colors.normalEm, Colors.Normal) + '\n')
642 out_list.extend(self._format_list(elist))
643 out_list.extend(self._format_list(elist))
643 # The exception info should be a single entry in the list.
644 # The exception info should be a single entry in the list.
644 lines = ''.join(self._format_exception_only(etype, value))
645 lines = ''.join(self._format_exception_only(etype, value))
645 out_list.append(lines)
646 out_list.append(lines)
646
647
647 # Note: this code originally read:
648 # Note: this code originally read:
648
649
649 ## for line in lines[:-1]:
650 ## for line in lines[:-1]:
650 ## out_list.append(" "+line)
651 ## out_list.append(" "+line)
651 ## out_list.append(lines[-1])
652 ## out_list.append(lines[-1])
652
653
653 # This means it was indenting everything but the last line by a little
654 # This means it was indenting everything but the last line by a little
654 # bit. I've disabled this for now, but if we see ugliness somewhere we
655 # bit. I've disabled this for now, but if we see ugliness somewhere we
655 # can restore it.
656 # can restore it.
656
657
657 return out_list
658 return out_list
658
659
659 def _format_list(self, extracted_list):
660 def _format_list(self, extracted_list):
660 """Format a list of traceback entry tuples for printing.
661 """Format a list of traceback entry tuples for printing.
661
662
662 Given a list of tuples as returned by extract_tb() or
663 Given a list of tuples as returned by extract_tb() or
663 extract_stack(), return a list of strings ready for printing.
664 extract_stack(), return a list of strings ready for printing.
664 Each string in the resulting list corresponds to the item with the
665 Each string in the resulting list corresponds to the item with the
665 same index in the argument list. Each string ends in a newline;
666 same index in the argument list. Each string ends in a newline;
666 the strings may contain internal newlines as well, for those items
667 the strings may contain internal newlines as well, for those items
667 whose source text line is not None.
668 whose source text line is not None.
668
669
669 Lifted almost verbatim from traceback.py
670 Lifted almost verbatim from traceback.py
670 """
671 """
671
672
672 Colors = self.Colors
673 Colors = self.Colors
673 list = []
674 list = []
674 for filename, lineno, name, line in extracted_list[:-1]:
675 for filename, lineno, name, line in extracted_list[:-1]:
675 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
676 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
676 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
677 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
677 Colors.lineno, lineno, Colors.Normal,
678 Colors.lineno, lineno, Colors.Normal,
678 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
679 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
679 if line:
680 if line:
680 item += ' %s\n' % line.strip()
681 item += ' %s\n' % line.strip()
681 list.append(item)
682 list.append(item)
682 # Emphasize the last entry
683 # Emphasize the last entry
683 filename, lineno, name, line = extracted_list[-1]
684 filename, lineno, name, line = extracted_list[-1]
684 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
685 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
685 (Colors.normalEm,
686 (Colors.normalEm,
686 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
687 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
687 Colors.linenoEm, lineno, Colors.normalEm,
688 Colors.linenoEm, lineno, Colors.normalEm,
688 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
689 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
689 Colors.Normal)
690 Colors.Normal)
690 if line:
691 if line:
691 item += '%s %s%s\n' % (Colors.line, line.strip(),
692 item += '%s %s%s\n' % (Colors.line, line.strip(),
692 Colors.Normal)
693 Colors.Normal)
693 list.append(item)
694 list.append(item)
694 return list
695 return list
695
696
696 def _format_exception_only(self, etype, value):
697 def _format_exception_only(self, etype, value):
697 """Format the exception part of a traceback.
698 """Format the exception part of a traceback.
698
699
699 The arguments are the exception type and value such as given by
700 The arguments are the exception type and value such as given by
700 sys.exc_info()[:2]. The return value is a list of strings, each ending
701 sys.exc_info()[:2]. The return value is a list of strings, each ending
701 in a newline. Normally, the list contains a single string; however,
702 in a newline. Normally, the list contains a single string; however,
702 for SyntaxError exceptions, it contains several lines that (when
703 for SyntaxError exceptions, it contains several lines that (when
703 printed) display detailed information about where the syntax error
704 printed) display detailed information about where the syntax error
704 occurred. The message indicating which exception occurred is the
705 occurred. The message indicating which exception occurred is the
705 always last string in the list.
706 always last string in the list.
706
707
707 Also lifted nearly verbatim from traceback.py
708 Also lifted nearly verbatim from traceback.py
708 """
709 """
709 have_filedata = False
710 have_filedata = False
710 Colors = self.Colors
711 Colors = self.Colors
711 list = []
712 list = []
712 stype = Colors.excName + etype.__name__ + Colors.Normal
713 stype = Colors.excName + etype.__name__ + Colors.Normal
713 if value is None:
714 if value is None:
714 # Not sure if this can still happen in Python 2.6 and above
715 # Not sure if this can still happen in Python 2.6 and above
715 list.append(py3compat.cast_unicode(stype) + '\n')
716 list.append(py3compat.cast_unicode(stype) + '\n')
716 else:
717 else:
717 if issubclass(etype, SyntaxError):
718 if issubclass(etype, SyntaxError):
718 have_filedata = True
719 have_filedata = True
719 if not value.filename: value.filename = "<string>"
720 if not value.filename: value.filename = "<string>"
720 if value.lineno:
721 if value.lineno:
721 lineno = value.lineno
722 lineno = value.lineno
722 textline = ulinecache.getline(value.filename, value.lineno)
723 textline = ulinecache.getline(value.filename, value.lineno)
723 else:
724 else:
724 lineno = 'unknown'
725 lineno = 'unknown'
725 textline = ''
726 textline = ''
726 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
727 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
727 (Colors.normalEm,
728 (Colors.normalEm,
728 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
729 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
729 Colors.linenoEm, lineno, Colors.Normal ))
730 Colors.linenoEm, lineno, Colors.Normal ))
730 if textline == '':
731 if textline == '':
731 textline = py3compat.cast_unicode(value.text, "utf-8")
732 textline = py3compat.cast_unicode(value.text, "utf-8")
732
733
733 if textline is not None:
734 if textline is not None:
734 i = 0
735 i = 0
735 while i < len(textline) and textline[i].isspace():
736 while i < len(textline) and textline[i].isspace():
736 i += 1
737 i += 1
737 list.append('%s %s%s\n' % (Colors.line,
738 list.append('%s %s%s\n' % (Colors.line,
738 textline.strip(),
739 textline.strip(),
739 Colors.Normal))
740 Colors.Normal))
740 if value.offset is not None:
741 if value.offset is not None:
741 s = ' '
742 s = ' '
742 for c in textline[i:value.offset - 1]:
743 for c in textline[i:value.offset - 1]:
743 if c.isspace():
744 if c.isspace():
744 s += c
745 s += c
745 else:
746 else:
746 s += ' '
747 s += ' '
747 list.append('%s%s^%s\n' % (Colors.caret, s,
748 list.append('%s%s^%s\n' % (Colors.caret, s,
748 Colors.Normal))
749 Colors.Normal))
749
750
750 try:
751 try:
751 s = value.msg
752 s = value.msg
752 except Exception:
753 except Exception:
753 s = self._some_str(value)
754 s = self._some_str(value)
754 if s:
755 if s:
755 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
756 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
756 Colors.Normal, s))
757 Colors.Normal, s))
757 else:
758 else:
758 list.append('%s\n' % str(stype))
759 list.append('%s\n' % str(stype))
759
760
760 # sync with user hooks
761 # sync with user hooks
761 if have_filedata:
762 if have_filedata:
762 ipinst = get_ipython()
763 ipinst = get_ipython()
763 if ipinst is not None:
764 if ipinst is not None:
764 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
765 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
765
766
766 return list
767 return list
767
768
768 def get_exception_only(self, etype, value):
769 def get_exception_only(self, etype, value):
769 """Only print the exception type and message, without a traceback.
770 """Only print the exception type and message, without a traceback.
770
771
771 Parameters
772 Parameters
772 ----------
773 ----------
773 etype : exception type
774 etype : exception type
774 value : exception value
775 value : exception value
775 """
776 """
776 return ListTB.structured_traceback(self, etype, value, [])
777 return ListTB.structured_traceback(self, etype, value, [])
777
778
778 def show_exception_only(self, etype, evalue):
779 def show_exception_only(self, etype, evalue):
779 """Only print the exception type and message, without a traceback.
780 """Only print the exception type and message, without a traceback.
780
781
781 Parameters
782 Parameters
782 ----------
783 ----------
783 etype : exception type
784 etype : exception type
784 value : exception value
785 value : exception value
785 """
786 """
786 # This method needs to use __call__ from *this* class, not the one from
787 # This method needs to use __call__ from *this* class, not the one from
787 # a subclass whose signature or behavior may be different
788 # a subclass whose signature or behavior may be different
788 ostream = self.ostream
789 ostream = self.ostream
789 ostream.flush()
790 ostream.flush()
790 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
791 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
791 ostream.flush()
792 ostream.flush()
792
793
793 def _some_str(self, value):
794 def _some_str(self, value):
794 # Lifted from traceback.py
795 # Lifted from traceback.py
795 try:
796 try:
796 return str(value)
797 return str(value)
797 except:
798 except:
798 return '<unprintable %s object>' % type(value).__name__
799 return '<unprintable %s object>' % type(value).__name__
799
800
800
801
801 #----------------------------------------------------------------------------
802 #----------------------------------------------------------------------------
802 class VerboseTB(TBTools):
803 class VerboseTB(TBTools):
803 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
804 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
804 of HTML. Requires inspect and pydoc. Crazy, man.
805 of HTML. Requires inspect and pydoc. Crazy, man.
805
806
806 Modified version which optionally strips the topmost entries from the
807 Modified version which optionally strips the topmost entries from the
807 traceback, to be used with alternate interpreters (because their own code
808 traceback, to be used with alternate interpreters (because their own code
808 would appear in the traceback)."""
809 would appear in the traceback)."""
809
810
810 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
811 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
811 tb_offset=0, long_header=False, include_vars=True,
812 tb_offset=0, long_header=False, include_vars=True,
812 check_cache=None):
813 check_cache=None):
813 """Specify traceback offset, headers and color scheme.
814 """Specify traceback offset, headers and color scheme.
814
815
815 Define how many frames to drop from the tracebacks. Calling it with
816 Define how many frames to drop from the tracebacks. Calling it with
816 tb_offset=1 allows use of this handler in interpreters which will have
817 tb_offset=1 allows use of this handler in interpreters which will have
817 their own code at the top of the traceback (VerboseTB will first
818 their own code at the top of the traceback (VerboseTB will first
818 remove that frame before printing the traceback info)."""
819 remove that frame before printing the traceback info)."""
819 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
820 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
820 ostream=ostream)
821 ostream=ostream)
821 self.tb_offset = tb_offset
822 self.tb_offset = tb_offset
822 self.long_header = long_header
823 self.long_header = long_header
823 self.include_vars = include_vars
824 self.include_vars = include_vars
824 # By default we use linecache.checkcache, but the user can provide a
825 # By default we use linecache.checkcache, but the user can provide a
825 # different check_cache implementation. This is used by the IPython
826 # different check_cache implementation. This is used by the IPython
826 # kernel to provide tracebacks for interactive code that is cached,
827 # kernel to provide tracebacks for interactive code that is cached,
827 # by a compiler instance that flushes the linecache but preserves its
828 # by a compiler instance that flushes the linecache but preserves its
828 # own code cache.
829 # own code cache.
829 if check_cache is None:
830 if check_cache is None:
830 check_cache = linecache.checkcache
831 check_cache = linecache.checkcache
831 self.check_cache = check_cache
832 self.check_cache = check_cache
832
833
833 def format_records(self, records, last_unique, recursion_repeat):
834 def format_records(self, records, last_unique, recursion_repeat):
834 """Format the stack frames of the traceback"""
835 """Format the stack frames of the traceback"""
835 frames = []
836 frames = []
836 for r in records[:last_unique+recursion_repeat+1]:
837 for r in records[:last_unique+recursion_repeat+1]:
837 #print '*** record:',file,lnum,func,lines,index # dbg
838 #print '*** record:',file,lnum,func,lines,index # dbg
838 frames.append(self.format_record(*r))
839 frames.append(self.format_record(*r))
839
840
840 if recursion_repeat:
841 if recursion_repeat:
841 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
842 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
842 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
843 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
843
844
844 return frames
845 return frames
845
846
846 def format_record(self, frame, file, lnum, func, lines, index):
847 def format_record(self, frame, file, lnum, func, lines, index):
847 """Format a single stack frame"""
848 """Format a single stack frame"""
848 Colors = self.Colors # just a shorthand + quicker name lookup
849 Colors = self.Colors # just a shorthand + quicker name lookup
849 ColorsNormal = Colors.Normal # used a lot
850 ColorsNormal = Colors.Normal # used a lot
850 col_scheme = self.color_scheme_table.active_scheme_name
851 col_scheme = self.color_scheme_table.active_scheme_name
851 indent = ' ' * INDENT_SIZE
852 indent = ' ' * INDENT_SIZE
852 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
853 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
853 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
854 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
854 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
855 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
855 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
856 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
856 ColorsNormal)
857 ColorsNormal)
857 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
858 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
858 (Colors.vName, Colors.valEm, ColorsNormal)
859 (Colors.vName, Colors.valEm, ColorsNormal)
859 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
860 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
860 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
861 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
861 Colors.vName, ColorsNormal)
862 Colors.vName, ColorsNormal)
862 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
863 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
863
864
864 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
865 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
865 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
866 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
866 ColorsNormal)
867 ColorsNormal)
867
868
868 abspath = os.path.abspath
869 abspath = os.path.abspath
869
870
870
871
871 if not file:
872 if not file:
872 file = '?'
873 file = '?'
873 elif file.startswith(str("<")) and file.endswith(str(">")):
874 elif file.startswith(str("<")) and file.endswith(str(">")):
874 # Not a real filename, no problem...
875 # Not a real filename, no problem...
875 pass
876 pass
876 elif not os.path.isabs(file):
877 elif not os.path.isabs(file):
877 # Try to make the filename absolute by trying all
878 # Try to make the filename absolute by trying all
878 # sys.path entries (which is also what linecache does)
879 # sys.path entries (which is also what linecache does)
879 for dirname in sys.path:
880 for dirname in sys.path:
880 try:
881 try:
881 fullname = os.path.join(dirname, file)
882 fullname = os.path.join(dirname, file)
882 if os.path.isfile(fullname):
883 if os.path.isfile(fullname):
883 file = os.path.abspath(fullname)
884 file = os.path.abspath(fullname)
884 break
885 break
885 except Exception:
886 except Exception:
886 # Just in case that sys.path contains very
887 # Just in case that sys.path contains very
887 # strange entries...
888 # strange entries...
888 pass
889 pass
889
890
890 file = py3compat.cast_unicode(file, util_path.fs_encoding)
891 file = py3compat.cast_unicode(file, util_path.fs_encoding)
891 link = tpl_link % file
892 link = tpl_link % file
892 args, varargs, varkw, locals = fixed_getargvalues(frame)
893 args, varargs, varkw, locals = fixed_getargvalues(frame)
893
894
894 if func == '?':
895 if func == '?':
895 call = ''
896 call = ''
896 else:
897 else:
897 # Decide whether to include variable details or not
898 # Decide whether to include variable details or not
898 var_repr = self.include_vars and eqrepr or nullrepr
899 var_repr = self.include_vars and eqrepr or nullrepr
899 try:
900 try:
900 call = tpl_call % (func, inspect.formatargvalues(args,
901 call = tpl_call % (func, inspect.formatargvalues(args,
901 varargs, varkw,
902 varargs, varkw,
902 locals, formatvalue=var_repr))
903 locals, formatvalue=var_repr))
903 except KeyError:
904 except KeyError:
904 # This happens in situations like errors inside generator
905 # This happens in situations like errors inside generator
905 # expressions, where local variables are listed in the
906 # expressions, where local variables are listed in the
906 # line, but can't be extracted from the frame. I'm not
907 # line, but can't be extracted from the frame. I'm not
907 # 100% sure this isn't actually a bug in inspect itself,
908 # 100% sure this isn't actually a bug in inspect itself,
908 # but since there's no info for us to compute with, the
909 # but since there's no info for us to compute with, the
909 # best we can do is report the failure and move on. Here
910 # best we can do is report the failure and move on. Here
910 # we must *not* call any traceback construction again,
911 # we must *not* call any traceback construction again,
911 # because that would mess up use of %debug later on. So we
912 # because that would mess up use of %debug later on. So we
912 # simply report the failure and move on. The only
913 # simply report the failure and move on. The only
913 # limitation will be that this frame won't have locals
914 # limitation will be that this frame won't have locals
914 # listed in the call signature. Quite subtle problem...
915 # listed in the call signature. Quite subtle problem...
915 # I can't think of a good way to validate this in a unit
916 # I can't think of a good way to validate this in a unit
916 # test, but running a script consisting of:
917 # test, but running a script consisting of:
917 # dict( (k,v.strip()) for (k,v) in range(10) )
918 # dict( (k,v.strip()) for (k,v) in range(10) )
918 # will illustrate the error, if this exception catch is
919 # will illustrate the error, if this exception catch is
919 # disabled.
920 # disabled.
920 call = tpl_call_fail % func
921 call = tpl_call_fail % func
921
922
922 # Don't attempt to tokenize binary files.
923 # Don't attempt to tokenize binary files.
923 if file.endswith(('.so', '.pyd', '.dll')):
924 if file.endswith(('.so', '.pyd', '.dll')):
924 return '%s %s\n' % (link, call)
925 return '%s %s\n' % (link, call)
925
926
926 elif file.endswith(('.pyc', '.pyo')):
927 elif file.endswith(('.pyc', '.pyo')):
927 # Look up the corresponding source file.
928 # Look up the corresponding source file.
928 file = openpy.source_from_cache(file)
929 file = openpy.source_from_cache(file)
929
930
930 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
931 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
931 line = getline(file, lnum[0])
932 line = getline(file, lnum[0])
932 lnum[0] += 1
933 lnum[0] += 1
933 return line
934 return line
934
935
935 # Build the list of names on this line of code where the exception
936 # Build the list of names on this line of code where the exception
936 # occurred.
937 # occurred.
937 try:
938 try:
938 names = []
939 names = []
939 name_cont = False
940 name_cont = False
940
941
941 for token_type, token, start, end, line in generate_tokens(linereader):
942 for token_type, token, start, end, line in generate_tokens(linereader):
942 # build composite names
943 # build composite names
943 if token_type == tokenize.NAME and token not in keyword.kwlist:
944 if token_type == tokenize.NAME and token not in keyword.kwlist:
944 if name_cont:
945 if name_cont:
945 # Continuation of a dotted name
946 # Continuation of a dotted name
946 try:
947 try:
947 names[-1].append(token)
948 names[-1].append(token)
948 except IndexError:
949 except IndexError:
949 names.append([token])
950 names.append([token])
950 name_cont = False
951 name_cont = False
951 else:
952 else:
952 # Regular new names. We append everything, the caller
953 # Regular new names. We append everything, the caller
953 # will be responsible for pruning the list later. It's
954 # will be responsible for pruning the list later. It's
954 # very tricky to try to prune as we go, b/c composite
955 # very tricky to try to prune as we go, b/c composite
955 # names can fool us. The pruning at the end is easy
956 # names can fool us. The pruning at the end is easy
956 # to do (or the caller can print a list with repeated
957 # to do (or the caller can print a list with repeated
957 # names if so desired.
958 # names if so desired.
958 names.append([token])
959 names.append([token])
959 elif token == '.':
960 elif token == '.':
960 name_cont = True
961 name_cont = True
961 elif token_type == tokenize.NEWLINE:
962 elif token_type == tokenize.NEWLINE:
962 break
963 break
963
964
964 except (IndexError, UnicodeDecodeError, SyntaxError):
965 except (IndexError, UnicodeDecodeError, SyntaxError):
965 # signals exit of tokenizer
966 # signals exit of tokenizer
966 # SyntaxError can occur if the file is not actually Python
967 # SyntaxError can occur if the file is not actually Python
967 # - see gh-6300
968 # - see gh-6300
968 pass
969 pass
969 except tokenize.TokenError as msg:
970 except tokenize.TokenError as msg:
970 _m = ("An unexpected error occurred while tokenizing input\n"
971 _m = ("An unexpected error occurred while tokenizing input\n"
971 "The following traceback may be corrupted or invalid\n"
972 "The following traceback may be corrupted or invalid\n"
972 "The error message is: %s\n" % msg)
973 "The error message is: %s\n" % msg)
973 error(_m)
974 error(_m)
974
975
975 # Join composite names (e.g. "dict.fromkeys")
976 # Join composite names (e.g. "dict.fromkeys")
976 names = ['.'.join(n) for n in names]
977 names = ['.'.join(n) for n in names]
977 # prune names list of duplicates, but keep the right order
978 # prune names list of duplicates, but keep the right order
978 unique_names = uniq_stable(names)
979 unique_names = uniq_stable(names)
979
980
980 # Start loop over vars
981 # Start loop over vars
981 lvals = []
982 lvals = []
982 if self.include_vars:
983 if self.include_vars:
983 for name_full in unique_names:
984 for name_full in unique_names:
984 name_base = name_full.split('.', 1)[0]
985 name_base = name_full.split('.', 1)[0]
985 if name_base in frame.f_code.co_varnames:
986 if name_base in frame.f_code.co_varnames:
986 if name_base in locals:
987 if name_base in locals:
987 try:
988 try:
988 value = repr(eval(name_full, locals))
989 value = repr(eval(name_full, locals))
989 except:
990 except:
990 value = undefined
991 value = undefined
991 else:
992 else:
992 value = undefined
993 value = undefined
993 name = tpl_local_var % name_full
994 name = tpl_local_var % name_full
994 else:
995 else:
995 if name_base in frame.f_globals:
996 if name_base in frame.f_globals:
996 try:
997 try:
997 value = repr(eval(name_full, frame.f_globals))
998 value = repr(eval(name_full, frame.f_globals))
998 except:
999 except:
999 value = undefined
1000 value = undefined
1000 else:
1001 else:
1001 value = undefined
1002 value = undefined
1002 name = tpl_global_var % name_full
1003 name = tpl_global_var % name_full
1003 lvals.append(tpl_name_val % (name, value))
1004 lvals.append(tpl_name_val % (name, value))
1004 if lvals:
1005 if lvals:
1005 lvals = '%s%s' % (indent, em_normal.join(lvals))
1006 lvals = '%s%s' % (indent, em_normal.join(lvals))
1006 else:
1007 else:
1007 lvals = ''
1008 lvals = ''
1008
1009
1009 level = '%s %s\n' % (link, call)
1010 level = '%s %s\n' % (link, call)
1010
1011
1011 if index is None:
1012 if index is None:
1012 return level
1013 return level
1013 else:
1014 else:
1014 return '%s%s' % (level, ''.join(
1015 return '%s%s' % (level, ''.join(
1015 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1016 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1016 col_scheme)))
1017 col_scheme)))
1017
1018
1018 def prepare_chained_exception_message(self, cause):
1019 def prepare_chained_exception_message(self, cause):
1019 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1020 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1020 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1021 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1021
1022
1022 if cause:
1023 if cause:
1023 message = [[direct_cause]]
1024 message = [[direct_cause]]
1024 else:
1025 else:
1025 message = [[exception_during_handling]]
1026 message = [[exception_during_handling]]
1026 return message
1027 return message
1027
1028
1028 def prepare_header(self, etype, long_version=False):
1029 def prepare_header(self, etype, long_version=False):
1029 colors = self.Colors # just a shorthand + quicker name lookup
1030 colors = self.Colors # just a shorthand + quicker name lookup
1030 colorsnormal = colors.Normal # used a lot
1031 colorsnormal = colors.Normal # used a lot
1031 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1032 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1033 width = min(75, get_terminal_size()[0])
1032 if long_version:
1034 if long_version:
1033 # Header with the exception type, python version, and date
1035 # Header with the exception type, python version, and date
1034 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1036 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1035 date = time.ctime(time.time())
1037 date = time.ctime(time.time())
1036
1038
1037 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
1039 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1038 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
1040 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1039 pyver, date.rjust(75) )
1041 pyver, date.rjust(width) )
1040 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1042 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1041 "\ncalls leading up to the error, with the most recent (innermost) call last."
1043 "\ncalls leading up to the error, with the most recent (innermost) call last."
1042 else:
1044 else:
1043 # Simplified header
1045 # Simplified header
1044 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1046 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1045 rjust(75 - len(str(etype))) )
1047 rjust(width - len(str(etype))) )
1046
1048
1047 return head
1049 return head
1048
1050
1049 def format_exception(self, etype, evalue):
1051 def format_exception(self, etype, evalue):
1050 colors = self.Colors # just a shorthand + quicker name lookup
1052 colors = self.Colors # just a shorthand + quicker name lookup
1051 colorsnormal = colors.Normal # used a lot
1053 colorsnormal = colors.Normal # used a lot
1052 indent = ' ' * INDENT_SIZE
1054 indent = ' ' * INDENT_SIZE
1053 # Get (safely) a string form of the exception info
1055 # Get (safely) a string form of the exception info
1054 try:
1056 try:
1055 etype_str, evalue_str = map(str, (etype, evalue))
1057 etype_str, evalue_str = map(str, (etype, evalue))
1056 except:
1058 except:
1057 # User exception is improperly defined.
1059 # User exception is improperly defined.
1058 etype, evalue = str, sys.exc_info()[:2]
1060 etype, evalue = str, sys.exc_info()[:2]
1059 etype_str, evalue_str = map(str, (etype, evalue))
1061 etype_str, evalue_str = map(str, (etype, evalue))
1060 # ... and format it
1062 # ... and format it
1061 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1063 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1062 colorsnormal, py3compat.cast_unicode(evalue_str))]
1064 colorsnormal, py3compat.cast_unicode(evalue_str))]
1063
1065
1064 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1066 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1065 try:
1067 try:
1066 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1068 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1067 except:
1069 except:
1068 # Every now and then, an object with funny internals blows up
1070 # Every now and then, an object with funny internals blows up
1069 # when dir() is called on it. We do the best we can to report
1071 # when dir() is called on it. We do the best we can to report
1070 # the problem and continue
1072 # the problem and continue
1071 _m = '%sException reporting error (object with broken dir())%s:'
1073 _m = '%sException reporting error (object with broken dir())%s:'
1072 exception.append(_m % (colors.excName, colorsnormal))
1074 exception.append(_m % (colors.excName, colorsnormal))
1073 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1075 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1074 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1076 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1075 colorsnormal, py3compat.cast_unicode(evalue_str)))
1077 colorsnormal, py3compat.cast_unicode(evalue_str)))
1076 names = []
1078 names = []
1077 for name in names:
1079 for name in names:
1078 value = text_repr(getattr(evalue, name))
1080 value = text_repr(getattr(evalue, name))
1079 exception.append('\n%s%s = %s' % (indent, name, value))
1081 exception.append('\n%s%s = %s' % (indent, name, value))
1080
1082
1081 return exception
1083 return exception
1082
1084
1083 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1085 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1084 """Formats the header, traceback and exception message for a single exception.
1086 """Formats the header, traceback and exception message for a single exception.
1085
1087
1086 This may be called multiple times by Python 3 exception chaining
1088 This may be called multiple times by Python 3 exception chaining
1087 (PEP 3134).
1089 (PEP 3134).
1088 """
1090 """
1089 # some locals
1091 # some locals
1090 orig_etype = etype
1092 orig_etype = etype
1091 try:
1093 try:
1092 etype = etype.__name__
1094 etype = etype.__name__
1093 except AttributeError:
1095 except AttributeError:
1094 pass
1096 pass
1095
1097
1096 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1098 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1097 head = self.prepare_header(etype, self.long_header)
1099 head = self.prepare_header(etype, self.long_header)
1098 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1100 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1099
1101
1100 if records is None:
1102 if records is None:
1101 return ""
1103 return ""
1102
1104
1103 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1105 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1104
1106
1105 frames = self.format_records(records, last_unique, recursion_repeat)
1107 frames = self.format_records(records, last_unique, recursion_repeat)
1106
1108
1107 formatted_exception = self.format_exception(etype, evalue)
1109 formatted_exception = self.format_exception(etype, evalue)
1108 if records:
1110 if records:
1109 filepath, lnum = records[-1][1:3]
1111 filepath, lnum = records[-1][1:3]
1110 filepath = os.path.abspath(filepath)
1112 filepath = os.path.abspath(filepath)
1111 ipinst = get_ipython()
1113 ipinst = get_ipython()
1112 if ipinst is not None:
1114 if ipinst is not None:
1113 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1115 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1114
1116
1115 return [[head] + frames + [''.join(formatted_exception[0])]]
1117 return [[head] + frames + [''.join(formatted_exception[0])]]
1116
1118
1117 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1119 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1118 try:
1120 try:
1119 # Try the default getinnerframes and Alex's: Alex's fixes some
1121 # Try the default getinnerframes and Alex's: Alex's fixes some
1120 # problems, but it generates empty tracebacks for console errors
1122 # problems, but it generates empty tracebacks for console errors
1121 # (5 blanks lines) where none should be returned.
1123 # (5 blanks lines) where none should be returned.
1122 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1124 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1123 except:
1125 except:
1124 # FIXME: I've been getting many crash reports from python 2.3
1126 # FIXME: I've been getting many crash reports from python 2.3
1125 # users, traceable to inspect.py. If I can find a small test-case
1127 # users, traceable to inspect.py. If I can find a small test-case
1126 # to reproduce this, I should either write a better workaround or
1128 # to reproduce this, I should either write a better workaround or
1127 # file a bug report against inspect (if that's the real problem).
1129 # file a bug report against inspect (if that's the real problem).
1128 # So far, I haven't been able to find an isolated example to
1130 # So far, I haven't been able to find an isolated example to
1129 # reproduce the problem.
1131 # reproduce the problem.
1130 inspect_error()
1132 inspect_error()
1131 traceback.print_exc(file=self.ostream)
1133 traceback.print_exc(file=self.ostream)
1132 info('\nUnfortunately, your original traceback can not be constructed.\n')
1134 info('\nUnfortunately, your original traceback can not be constructed.\n')
1133 return None
1135 return None
1134
1136
1135 def get_parts_of_chained_exception(self, evalue):
1137 def get_parts_of_chained_exception(self, evalue):
1136 def get_chained_exception(exception_value):
1138 def get_chained_exception(exception_value):
1137 cause = getattr(exception_value, '__cause__', None)
1139 cause = getattr(exception_value, '__cause__', None)
1138 if cause:
1140 if cause:
1139 return cause
1141 return cause
1140 if getattr(exception_value, '__suppress_context__', False):
1142 if getattr(exception_value, '__suppress_context__', False):
1141 return None
1143 return None
1142 return getattr(exception_value, '__context__', None)
1144 return getattr(exception_value, '__context__', None)
1143
1145
1144 chained_evalue = get_chained_exception(evalue)
1146 chained_evalue = get_chained_exception(evalue)
1145
1147
1146 if chained_evalue:
1148 if chained_evalue:
1147 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1149 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1148
1150
1149 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1151 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1150 number_of_lines_of_context=5):
1152 number_of_lines_of_context=5):
1151 """Return a nice text document describing the traceback."""
1153 """Return a nice text document describing the traceback."""
1152
1154
1153 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1155 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1154 tb_offset)
1156 tb_offset)
1155
1157
1156 colors = self.Colors # just a shorthand + quicker name lookup
1158 colors = self.Colors # just a shorthand + quicker name lookup
1157 colorsnormal = colors.Normal # used a lot
1159 colorsnormal = colors.Normal # used a lot
1158 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1160 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1159 structured_traceback_parts = [head]
1161 structured_traceback_parts = [head]
1160 if py3compat.PY3:
1162 if py3compat.PY3:
1161 chained_exceptions_tb_offset = 0
1163 chained_exceptions_tb_offset = 0
1162 lines_of_context = 3
1164 lines_of_context = 3
1163 formatted_exceptions = formatted_exception
1165 formatted_exceptions = formatted_exception
1164 exception = self.get_parts_of_chained_exception(evalue)
1166 exception = self.get_parts_of_chained_exception(evalue)
1165 if exception:
1167 if exception:
1166 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1168 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1167 etype, evalue, etb = exception
1169 etype, evalue, etb = exception
1168 else:
1170 else:
1169 evalue = None
1171 evalue = None
1170 chained_exc_ids = set()
1172 chained_exc_ids = set()
1171 while evalue:
1173 while evalue:
1172 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1174 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1173 chained_exceptions_tb_offset)
1175 chained_exceptions_tb_offset)
1174 exception = self.get_parts_of_chained_exception(evalue)
1176 exception = self.get_parts_of_chained_exception(evalue)
1175
1177
1176 if exception and not id(exception[1]) in chained_exc_ids:
1178 if exception and not id(exception[1]) in chained_exc_ids:
1177 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1179 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1178 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1180 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1179 etype, evalue, etb = exception
1181 etype, evalue, etb = exception
1180 else:
1182 else:
1181 evalue = None
1183 evalue = None
1182
1184
1183 # we want to see exceptions in a reversed order:
1185 # we want to see exceptions in a reversed order:
1184 # the first exception should be on top
1186 # the first exception should be on top
1185 for formatted_exception in reversed(formatted_exceptions):
1187 for formatted_exception in reversed(formatted_exceptions):
1186 structured_traceback_parts += formatted_exception
1188 structured_traceback_parts += formatted_exception
1187 else:
1189 else:
1188 structured_traceback_parts += formatted_exception[0]
1190 structured_traceback_parts += formatted_exception[0]
1189
1191
1190 return structured_traceback_parts
1192 return structured_traceback_parts
1191
1193
1192 def debugger(self, force=False):
1194 def debugger(self, force=False):
1193 """Call up the pdb debugger if desired, always clean up the tb
1195 """Call up the pdb debugger if desired, always clean up the tb
1194 reference.
1196 reference.
1195
1197
1196 Keywords:
1198 Keywords:
1197
1199
1198 - force(False): by default, this routine checks the instance call_pdb
1200 - force(False): by default, this routine checks the instance call_pdb
1199 flag and does not actually invoke the debugger if the flag is false.
1201 flag and does not actually invoke the debugger if the flag is false.
1200 The 'force' option forces the debugger to activate even if the flag
1202 The 'force' option forces the debugger to activate even if the flag
1201 is false.
1203 is false.
1202
1204
1203 If the call_pdb flag is set, the pdb interactive debugger is
1205 If the call_pdb flag is set, the pdb interactive debugger is
1204 invoked. In all cases, the self.tb reference to the current traceback
1206 invoked. In all cases, the self.tb reference to the current traceback
1205 is deleted to prevent lingering references which hamper memory
1207 is deleted to prevent lingering references which hamper memory
1206 management.
1208 management.
1207
1209
1208 Note that each call to pdb() does an 'import readline', so if your app
1210 Note that each call to pdb() does an 'import readline', so if your app
1209 requires a special setup for the readline completers, you'll have to
1211 requires a special setup for the readline completers, you'll have to
1210 fix that by hand after invoking the exception handler."""
1212 fix that by hand after invoking the exception handler."""
1211
1213
1212 if force or self.call_pdb:
1214 if force or self.call_pdb:
1213 if self.pdb is None:
1215 if self.pdb is None:
1214 self.pdb = debugger.Pdb(
1216 self.pdb = debugger.Pdb(
1215 self.color_scheme_table.active_scheme_name)
1217 self.color_scheme_table.active_scheme_name)
1216 # the system displayhook may have changed, restore the original
1218 # the system displayhook may have changed, restore the original
1217 # for pdb
1219 # for pdb
1218 display_trap = DisplayTrap(hook=sys.__displayhook__)
1220 display_trap = DisplayTrap(hook=sys.__displayhook__)
1219 with display_trap:
1221 with display_trap:
1220 self.pdb.reset()
1222 self.pdb.reset()
1221 # Find the right frame so we don't pop up inside ipython itself
1223 # Find the right frame so we don't pop up inside ipython itself
1222 if hasattr(self, 'tb') and self.tb is not None:
1224 if hasattr(self, 'tb') and self.tb is not None:
1223 etb = self.tb
1225 etb = self.tb
1224 else:
1226 else:
1225 etb = self.tb = sys.last_traceback
1227 etb = self.tb = sys.last_traceback
1226 while self.tb is not None and self.tb.tb_next is not None:
1228 while self.tb is not None and self.tb.tb_next is not None:
1227 self.tb = self.tb.tb_next
1229 self.tb = self.tb.tb_next
1228 if etb and etb.tb_next:
1230 if etb and etb.tb_next:
1229 etb = etb.tb_next
1231 etb = etb.tb_next
1230 self.pdb.botframe = etb.tb_frame
1232 self.pdb.botframe = etb.tb_frame
1231 self.pdb.interaction(self.tb.tb_frame, self.tb)
1233 self.pdb.interaction(self.tb.tb_frame, self.tb)
1232
1234
1233 if hasattr(self, 'tb'):
1235 if hasattr(self, 'tb'):
1234 del self.tb
1236 del self.tb
1235
1237
1236 def handler(self, info=None):
1238 def handler(self, info=None):
1237 (etype, evalue, etb) = info or sys.exc_info()
1239 (etype, evalue, etb) = info or sys.exc_info()
1238 self.tb = etb
1240 self.tb = etb
1239 ostream = self.ostream
1241 ostream = self.ostream
1240 ostream.flush()
1242 ostream.flush()
1241 ostream.write(self.text(etype, evalue, etb))
1243 ostream.write(self.text(etype, evalue, etb))
1242 ostream.write('\n')
1244 ostream.write('\n')
1243 ostream.flush()
1245 ostream.flush()
1244
1246
1245 # Changed so an instance can just be called as VerboseTB_inst() and print
1247 # Changed so an instance can just be called as VerboseTB_inst() and print
1246 # out the right info on its own.
1248 # out the right info on its own.
1247 def __call__(self, etype=None, evalue=None, etb=None):
1249 def __call__(self, etype=None, evalue=None, etb=None):
1248 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1250 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1249 if etb is None:
1251 if etb is None:
1250 self.handler()
1252 self.handler()
1251 else:
1253 else:
1252 self.handler((etype, evalue, etb))
1254 self.handler((etype, evalue, etb))
1253 try:
1255 try:
1254 self.debugger()
1256 self.debugger()
1255 except KeyboardInterrupt:
1257 except KeyboardInterrupt:
1256 print("\nKeyboardInterrupt")
1258 print("\nKeyboardInterrupt")
1257
1259
1258
1260
1259 #----------------------------------------------------------------------------
1261 #----------------------------------------------------------------------------
1260 class FormattedTB(VerboseTB, ListTB):
1262 class FormattedTB(VerboseTB, ListTB):
1261 """Subclass ListTB but allow calling with a traceback.
1263 """Subclass ListTB but allow calling with a traceback.
1262
1264
1263 It can thus be used as a sys.excepthook for Python > 2.1.
1265 It can thus be used as a sys.excepthook for Python > 2.1.
1264
1266
1265 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1267 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1266
1268
1267 Allows a tb_offset to be specified. This is useful for situations where
1269 Allows a tb_offset to be specified. This is useful for situations where
1268 one needs to remove a number of topmost frames from the traceback (such as
1270 one needs to remove a number of topmost frames from the traceback (such as
1269 occurs with python programs that themselves execute other python code,
1271 occurs with python programs that themselves execute other python code,
1270 like Python shells). """
1272 like Python shells). """
1271
1273
1272 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1274 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1273 ostream=None,
1275 ostream=None,
1274 tb_offset=0, long_header=False, include_vars=False,
1276 tb_offset=0, long_header=False, include_vars=False,
1275 check_cache=None):
1277 check_cache=None):
1276
1278
1277 # NEVER change the order of this list. Put new modes at the end:
1279 # NEVER change the order of this list. Put new modes at the end:
1278 self.valid_modes = ['Plain', 'Context', 'Verbose']
1280 self.valid_modes = ['Plain', 'Context', 'Verbose']
1279 self.verbose_modes = self.valid_modes[1:3]
1281 self.verbose_modes = self.valid_modes[1:3]
1280
1282
1281 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1283 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1282 ostream=ostream, tb_offset=tb_offset,
1284 ostream=ostream, tb_offset=tb_offset,
1283 long_header=long_header, include_vars=include_vars,
1285 long_header=long_header, include_vars=include_vars,
1284 check_cache=check_cache)
1286 check_cache=check_cache)
1285
1287
1286 # Different types of tracebacks are joined with different separators to
1288 # Different types of tracebacks are joined with different separators to
1287 # form a single string. They are taken from this dict
1289 # form a single string. They are taken from this dict
1288 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1290 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1289 # set_mode also sets the tb_join_char attribute
1291 # set_mode also sets the tb_join_char attribute
1290 self.set_mode(mode)
1292 self.set_mode(mode)
1291
1293
1292 def _extract_tb(self, tb):
1294 def _extract_tb(self, tb):
1293 if tb:
1295 if tb:
1294 return traceback.extract_tb(tb)
1296 return traceback.extract_tb(tb)
1295 else:
1297 else:
1296 return None
1298 return None
1297
1299
1298 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1300 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1299 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1301 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1300 mode = self.mode
1302 mode = self.mode
1301 if mode in self.verbose_modes:
1303 if mode in self.verbose_modes:
1302 # Verbose modes need a full traceback
1304 # Verbose modes need a full traceback
1303 return VerboseTB.structured_traceback(
1305 return VerboseTB.structured_traceback(
1304 self, etype, value, tb, tb_offset, number_of_lines_of_context
1306 self, etype, value, tb, tb_offset, number_of_lines_of_context
1305 )
1307 )
1306 else:
1308 else:
1307 # We must check the source cache because otherwise we can print
1309 # We must check the source cache because otherwise we can print
1308 # out-of-date source code.
1310 # out-of-date source code.
1309 self.check_cache()
1311 self.check_cache()
1310 # Now we can extract and format the exception
1312 # Now we can extract and format the exception
1311 elist = self._extract_tb(tb)
1313 elist = self._extract_tb(tb)
1312 return ListTB.structured_traceback(
1314 return ListTB.structured_traceback(
1313 self, etype, value, elist, tb_offset, number_of_lines_of_context
1315 self, etype, value, elist, tb_offset, number_of_lines_of_context
1314 )
1316 )
1315
1317
1316 def stb2text(self, stb):
1318 def stb2text(self, stb):
1317 """Convert a structured traceback (a list) to a string."""
1319 """Convert a structured traceback (a list) to a string."""
1318 return self.tb_join_char.join(stb)
1320 return self.tb_join_char.join(stb)
1319
1321
1320
1322
1321 def set_mode(self, mode=None):
1323 def set_mode(self, mode=None):
1322 """Switch to the desired mode.
1324 """Switch to the desired mode.
1323
1325
1324 If mode is not specified, cycles through the available modes."""
1326 If mode is not specified, cycles through the available modes."""
1325
1327
1326 if not mode:
1328 if not mode:
1327 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1329 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1328 len(self.valid_modes)
1330 len(self.valid_modes)
1329 self.mode = self.valid_modes[new_idx]
1331 self.mode = self.valid_modes[new_idx]
1330 elif mode not in self.valid_modes:
1332 elif mode not in self.valid_modes:
1331 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1333 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1332 'Valid modes: ' + str(self.valid_modes))
1334 'Valid modes: ' + str(self.valid_modes))
1333 else:
1335 else:
1334 self.mode = mode
1336 self.mode = mode
1335 # include variable details only in 'Verbose' mode
1337 # include variable details only in 'Verbose' mode
1336 self.include_vars = (self.mode == self.valid_modes[2])
1338 self.include_vars = (self.mode == self.valid_modes[2])
1337 # Set the join character for generating text tracebacks
1339 # Set the join character for generating text tracebacks
1338 self.tb_join_char = self._join_chars[self.mode]
1340 self.tb_join_char = self._join_chars[self.mode]
1339
1341
1340 # some convenient shortcuts
1342 # some convenient shortcuts
1341 def plain(self):
1343 def plain(self):
1342 self.set_mode(self.valid_modes[0])
1344 self.set_mode(self.valid_modes[0])
1343
1345
1344 def context(self):
1346 def context(self):
1345 self.set_mode(self.valid_modes[1])
1347 self.set_mode(self.valid_modes[1])
1346
1348
1347 def verbose(self):
1349 def verbose(self):
1348 self.set_mode(self.valid_modes[2])
1350 self.set_mode(self.valid_modes[2])
1349
1351
1350
1352
1351 #----------------------------------------------------------------------------
1353 #----------------------------------------------------------------------------
1352 class AutoFormattedTB(FormattedTB):
1354 class AutoFormattedTB(FormattedTB):
1353 """A traceback printer which can be called on the fly.
1355 """A traceback printer which can be called on the fly.
1354
1356
1355 It will find out about exceptions by itself.
1357 It will find out about exceptions by itself.
1356
1358
1357 A brief example::
1359 A brief example::
1358
1360
1359 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1361 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1360 try:
1362 try:
1361 ...
1363 ...
1362 except:
1364 except:
1363 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1365 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1364 """
1366 """
1365
1367
1366 def __call__(self, etype=None, evalue=None, etb=None,
1368 def __call__(self, etype=None, evalue=None, etb=None,
1367 out=None, tb_offset=None):
1369 out=None, tb_offset=None):
1368 """Print out a formatted exception traceback.
1370 """Print out a formatted exception traceback.
1369
1371
1370 Optional arguments:
1372 Optional arguments:
1371 - out: an open file-like object to direct output to.
1373 - out: an open file-like object to direct output to.
1372
1374
1373 - tb_offset: the number of frames to skip over in the stack, on a
1375 - tb_offset: the number of frames to skip over in the stack, on a
1374 per-call basis (this overrides temporarily the instance's tb_offset
1376 per-call basis (this overrides temporarily the instance's tb_offset
1375 given at initialization time. """
1377 given at initialization time. """
1376
1378
1377 if out is None:
1379 if out is None:
1378 out = self.ostream
1380 out = self.ostream
1379 out.flush()
1381 out.flush()
1380 out.write(self.text(etype, evalue, etb, tb_offset))
1382 out.write(self.text(etype, evalue, etb, tb_offset))
1381 out.write('\n')
1383 out.write('\n')
1382 out.flush()
1384 out.flush()
1383 # FIXME: we should remove the auto pdb behavior from here and leave
1385 # FIXME: we should remove the auto pdb behavior from here and leave
1384 # that to the clients.
1386 # that to the clients.
1385 try:
1387 try:
1386 self.debugger()
1388 self.debugger()
1387 except KeyboardInterrupt:
1389 except KeyboardInterrupt:
1388 print("\nKeyboardInterrupt")
1390 print("\nKeyboardInterrupt")
1389
1391
1390 def structured_traceback(self, etype=None, value=None, tb=None,
1392 def structured_traceback(self, etype=None, value=None, tb=None,
1391 tb_offset=None, number_of_lines_of_context=5):
1393 tb_offset=None, number_of_lines_of_context=5):
1392 if etype is None:
1394 if etype is None:
1393 etype, value, tb = sys.exc_info()
1395 etype, value, tb = sys.exc_info()
1394 self.tb = tb
1396 self.tb = tb
1395 return FormattedTB.structured_traceback(
1397 return FormattedTB.structured_traceback(
1396 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1398 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1397
1399
1398
1400
1399 #---------------------------------------------------------------------------
1401 #---------------------------------------------------------------------------
1400
1402
1401 # A simple class to preserve Nathan's original functionality.
1403 # A simple class to preserve Nathan's original functionality.
1402 class ColorTB(FormattedTB):
1404 class ColorTB(FormattedTB):
1403 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1405 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1404
1406
1405 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1407 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1406 FormattedTB.__init__(self, color_scheme=color_scheme,
1408 FormattedTB.__init__(self, color_scheme=color_scheme,
1407 call_pdb=call_pdb, **kwargs)
1409 call_pdb=call_pdb, **kwargs)
1408
1410
1409
1411
1410 class SyntaxTB(ListTB):
1412 class SyntaxTB(ListTB):
1411 """Extension which holds some state: the last exception value"""
1413 """Extension which holds some state: the last exception value"""
1412
1414
1413 def __init__(self, color_scheme='NoColor'):
1415 def __init__(self, color_scheme='NoColor'):
1414 ListTB.__init__(self, color_scheme)
1416 ListTB.__init__(self, color_scheme)
1415 self.last_syntax_error = None
1417 self.last_syntax_error = None
1416
1418
1417 def __call__(self, etype, value, elist):
1419 def __call__(self, etype, value, elist):
1418 self.last_syntax_error = value
1420 self.last_syntax_error = value
1419
1421
1420 ListTB.__call__(self, etype, value, elist)
1422 ListTB.__call__(self, etype, value, elist)
1421
1423
1422 def structured_traceback(self, etype, value, elist, tb_offset=None,
1424 def structured_traceback(self, etype, value, elist, tb_offset=None,
1423 context=5):
1425 context=5):
1424 # If the source file has been edited, the line in the syntax error can
1426 # If the source file has been edited, the line in the syntax error can
1425 # be wrong (retrieved from an outdated cache). This replaces it with
1427 # be wrong (retrieved from an outdated cache). This replaces it with
1426 # the current value.
1428 # the current value.
1427 if isinstance(value, SyntaxError) \
1429 if isinstance(value, SyntaxError) \
1428 and isinstance(value.filename, py3compat.string_types) \
1430 and isinstance(value.filename, py3compat.string_types) \
1429 and isinstance(value.lineno, int):
1431 and isinstance(value.lineno, int):
1430 linecache.checkcache(value.filename)
1432 linecache.checkcache(value.filename)
1431 newtext = ulinecache.getline(value.filename, value.lineno)
1433 newtext = ulinecache.getline(value.filename, value.lineno)
1432 if newtext:
1434 if newtext:
1433 value.text = newtext
1435 value.text = newtext
1434 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1436 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1435 tb_offset=tb_offset, context=context)
1437 tb_offset=tb_offset, context=context)
1436
1438
1437 def clear_err_state(self):
1439 def clear_err_state(self):
1438 """Return the current error state and clear it"""
1440 """Return the current error state and clear it"""
1439 e = self.last_syntax_error
1441 e = self.last_syntax_error
1440 self.last_syntax_error = None
1442 self.last_syntax_error = None
1441 return e
1443 return e
1442
1444
1443 def stb2text(self, stb):
1445 def stb2text(self, stb):
1444 """Convert a structured traceback (a list) to a string."""
1446 """Convert a structured traceback (a list) to a string."""
1445 return ''.join(stb)
1447 return ''.join(stb)
1446
1448
1447
1449
1448 # some internal-use functions
1450 # some internal-use functions
1449 def text_repr(value):
1451 def text_repr(value):
1450 """Hopefully pretty robust repr equivalent."""
1452 """Hopefully pretty robust repr equivalent."""
1451 # this is pretty horrible but should always return *something*
1453 # this is pretty horrible but should always return *something*
1452 try:
1454 try:
1453 return pydoc.text.repr(value)
1455 return pydoc.text.repr(value)
1454 except KeyboardInterrupt:
1456 except KeyboardInterrupt:
1455 raise
1457 raise
1456 except:
1458 except:
1457 try:
1459 try:
1458 return repr(value)
1460 return repr(value)
1459 except KeyboardInterrupt:
1461 except KeyboardInterrupt:
1460 raise
1462 raise
1461 except:
1463 except:
1462 try:
1464 try:
1463 # all still in an except block so we catch
1465 # all still in an except block so we catch
1464 # getattr raising
1466 # getattr raising
1465 name = getattr(value, '__name__', None)
1467 name = getattr(value, '__name__', None)
1466 if name:
1468 if name:
1467 # ick, recursion
1469 # ick, recursion
1468 return text_repr(name)
1470 return text_repr(name)
1469 klass = getattr(value, '__class__', None)
1471 klass = getattr(value, '__class__', None)
1470 if klass:
1472 if klass:
1471 return '%s instance' % text_repr(klass)
1473 return '%s instance' % text_repr(klass)
1472 except KeyboardInterrupt:
1474 except KeyboardInterrupt:
1473 raise
1475 raise
1474 except:
1476 except:
1475 return 'UNRECOVERABLE REPR FAILURE'
1477 return 'UNRECOVERABLE REPR FAILURE'
1476
1478
1477
1479
1478 def eqrepr(value, repr=text_repr):
1480 def eqrepr(value, repr=text_repr):
1479 return '=%s' % repr(value)
1481 return '=%s' % repr(value)
1480
1482
1481
1483
1482 def nullrepr(value, repr=text_repr):
1484 def nullrepr(value, repr=text_repr):
1483 return ''
1485 return ''
@@ -1,156 +1,125 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with terminals.
3 Utilities for working with terminals.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian E. Granger
7 * Brian E. Granger
8 * Fernando Perez
8 * Fernando Perez
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import struct
24 import struct
25 import sys
25 import sys
26 import warnings
26 import warnings
27 import backports.shutil_get_terminal_size
27
28
28 from . import py3compat
29 from . import py3compat
29
30
30 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
31 # Code
32 # Code
32 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
33
34
34 # This variable is part of the expected API of the module:
35 # This variable is part of the expected API of the module:
35 ignore_termtitle = True
36 ignore_termtitle = True
36
37
37
38
38
39
39 if os.name == 'posix':
40 if os.name == 'posix':
40 def _term_clear():
41 def _term_clear():
41 os.system('clear')
42 os.system('clear')
42 elif sys.platform == 'win32':
43 elif sys.platform == 'win32':
43 def _term_clear():
44 def _term_clear():
44 os.system('cls')
45 os.system('cls')
45 else:
46 else:
46 def _term_clear():
47 def _term_clear():
47 pass
48 pass
48
49
49
50
50
51
51 def toggle_set_term_title(val):
52 def toggle_set_term_title(val):
52 """Control whether set_term_title is active or not.
53 """Control whether set_term_title is active or not.
53
54
54 set_term_title() allows writing to the console titlebar. In embedded
55 set_term_title() allows writing to the console titlebar. In embedded
55 widgets this can cause problems, so this call can be used to toggle it on
56 widgets this can cause problems, so this call can be used to toggle it on
56 or off as needed.
57 or off as needed.
57
58
58 The default state of the module is for the function to be disabled.
59 The default state of the module is for the function to be disabled.
59
60
60 Parameters
61 Parameters
61 ----------
62 ----------
62 val : bool
63 val : bool
63 If True, set_term_title() actually writes to the terminal (using the
64 If True, set_term_title() actually writes to the terminal (using the
64 appropriate platform-specific module). If False, it is a no-op.
65 appropriate platform-specific module). If False, it is a no-op.
65 """
66 """
66 global ignore_termtitle
67 global ignore_termtitle
67 ignore_termtitle = not(val)
68 ignore_termtitle = not(val)
68
69
69
70
70 def _set_term_title(*args,**kw):
71 def _set_term_title(*args,**kw):
71 """Dummy no-op."""
72 """Dummy no-op."""
72 pass
73 pass
73
74
74
75
75 def _set_term_title_xterm(title):
76 def _set_term_title_xterm(title):
76 """ Change virtual terminal title in xterm-workalikes """
77 """ Change virtual terminal title in xterm-workalikes """
77 sys.stdout.write('\033]0;%s\007' % title)
78 sys.stdout.write('\033]0;%s\007' % title)
78
79
79 if os.name == 'posix':
80 if os.name == 'posix':
80 TERM = os.environ.get('TERM','')
81 TERM = os.environ.get('TERM','')
81 if TERM.startswith('xterm'):
82 if TERM.startswith('xterm'):
82 _set_term_title = _set_term_title_xterm
83 _set_term_title = _set_term_title_xterm
83 elif sys.platform == 'win32':
84 elif sys.platform == 'win32':
84 try:
85 try:
85 import ctypes
86 import ctypes
86
87
87 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
88 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
88 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
89 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
89
90
90 def _set_term_title(title):
91 def _set_term_title(title):
91 """Set terminal title using ctypes to access the Win32 APIs."""
92 """Set terminal title using ctypes to access the Win32 APIs."""
92 SetConsoleTitleW(title)
93 SetConsoleTitleW(title)
93 except ImportError:
94 except ImportError:
94 def _set_term_title(title):
95 def _set_term_title(title):
95 """Set terminal title using the 'title' command."""
96 """Set terminal title using the 'title' command."""
96 global ignore_termtitle
97 global ignore_termtitle
97
98
98 try:
99 try:
99 # Cannot be on network share when issuing system commands
100 # Cannot be on network share when issuing system commands
100 curr = py3compat.getcwd()
101 curr = py3compat.getcwd()
101 os.chdir("C:")
102 os.chdir("C:")
102 ret = os.system("title " + title)
103 ret = os.system("title " + title)
103 finally:
104 finally:
104 os.chdir(curr)
105 os.chdir(curr)
105 if ret:
106 if ret:
106 # non-zero return code signals error, don't try again
107 # non-zero return code signals error, don't try again
107 ignore_termtitle = True
108 ignore_termtitle = True
108
109
109
110
110 def set_term_title(title):
111 def set_term_title(title):
111 """Set terminal title using the necessary platform-dependent calls."""
112 """Set terminal title using the necessary platform-dependent calls."""
112 if ignore_termtitle:
113 if ignore_termtitle:
113 return
114 return
114 _set_term_title(title)
115 _set_term_title(title)
115
116
116
117
117 def freeze_term_title():
118 def freeze_term_title():
118 warnings.warn("This function is deprecated, use toggle_set_term_title()")
119 warnings.warn("This function is deprecated, use toggle_set_term_title()")
119 global ignore_termtitle
120 global ignore_termtitle
120 ignore_termtitle = True
121 ignore_termtitle = True
121
122
122
123
123 if sys.platform == 'win32':
124 def get_terminal_size(defaultx=80, defaulty=25):
124 def get_terminal_size(defaultx=80, defaulty=25):
125 """Return size of current terminal console.
125 return backports.shutil_get_terminal_size.get_terminal_size((defaultx, defaulty))
126
127 This function try to determine actual size of current working
128 console window and return tuple (sizex, sizey) if success,
129 or default size (defaultx, defaulty) otherwise.
130
131 Dependencies: ctypes should be installed.
132
133 Author: Alexander Belchenko (e-mail: bialix AT ukr.net)
134 """
135 try:
136 import ctypes
137 except ImportError:
138 return defaultx, defaulty
139
140 h = ctypes.windll.kernel32.GetStdHandle(-11)
141 csbi = ctypes.create_string_buffer(22)
142 res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
143
144 if res:
145 (bufx, bufy, curx, cury, wattr,
146 left, top, right, bottom, maxx, maxy) = struct.unpack(
147 "hhhhHhhhhhh", csbi.raw)
148 sizex = right - left + 1
149 sizey = bottom - top + 1
150 return (sizex, sizey)
151 else:
152 return (defaultx, defaulty)
153 else:
154 def get_terminal_size(defaultx=80, defaulty=25):
155 return defaultx, defaulty
156
@@ -1,297 +1,298 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) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.rst, distributed with this software.
17 # The full license is in the file COPYING.rst, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Minimal Python version sanity check
21 # Minimal Python version sanity check
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 from __future__ import print_function
23 from __future__ import print_function
24
24
25 import sys
25 import sys
26
26
27 # This check is also made in IPython/__init__, don't forget to update both when
27 # This check is also made in IPython/__init__, don't forget to update both when
28 # changing Python version requirements.
28 # changing Python version requirements.
29 v = sys.version_info
29 v = sys.version_info
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 print(error, file=sys.stderr)
32 print(error, file=sys.stderr)
33 sys.exit(1)
33 sys.exit(1)
34
34
35 PY3 = (sys.version_info[0] >= 3)
35 PY3 = (sys.version_info[0] >= 3)
36
36
37 # At least we're on the python version we need, move on.
37 # At least we're on the python version we need, move on.
38
38
39 #-------------------------------------------------------------------------------
39 #-------------------------------------------------------------------------------
40 # Imports
40 # Imports
41 #-------------------------------------------------------------------------------
41 #-------------------------------------------------------------------------------
42
42
43 # Stdlib imports
43 # Stdlib imports
44 import os
44 import os
45
45
46 from glob import glob
46 from glob import glob
47
47
48 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
48 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 # update it when the contents of directories change.
49 # update it when the contents of directories change.
50 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
50 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51
51
52 from distutils.core import setup
52 from distutils.core import setup
53
53
54 # Our own imports
54 # Our own imports
55 from setupbase import target_update
55 from setupbase import target_update
56
56
57 from setupbase import (
57 from setupbase import (
58 setup_args,
58 setup_args,
59 find_packages,
59 find_packages,
60 find_package_data,
60 find_package_data,
61 check_package_data_first,
61 check_package_data_first,
62 find_entry_points,
62 find_entry_points,
63 build_scripts_entrypt,
63 build_scripts_entrypt,
64 find_data_files,
64 find_data_files,
65 git_prebuild,
65 git_prebuild,
66 install_symlinked,
66 install_symlinked,
67 install_lib_symlink,
67 install_lib_symlink,
68 install_scripts_for_symlink,
68 install_scripts_for_symlink,
69 unsymlink,
69 unsymlink,
70 )
70 )
71
71
72 isfile = os.path.isfile
72 isfile = os.path.isfile
73 pjoin = os.path.join
73 pjoin = os.path.join
74
74
75 #-------------------------------------------------------------------------------
75 #-------------------------------------------------------------------------------
76 # Handle OS specific things
76 # Handle OS specific things
77 #-------------------------------------------------------------------------------
77 #-------------------------------------------------------------------------------
78
78
79 if os.name in ('nt','dos'):
79 if os.name in ('nt','dos'):
80 os_name = 'windows'
80 os_name = 'windows'
81 else:
81 else:
82 os_name = os.name
82 os_name = os.name
83
83
84 # Under Windows, 'sdist' has not been supported. Now that the docs build with
84 # Under Windows, 'sdist' has not been supported. Now that the docs build with
85 # Sphinx it might work, but let's not turn it on until someone confirms that it
85 # Sphinx it might work, but let's not turn it on until someone confirms that it
86 # actually works.
86 # actually works.
87 if os_name == 'windows' and 'sdist' in sys.argv:
87 if os_name == 'windows' and 'sdist' in sys.argv:
88 print('The sdist command is not available under Windows. Exiting.')
88 print('The sdist command is not available under Windows. Exiting.')
89 sys.exit(1)
89 sys.exit(1)
90
90
91
91
92 #-------------------------------------------------------------------------------
92 #-------------------------------------------------------------------------------
93 # Things related to the IPython documentation
93 # Things related to the IPython documentation
94 #-------------------------------------------------------------------------------
94 #-------------------------------------------------------------------------------
95
95
96 # update the manuals when building a source dist
96 # update the manuals when building a source dist
97 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
97 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
98
98
99 # List of things to be updated. Each entry is a triplet of args for
99 # List of things to be updated. Each entry is a triplet of args for
100 # target_update()
100 # target_update()
101 to_update = [
101 to_update = [
102 ('docs/man/ipython.1.gz',
102 ('docs/man/ipython.1.gz',
103 ['docs/man/ipython.1'],
103 ['docs/man/ipython.1'],
104 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
104 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
105 ]
105 ]
106
106
107
107
108 [ target_update(*t) for t in to_update ]
108 [ target_update(*t) for t in to_update ]
109
109
110 #---------------------------------------------------------------------------
110 #---------------------------------------------------------------------------
111 # Find all the packages, package data, and data_files
111 # Find all the packages, package data, and data_files
112 #---------------------------------------------------------------------------
112 #---------------------------------------------------------------------------
113
113
114 packages = find_packages()
114 packages = find_packages()
115 package_data = find_package_data()
115 package_data = find_package_data()
116
116
117 data_files = find_data_files()
117 data_files = find_data_files()
118
118
119 setup_args['packages'] = packages
119 setup_args['packages'] = packages
120 setup_args['package_data'] = package_data
120 setup_args['package_data'] = package_data
121 setup_args['data_files'] = data_files
121 setup_args['data_files'] = data_files
122
122
123 #---------------------------------------------------------------------------
123 #---------------------------------------------------------------------------
124 # custom distutils commands
124 # custom distutils commands
125 #---------------------------------------------------------------------------
125 #---------------------------------------------------------------------------
126 # imports here, so they are after setuptools import if there was one
126 # imports here, so they are after setuptools import if there was one
127 from distutils.command.sdist import sdist
127 from distutils.command.sdist import sdist
128 from distutils.command.upload import upload
128 from distutils.command.upload import upload
129
129
130 class UploadWindowsInstallers(upload):
130 class UploadWindowsInstallers(upload):
131
131
132 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
132 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
133 user_options = upload.user_options + [
133 user_options = upload.user_options + [
134 ('files=', 'f', 'exe file (or glob) to upload')
134 ('files=', 'f', 'exe file (or glob) to upload')
135 ]
135 ]
136 def initialize_options(self):
136 def initialize_options(self):
137 upload.initialize_options(self)
137 upload.initialize_options(self)
138 meta = self.distribution.metadata
138 meta = self.distribution.metadata
139 base = '{name}-{version}'.format(
139 base = '{name}-{version}'.format(
140 name=meta.get_name(),
140 name=meta.get_name(),
141 version=meta.get_version()
141 version=meta.get_version()
142 )
142 )
143 self.files = os.path.join('dist', '%s.*.exe' % base)
143 self.files = os.path.join('dist', '%s.*.exe' % base)
144
144
145 def run(self):
145 def run(self):
146 for dist_file in glob(self.files):
146 for dist_file in glob(self.files):
147 self.upload_file('bdist_wininst', 'any', dist_file)
147 self.upload_file('bdist_wininst', 'any', dist_file)
148
148
149 setup_args['cmdclass'] = {
149 setup_args['cmdclass'] = {
150 'build_py': \
150 'build_py': \
151 check_package_data_first(git_prebuild('IPython')),
151 check_package_data_first(git_prebuild('IPython')),
152 'sdist' : git_prebuild('IPython', sdist),
152 'sdist' : git_prebuild('IPython', sdist),
153 'upload_wininst' : UploadWindowsInstallers,
153 'upload_wininst' : UploadWindowsInstallers,
154 'symlink': install_symlinked,
154 'symlink': install_symlinked,
155 'install_lib_symlink': install_lib_symlink,
155 'install_lib_symlink': install_lib_symlink,
156 'install_scripts_sym': install_scripts_for_symlink,
156 'install_scripts_sym': install_scripts_for_symlink,
157 'unsymlink': unsymlink,
157 'unsymlink': unsymlink,
158 }
158 }
159
159
160
160
161 #---------------------------------------------------------------------------
161 #---------------------------------------------------------------------------
162 # Handle scripts, dependencies, and setuptools specific things
162 # Handle scripts, dependencies, and setuptools specific things
163 #---------------------------------------------------------------------------
163 #---------------------------------------------------------------------------
164
164
165 # For some commands, use setuptools. Note that we do NOT list install here!
165 # For some commands, use setuptools. Note that we do NOT list install here!
166 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
166 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
167 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
167 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
168 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
168 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
169 'egg_info', 'easy_install', 'upload', 'install_egg_info',
169 'egg_info', 'easy_install', 'upload', 'install_egg_info',
170 ))
170 ))
171
171
172 if len(needs_setuptools.intersection(sys.argv)) > 0:
172 if len(needs_setuptools.intersection(sys.argv)) > 0:
173 import setuptools
173 import setuptools
174
174
175 # This dict is used for passing extra arguments that are setuptools
175 # This dict is used for passing extra arguments that are setuptools
176 # specific to setup
176 # specific to setup
177 setuptools_extra_args = {}
177 setuptools_extra_args = {}
178
178
179 # setuptools requirements
179 # setuptools requirements
180
180
181 extras_require = dict(
181 extras_require = dict(
182 parallel = ['ipyparallel'],
182 parallel = ['ipyparallel'],
183 qtconsole = ['qtconsole'],
183 qtconsole = ['qtconsole'],
184 doc = ['Sphinx>=1.3'],
184 doc = ['Sphinx>=1.3'],
185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments'],
185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments'],
186 terminal = [],
186 terminal = [],
187 kernel = ['ipykernel'],
187 kernel = ['ipykernel'],
188 nbformat = ['nbformat'],
188 nbformat = ['nbformat'],
189 notebook = ['notebook', 'ipywidgets'],
189 notebook = ['notebook', 'ipywidgets'],
190 nbconvert = ['nbconvert'],
190 nbconvert = ['nbconvert'],
191 )
191 )
192 install_requires = [
192 install_requires = [
193 'setuptools>=18.5',
193 'setuptools>=18.5',
194 'decorator',
194 'decorator',
195 'pickleshare',
195 'pickleshare',
196 'simplegeneric>0.8',
196 'simplegeneric>0.8',
197 'traitlets',
197 'traitlets',
198 'prompt_toolkit>=0.58',
198 'prompt_toolkit>=0.58',
199 'pygments',
199 'pygments',
200 'backports.shutil_get_terminal_size',
200 ]
201 ]
201
202
202 # Platform-specific dependencies:
203 # Platform-specific dependencies:
203 # This is the correct way to specify these,
204 # This is the correct way to specify these,
204 # but requires pip >= 6. pip < 6 ignores these.
205 # but requires pip >= 6. pip < 6 ignores these.
205
206
206 extras_require.update({
207 extras_require.update({
207 ':sys_platform != "win32"': ['pexpect'],
208 ':sys_platform != "win32"': ['pexpect'],
208 ':sys_platform == "darwin"': ['appnope'],
209 ':sys_platform == "darwin"': ['appnope'],
209 ':sys_platform == "win32"': ['colorama'],
210 ':sys_platform == "win32"': ['colorama'],
210 'test:python_version == "2.7"': ['mock'],
211 'test:python_version == "2.7"': ['mock'],
211 })
212 })
212 # FIXME: re-specify above platform dependencies for pip < 6
213 # FIXME: re-specify above platform dependencies for pip < 6
213 # These would result in non-portable bdists.
214 # These would result in non-portable bdists.
214 if not any(arg.startswith('bdist') for arg in sys.argv):
215 if not any(arg.startswith('bdist') for arg in sys.argv):
215 if sys.version_info < (3, 3):
216 if sys.version_info < (3, 3):
216 extras_require['test'].append('mock')
217 extras_require['test'].append('mock')
217
218
218 if sys.platform == 'darwin':
219 if sys.platform == 'darwin':
219 install_requires.extend(['appnope'])
220 install_requires.extend(['appnope'])
220 have_readline = False
221 have_readline = False
221 try:
222 try:
222 import readline
223 import readline
223 except ImportError:
224 except ImportError:
224 pass
225 pass
225 else:
226 else:
226 if 'libedit' not in readline.__doc__:
227 if 'libedit' not in readline.__doc__:
227 have_readline = True
228 have_readline = True
228 if not have_readline:
229 if not have_readline:
229 install_requires.extend(['gnureadline'])
230 install_requires.extend(['gnureadline'])
230
231
231 if sys.platform.startswith('win'):
232 if sys.platform.startswith('win'):
232 extras_require['terminal'].append('pyreadline>=2.0')
233 extras_require['terminal'].append('pyreadline>=2.0')
233 else:
234 else:
234 install_requires.append('pexpect')
235 install_requires.append('pexpect')
235
236
236 # workaround pypa/setuptools#147, where setuptools misspells
237 # workaround pypa/setuptools#147, where setuptools misspells
237 # platform_python_implementation as python_implementation
238 # platform_python_implementation as python_implementation
238 if 'setuptools' in sys.modules:
239 if 'setuptools' in sys.modules:
239 for key in list(extras_require):
240 for key in list(extras_require):
240 if 'platform_python_implementation' in key:
241 if 'platform_python_implementation' in key:
241 new_key = key.replace('platform_python_implementation', 'python_implementation')
242 new_key = key.replace('platform_python_implementation', 'python_implementation')
242 extras_require[new_key] = extras_require.pop(key)
243 extras_require[new_key] = extras_require.pop(key)
243
244
244 everything = set()
245 everything = set()
245 for key, deps in extras_require.items():
246 for key, deps in extras_require.items():
246 if ':' not in key:
247 if ':' not in key:
247 everything.update(deps)
248 everything.update(deps)
248 extras_require['all'] = everything
249 extras_require['all'] = everything
249
250
250 if 'setuptools' in sys.modules:
251 if 'setuptools' in sys.modules:
251 setuptools_extra_args['zip_safe'] = False
252 setuptools_extra_args['zip_safe'] = False
252 setuptools_extra_args['entry_points'] = {
253 setuptools_extra_args['entry_points'] = {
253 'console_scripts': find_entry_points(),
254 'console_scripts': find_entry_points(),
254 'pygments.lexers': [
255 'pygments.lexers': [
255 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
256 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
256 'ipython = IPython.lib.lexers:IPythonLexer',
257 'ipython = IPython.lib.lexers:IPythonLexer',
257 'ipython3 = IPython.lib.lexers:IPython3Lexer',
258 'ipython3 = IPython.lib.lexers:IPython3Lexer',
258 ],
259 ],
259 }
260 }
260 setup_args['extras_require'] = extras_require
261 setup_args['extras_require'] = extras_require
261 requires = setup_args['install_requires'] = install_requires
262 requires = setup_args['install_requires'] = install_requires
262
263
263 # Script to be run by the windows binary installer after the default setup
264 # Script to be run by the windows binary installer after the default setup
264 # routine, to add shortcuts and similar windows-only things. Windows
265 # routine, to add shortcuts and similar windows-only things. Windows
265 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
266 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
266 # doesn't find them.
267 # doesn't find them.
267 if 'bdist_wininst' in sys.argv:
268 if 'bdist_wininst' in sys.argv:
268 if len(sys.argv) > 2 and \
269 if len(sys.argv) > 2 and \
269 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
270 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
270 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
271 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
271 sys.exit(1)
272 sys.exit(1)
272 setup_args['data_files'].append(
273 setup_args['data_files'].append(
273 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
274 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
274 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
275 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
275 setup_args['options'] = {"bdist_wininst":
276 setup_args['options'] = {"bdist_wininst":
276 {"install_script":
277 {"install_script":
277 "ipython_win_post_install.py"}}
278 "ipython_win_post_install.py"}}
278
279
279 else:
280 else:
280 # scripts has to be a non-empty list, or install_scripts isn't called
281 # scripts has to be a non-empty list, or install_scripts isn't called
281 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
282 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
282
283
283 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
284 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
284
285
285 #---------------------------------------------------------------------------
286 #---------------------------------------------------------------------------
286 # Do the actual setup now
287 # Do the actual setup now
287 #---------------------------------------------------------------------------
288 #---------------------------------------------------------------------------
288
289
289 setup_args.update(setuptools_extra_args)
290 setup_args.update(setuptools_extra_args)
290
291
291
292
292
293
293 def main():
294 def main():
294 setup(**setup_args)
295 setup(**setup_args)
295
296
296 if __name__ == '__main__':
297 if __name__ == '__main__':
297 main()
298 main()
General Comments 0
You need to be logged in to leave comments. Login now