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