##// END OF EJS Templates
Remove import indirection and deprecated private function....
Matthias Bussonnier -
Show More
@@ -1,1461 +1,1462 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 - Neutral: a neutral color scheme that should be readable on both light and
70 - Neutral: a neutral color scheme that should be readable on both light and
71 dark background
71 dark background
72
72
73 You can implement other color schemes easily, the syntax is fairly
73 You can implement other color schemes easily, the syntax is fairly
74 self-explanatory. Please send back new schemes you develop to the author for
74 self-explanatory. Please send back new schemes you develop to the author for
75 possible inclusion in future releases.
75 possible inclusion in future releases.
76
76
77 Inheritance diagram:
77 Inheritance diagram:
78
78
79 .. inheritance-diagram:: IPython.core.ultratb
79 .. inheritance-diagram:: IPython.core.ultratb
80 :parts: 3
80 :parts: 3
81 """
81 """
82
82
83 #*****************************************************************************
83 #*****************************************************************************
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 #
86 #
87 # Distributed under the terms of the BSD License. The full license is in
87 # Distributed under the terms of the BSD License. The full license is in
88 # the file COPYING, distributed as part of this software.
88 # the file COPYING, distributed as part of this software.
89 #*****************************************************************************
89 #*****************************************************************************
90
90
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
103
104 try: # Python 2
104 try: # Python 2
105 generate_tokens = tokenize.generate_tokens
105 generate_tokens = tokenize.generate_tokens
106 except AttributeError: # Python 3
106 except AttributeError: # Python 3
107 generate_tokens = tokenize.tokenize
107 generate_tokens = tokenize.tokenize
108
108
109 # For purposes of monkeypatching inspect to fix a bug in it.
109 # For purposes of monkeypatching inspect to fix a bug in it.
110 from inspect import getsourcefile, getfile, getmodule, \
110 from inspect import getsourcefile, getfile, getmodule, \
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
112
112
113 # IPython's own modules
113 # IPython's own modules
114 from IPython import get_ipython
114 from IPython import get_ipython
115 from IPython.core import debugger
115 from IPython.core import debugger
116 from IPython.core.display_trap import DisplayTrap
116 from IPython.core.display_trap import DisplayTrap
117 from IPython.core.excolors import exception_colors
117 from IPython.core.excolors import exception_colors
118 from IPython.utils import PyColorize
118 from IPython.utils import PyColorize
119 from IPython.utils import openpy
120 from IPython.utils import path as util_path
119 from IPython.utils import path as util_path
121 from IPython.utils import py3compat
120 from IPython.utils import py3compat
122 from IPython.utils.data import uniq_stable
121 from IPython.utils.data import uniq_stable
123 from IPython.utils.terminal import get_terminal_size
122 from IPython.utils.terminal import get_terminal_size
124 from logging import info, error, debug
123 from logging import info, error, debug
125
124
125 from importlib.util import source_from_cache
126
126 import IPython.utils.colorable as colorable
127 import IPython.utils.colorable as colorable
127
128
128 # Globals
129 # Globals
129 # amount of space to put line numbers before verbose tracebacks
130 # amount of space to put line numbers before verbose tracebacks
130 INDENT_SIZE = 8
131 INDENT_SIZE = 8
131
132
132 # Default color scheme. This is used, for example, by the traceback
133 # Default color scheme. This is used, for example, by the traceback
133 # formatter. When running in an actual IPython instance, the user's rc.colors
134 # formatter. When running in an actual IPython instance, the user's rc.colors
134 # value is used, but having a module global makes this functionality available
135 # value is used, but having a module global makes this functionality available
135 # to users of ultratb who are NOT running inside ipython.
136 # to users of ultratb who are NOT running inside ipython.
136 DEFAULT_SCHEME = 'NoColor'
137 DEFAULT_SCHEME = 'NoColor'
137
138
138 # ---------------------------------------------------------------------------
139 # ---------------------------------------------------------------------------
139 # Code begins
140 # Code begins
140
141
141 # Utility functions
142 # Utility functions
142 def inspect_error():
143 def inspect_error():
143 """Print a message about internal inspect errors.
144 """Print a message about internal inspect errors.
144
145
145 These are unfortunately quite common."""
146 These are unfortunately quite common."""
146
147
147 error('Internal Python error in the inspect module.\n'
148 error('Internal Python error in the inspect module.\n'
148 'Below is the traceback from this internal error.\n')
149 'Below is the traceback from this internal error.\n')
149
150
150
151
151 # This function is a monkeypatch we apply to the Python inspect module. We have
152 # This function is a monkeypatch we apply to the Python inspect module. We have
152 # now found when it's needed (see discussion on issue gh-1456), and we have a
153 # now found when it's needed (see discussion on issue gh-1456), and we have a
153 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
154 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
154 # the monkeypatch is not applied. TK, Aug 2012.
155 # the monkeypatch is not applied. TK, Aug 2012.
155 def findsource(object):
156 def findsource(object):
156 """Return the entire source file and starting line number for an object.
157 """Return the entire source file and starting line number for an object.
157
158
158 The argument may be a module, class, method, function, traceback, frame,
159 The argument may be a module, class, method, function, traceback, frame,
159 or code object. The source code is returned as a list of all the lines
160 or code object. The source code is returned as a list of all the lines
160 in the file and the line number indexes a line in that list. An IOError
161 in the file and the line number indexes a line in that list. An IOError
161 is raised if the source code cannot be retrieved.
162 is raised if the source code cannot be retrieved.
162
163
163 FIXED version with which we monkeypatch the stdlib to work around a bug."""
164 FIXED version with which we monkeypatch the stdlib to work around a bug."""
164
165
165 file = getsourcefile(object) or getfile(object)
166 file = getsourcefile(object) or getfile(object)
166 # If the object is a frame, then trying to get the globals dict from its
167 # If the object is a frame, then trying to get the globals dict from its
167 # module won't work. Instead, the frame object itself has the globals
168 # module won't work. Instead, the frame object itself has the globals
168 # dictionary.
169 # dictionary.
169 globals_dict = None
170 globals_dict = None
170 if inspect.isframe(object):
171 if inspect.isframe(object):
171 # XXX: can this ever be false?
172 # XXX: can this ever be false?
172 globals_dict = object.f_globals
173 globals_dict = object.f_globals
173 else:
174 else:
174 module = getmodule(object, file)
175 module = getmodule(object, file)
175 if module:
176 if module:
176 globals_dict = module.__dict__
177 globals_dict = module.__dict__
177 lines = linecache.getlines(file, globals_dict)
178 lines = linecache.getlines(file, globals_dict)
178 if not lines:
179 if not lines:
179 raise IOError('could not get source code')
180 raise IOError('could not get source code')
180
181
181 if ismodule(object):
182 if ismodule(object):
182 return lines, 0
183 return lines, 0
183
184
184 if isclass(object):
185 if isclass(object):
185 name = object.__name__
186 name = object.__name__
186 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
187 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
187 # make some effort to find the best matching class definition:
188 # make some effort to find the best matching class definition:
188 # use the one with the least indentation, which is the one
189 # use the one with the least indentation, which is the one
189 # that's most probably not inside a function definition.
190 # that's most probably not inside a function definition.
190 candidates = []
191 candidates = []
191 for i, line in enumerate(lines):
192 for i, line in enumerate(lines):
192 match = pat.match(line)
193 match = pat.match(line)
193 if match:
194 if match:
194 # if it's at toplevel, it's already the best one
195 # if it's at toplevel, it's already the best one
195 if line[0] == 'c':
196 if line[0] == 'c':
196 return lines, i
197 return lines, i
197 # else add whitespace to candidate list
198 # else add whitespace to candidate list
198 candidates.append((match.group(1), i))
199 candidates.append((match.group(1), i))
199 if candidates:
200 if candidates:
200 # this will sort by whitespace, and by line number,
201 # this will sort by whitespace, and by line number,
201 # less whitespace first
202 # less whitespace first
202 candidates.sort()
203 candidates.sort()
203 return lines, candidates[0][1]
204 return lines, candidates[0][1]
204 else:
205 else:
205 raise IOError('could not find class definition')
206 raise IOError('could not find class definition')
206
207
207 if ismethod(object):
208 if ismethod(object):
208 object = object.__func__
209 object = object.__func__
209 if isfunction(object):
210 if isfunction(object):
210 object = object.__code__
211 object = object.__code__
211 if istraceback(object):
212 if istraceback(object):
212 object = object.tb_frame
213 object = object.tb_frame
213 if isframe(object):
214 if isframe(object):
214 object = object.f_code
215 object = object.f_code
215 if iscode(object):
216 if iscode(object):
216 if not hasattr(object, 'co_firstlineno'):
217 if not hasattr(object, 'co_firstlineno'):
217 raise IOError('could not find function definition')
218 raise IOError('could not find function definition')
218 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
219 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
219 pmatch = pat.match
220 pmatch = pat.match
220 # fperez - fix: sometimes, co_firstlineno can give a number larger than
221 # fperez - fix: sometimes, co_firstlineno can give a number larger than
221 # the length of lines, which causes an error. Safeguard against that.
222 # the length of lines, which causes an error. Safeguard against that.
222 lnum = min(object.co_firstlineno, len(lines)) - 1
223 lnum = min(object.co_firstlineno, len(lines)) - 1
223 while lnum > 0:
224 while lnum > 0:
224 if pmatch(lines[lnum]):
225 if pmatch(lines[lnum]):
225 break
226 break
226 lnum -= 1
227 lnum -= 1
227
228
228 return lines, lnum
229 return lines, lnum
229 raise IOError('could not find code object')
230 raise IOError('could not find code object')
230
231
231
232
232 # This is a patched version of inspect.getargs that applies the (unmerged)
233 # This is a patched version of inspect.getargs that applies the (unmerged)
233 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
234 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
234 # https://github.com/ipython/ipython/issues/8205 and
235 # https://github.com/ipython/ipython/issues/8205 and
235 # https://github.com/ipython/ipython/issues/8293
236 # https://github.com/ipython/ipython/issues/8293
236 def getargs(co):
237 def getargs(co):
237 """Get information about the arguments accepted by a code object.
238 """Get information about the arguments accepted by a code object.
238
239
239 Three things are returned: (args, varargs, varkw), where 'args' is
240 Three things are returned: (args, varargs, varkw), where 'args' is
240 a list of argument names (possibly containing nested lists), and
241 a list of argument names (possibly containing nested lists), and
241 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
242 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
242 if not iscode(co):
243 if not iscode(co):
243 raise TypeError('{!r} is not a code object'.format(co))
244 raise TypeError('{!r} is not a code object'.format(co))
244
245
245 nargs = co.co_argcount
246 nargs = co.co_argcount
246 names = co.co_varnames
247 names = co.co_varnames
247 args = list(names[:nargs])
248 args = list(names[:nargs])
248 step = 0
249 step = 0
249
250
250 # The following acrobatics are for anonymous (tuple) arguments.
251 # The following acrobatics are for anonymous (tuple) arguments.
251 for i in range(nargs):
252 for i in range(nargs):
252 if args[i][:1] in ('', '.'):
253 if args[i][:1] in ('', '.'):
253 stack, remain, count = [], [], []
254 stack, remain, count = [], [], []
254 while step < len(co.co_code):
255 while step < len(co.co_code):
255 op = ord(co.co_code[step])
256 op = ord(co.co_code[step])
256 step = step + 1
257 step = step + 1
257 if op >= dis.HAVE_ARGUMENT:
258 if op >= dis.HAVE_ARGUMENT:
258 opname = dis.opname[op]
259 opname = dis.opname[op]
259 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
260 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
260 step = step + 2
261 step = step + 2
261 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
262 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
262 remain.append(value)
263 remain.append(value)
263 count.append(value)
264 count.append(value)
264 elif opname in ('STORE_FAST', 'STORE_DEREF'):
265 elif opname in ('STORE_FAST', 'STORE_DEREF'):
265 if op in dis.haslocal:
266 if op in dis.haslocal:
266 stack.append(co.co_varnames[value])
267 stack.append(co.co_varnames[value])
267 elif op in dis.hasfree:
268 elif op in dis.hasfree:
268 stack.append((co.co_cellvars + co.co_freevars)[value])
269 stack.append((co.co_cellvars + co.co_freevars)[value])
269 # Special case for sublists of length 1: def foo((bar))
270 # Special case for sublists of length 1: def foo((bar))
270 # doesn't generate the UNPACK_TUPLE bytecode, so if
271 # doesn't generate the UNPACK_TUPLE bytecode, so if
271 # `remain` is empty here, we have such a sublist.
272 # `remain` is empty here, we have such a sublist.
272 if not remain:
273 if not remain:
273 stack[0] = [stack[0]]
274 stack[0] = [stack[0]]
274 break
275 break
275 else:
276 else:
276 remain[-1] = remain[-1] - 1
277 remain[-1] = remain[-1] - 1
277 while remain[-1] == 0:
278 while remain[-1] == 0:
278 remain.pop()
279 remain.pop()
279 size = count.pop()
280 size = count.pop()
280 stack[-size:] = [stack[-size:]]
281 stack[-size:] = [stack[-size:]]
281 if not remain:
282 if not remain:
282 break
283 break
283 remain[-1] = remain[-1] - 1
284 remain[-1] = remain[-1] - 1
284 if not remain:
285 if not remain:
285 break
286 break
286 args[i] = stack[0]
287 args[i] = stack[0]
287
288
288 varargs = None
289 varargs = None
289 if co.co_flags & inspect.CO_VARARGS:
290 if co.co_flags & inspect.CO_VARARGS:
290 varargs = co.co_varnames[nargs]
291 varargs = co.co_varnames[nargs]
291 nargs = nargs + 1
292 nargs = nargs + 1
292 varkw = None
293 varkw = None
293 if co.co_flags & inspect.CO_VARKEYWORDS:
294 if co.co_flags & inspect.CO_VARKEYWORDS:
294 varkw = co.co_varnames[nargs]
295 varkw = co.co_varnames[nargs]
295 return inspect.Arguments(args, varargs, varkw)
296 return inspect.Arguments(args, varargs, varkw)
296
297
297
298
298 # Monkeypatch inspect to apply our bugfix.
299 # Monkeypatch inspect to apply our bugfix.
299 def with_patch_inspect(f):
300 def with_patch_inspect(f):
300 """
301 """
301 Deprecated since IPython 6.0
302 Deprecated since IPython 6.0
302 decorator for monkeypatching inspect.findsource
303 decorator for monkeypatching inspect.findsource
303 """
304 """
304
305
305 def wrapped(*args, **kwargs):
306 def wrapped(*args, **kwargs):
306 save_findsource = inspect.findsource
307 save_findsource = inspect.findsource
307 save_getargs = inspect.getargs
308 save_getargs = inspect.getargs
308 inspect.findsource = findsource
309 inspect.findsource = findsource
309 inspect.getargs = getargs
310 inspect.getargs = getargs
310 try:
311 try:
311 return f(*args, **kwargs)
312 return f(*args, **kwargs)
312 finally:
313 finally:
313 inspect.findsource = save_findsource
314 inspect.findsource = save_findsource
314 inspect.getargs = save_getargs
315 inspect.getargs = save_getargs
315
316
316 return wrapped
317 return wrapped
317
318
318
319
319 def fix_frame_records_filenames(records):
320 def fix_frame_records_filenames(records):
320 """Try to fix the filenames in each record from inspect.getinnerframes().
321 """Try to fix the filenames in each record from inspect.getinnerframes().
321
322
322 Particularly, modules loaded from within zip files have useless filenames
323 Particularly, modules loaded from within zip files have useless filenames
323 attached to their code object, and inspect.getinnerframes() just uses it.
324 attached to their code object, and inspect.getinnerframes() just uses it.
324 """
325 """
325 fixed_records = []
326 fixed_records = []
326 for frame, filename, line_no, func_name, lines, index in records:
327 for frame, filename, line_no, func_name, lines, index in records:
327 # Look inside the frame's globals dictionary for __file__,
328 # Look inside the frame's globals dictionary for __file__,
328 # which should be better. However, keep Cython filenames since
329 # which should be better. However, keep Cython filenames since
329 # we prefer the source filenames over the compiled .so file.
330 # we prefer the source filenames over the compiled .so file.
330 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
331 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
331 better_fn = frame.f_globals.get('__file__', None)
332 better_fn = frame.f_globals.get('__file__', None)
332 if isinstance(better_fn, str):
333 if isinstance(better_fn, str):
333 # Check the type just in case someone did something weird with
334 # Check the type just in case someone did something weird with
334 # __file__. It might also be None if the error occurred during
335 # __file__. It might also be None if the error occurred during
335 # import.
336 # import.
336 filename = better_fn
337 filename = better_fn
337 fixed_records.append((frame, filename, line_no, func_name, lines, index))
338 fixed_records.append((frame, filename, line_no, func_name, lines, index))
338 return fixed_records
339 return fixed_records
339
340
340
341
341 @with_patch_inspect
342 @with_patch_inspect
342 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
343 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
343 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
344 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
344
345
345 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
346 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
346 # If the error is at the console, don't build any context, since it would
347 # If the error is at the console, don't build any context, since it would
347 # otherwise produce 5 blank lines printed out (there is no file at the
348 # otherwise produce 5 blank lines printed out (there is no file at the
348 # console)
349 # console)
349 rec_check = records[tb_offset:]
350 rec_check = records[tb_offset:]
350 try:
351 try:
351 rname = rec_check[0][1]
352 rname = rec_check[0][1]
352 if rname == '<ipython console>' or rname.endswith('<string>'):
353 if rname == '<ipython console>' or rname.endswith('<string>'):
353 return rec_check
354 return rec_check
354 except IndexError:
355 except IndexError:
355 pass
356 pass
356
357
357 aux = traceback.extract_tb(etb)
358 aux = traceback.extract_tb(etb)
358 assert len(records) == len(aux)
359 assert len(records) == len(aux)
359 for i, (file, lnum, _, _) in enumerate(aux):
360 for i, (file, lnum, _, _) in enumerate(aux):
360 maybeStart = lnum - 1 - context // 2
361 maybeStart = lnum - 1 - context // 2
361 start = max(maybeStart, 0)
362 start = max(maybeStart, 0)
362 end = start + context
363 end = start + context
363 lines = linecache.getlines(file)[start:end]
364 lines = linecache.getlines(file)[start:end]
364 buf = list(records[i])
365 buf = list(records[i])
365 buf[LNUM_POS] = lnum
366 buf[LNUM_POS] = lnum
366 buf[INDEX_POS] = lnum - 1 - start
367 buf[INDEX_POS] = lnum - 1 - start
367 buf[LINES_POS] = lines
368 buf[LINES_POS] = lines
368 records[i] = tuple(buf)
369 records[i] = tuple(buf)
369 return records[tb_offset:]
370 return records[tb_offset:]
370
371
371 # Helper function -- largely belongs to VerboseTB, but we need the same
372 # Helper function -- largely belongs to VerboseTB, but we need the same
372 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
373 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
373 # can be recognized properly by ipython.el's py-traceback-line-re
374 # can be recognized properly by ipython.el's py-traceback-line-re
374 # (SyntaxErrors have to be treated specially because they have no traceback)
375 # (SyntaxErrors have to be treated specially because they have no traceback)
375
376
376
377
377 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
378 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
378 numbers_width = INDENT_SIZE - 1
379 numbers_width = INDENT_SIZE - 1
379 res = []
380 res = []
380 i = lnum - index
381 i = lnum - index
381
382
382 for line in lines:
383 for line in lines:
383 line = py3compat.cast_unicode(line)
384 line = py3compat.cast_unicode(line)
384
385
385 new_line, err = _line_format(line, 'str')
386 new_line, err = _line_format(line, 'str')
386 if not err: line = new_line
387 if not err: line = new_line
387
388
388 if i == lnum:
389 if i == lnum:
389 # This is the line with the error
390 # This is the line with the error
390 pad = numbers_width - len(str(i))
391 pad = numbers_width - len(str(i))
391 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
392 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
392 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
393 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
393 Colors.line, line, Colors.Normal)
394 Colors.line, line, Colors.Normal)
394 else:
395 else:
395 num = '%*s' % (numbers_width, i)
396 num = '%*s' % (numbers_width, i)
396 line = '%s%s%s %s' % (Colors.lineno, num,
397 line = '%s%s%s %s' % (Colors.lineno, num,
397 Colors.Normal, line)
398 Colors.Normal, line)
398
399
399 res.append(line)
400 res.append(line)
400 if lvals and i == lnum:
401 if lvals and i == lnum:
401 res.append(lvals + '\n')
402 res.append(lvals + '\n')
402 i = i + 1
403 i = i + 1
403 return res
404 return res
404
405
405 def is_recursion_error(etype, value, records):
406 def is_recursion_error(etype, value, records):
406 try:
407 try:
407 # RecursionError is new in Python 3.5
408 # RecursionError is new in Python 3.5
408 recursion_error_type = RecursionError
409 recursion_error_type = RecursionError
409 except NameError:
410 except NameError:
410 recursion_error_type = RuntimeError
411 recursion_error_type = RuntimeError
411
412
412 # The default recursion limit is 1000, but some of that will be taken up
413 # The default recursion limit is 1000, but some of that will be taken up
413 # by stack frames in IPython itself. >500 frames probably indicates
414 # by stack frames in IPython itself. >500 frames probably indicates
414 # a recursion error.
415 # a recursion error.
415 return (etype is recursion_error_type) \
416 return (etype is recursion_error_type) \
416 and "recursion" in str(value).lower() \
417 and "recursion" in str(value).lower() \
417 and len(records) > 500
418 and len(records) > 500
418
419
419 def find_recursion(etype, value, records):
420 def find_recursion(etype, value, records):
420 """Identify the repeating stack frames from a RecursionError traceback
421 """Identify the repeating stack frames from a RecursionError traceback
421
422
422 'records' is a list as returned by VerboseTB.get_records()
423 'records' is a list as returned by VerboseTB.get_records()
423
424
424 Returns (last_unique, repeat_length)
425 Returns (last_unique, repeat_length)
425 """
426 """
426 # This involves a bit of guesswork - we want to show enough of the traceback
427 # This involves a bit of guesswork - we want to show enough of the traceback
427 # to indicate where the recursion is occurring. We guess that the innermost
428 # to indicate where the recursion is occurring. We guess that the innermost
428 # quarter of the traceback (250 frames by default) is repeats, and find the
429 # quarter of the traceback (250 frames by default) is repeats, and find the
429 # first frame (from in to out) that looks different.
430 # first frame (from in to out) that looks different.
430 if not is_recursion_error(etype, value, records):
431 if not is_recursion_error(etype, value, records):
431 return len(records), 0
432 return len(records), 0
432
433
433 # Select filename, lineno, func_name to track frames with
434 # Select filename, lineno, func_name to track frames with
434 records = [r[1:4] for r in records]
435 records = [r[1:4] for r in records]
435 inner_frames = records[-(len(records)//4):]
436 inner_frames = records[-(len(records)//4):]
436 frames_repeated = set(inner_frames)
437 frames_repeated = set(inner_frames)
437
438
438 last_seen_at = {}
439 last_seen_at = {}
439 longest_repeat = 0
440 longest_repeat = 0
440 i = len(records)
441 i = len(records)
441 for frame in reversed(records):
442 for frame in reversed(records):
442 i -= 1
443 i -= 1
443 if frame not in frames_repeated:
444 if frame not in frames_repeated:
444 last_unique = i
445 last_unique = i
445 break
446 break
446
447
447 if frame in last_seen_at:
448 if frame in last_seen_at:
448 distance = last_seen_at[frame] - i
449 distance = last_seen_at[frame] - i
449 longest_repeat = max(longest_repeat, distance)
450 longest_repeat = max(longest_repeat, distance)
450
451
451 last_seen_at[frame] = i
452 last_seen_at[frame] = i
452 else:
453 else:
453 last_unique = 0 # The whole traceback was recursion
454 last_unique = 0 # The whole traceback was recursion
454
455
455 return last_unique, longest_repeat
456 return last_unique, longest_repeat
456
457
457 #---------------------------------------------------------------------------
458 #---------------------------------------------------------------------------
458 # Module classes
459 # Module classes
459 class TBTools(colorable.Colorable):
460 class TBTools(colorable.Colorable):
460 """Basic tools used by all traceback printer classes."""
461 """Basic tools used by all traceback printer classes."""
461
462
462 # Number of frames to skip when reporting tracebacks
463 # Number of frames to skip when reporting tracebacks
463 tb_offset = 0
464 tb_offset = 0
464
465
465 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
466 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
466 # Whether to call the interactive pdb debugger after printing
467 # Whether to call the interactive pdb debugger after printing
467 # tracebacks or not
468 # tracebacks or not
468 super(TBTools, self).__init__(parent=parent, config=config)
469 super(TBTools, self).__init__(parent=parent, config=config)
469 self.call_pdb = call_pdb
470 self.call_pdb = call_pdb
470
471
471 # Output stream to write to. Note that we store the original value in
472 # Output stream to write to. Note that we store the original value in
472 # a private attribute and then make the public ostream a property, so
473 # a private attribute and then make the public ostream a property, so
473 # that we can delay accessing sys.stdout until runtime. The way
474 # that we can delay accessing sys.stdout until runtime. The way
474 # things are written now, the sys.stdout object is dynamically managed
475 # things are written now, the sys.stdout object is dynamically managed
475 # so a reference to it should NEVER be stored statically. This
476 # so a reference to it should NEVER be stored statically. This
476 # property approach confines this detail to a single location, and all
477 # property approach confines this detail to a single location, and all
477 # subclasses can simply access self.ostream for writing.
478 # subclasses can simply access self.ostream for writing.
478 self._ostream = ostream
479 self._ostream = ostream
479
480
480 # Create color table
481 # Create color table
481 self.color_scheme_table = exception_colors()
482 self.color_scheme_table = exception_colors()
482
483
483 self.set_colors(color_scheme)
484 self.set_colors(color_scheme)
484 self.old_scheme = color_scheme # save initial value for toggles
485 self.old_scheme = color_scheme # save initial value for toggles
485
486
486 if call_pdb:
487 if call_pdb:
487 self.pdb = debugger.Pdb()
488 self.pdb = debugger.Pdb()
488 else:
489 else:
489 self.pdb = None
490 self.pdb = None
490
491
491 def _get_ostream(self):
492 def _get_ostream(self):
492 """Output stream that exceptions are written to.
493 """Output stream that exceptions are written to.
493
494
494 Valid values are:
495 Valid values are:
495
496
496 - None: the default, which means that IPython will dynamically resolve
497 - None: the default, which means that IPython will dynamically resolve
497 to sys.stdout. This ensures compatibility with most tools, including
498 to sys.stdout. This ensures compatibility with most tools, including
498 Windows (where plain stdout doesn't recognize ANSI escapes).
499 Windows (where plain stdout doesn't recognize ANSI escapes).
499
500
500 - Any object with 'write' and 'flush' attributes.
501 - Any object with 'write' and 'flush' attributes.
501 """
502 """
502 return sys.stdout if self._ostream is None else self._ostream
503 return sys.stdout if self._ostream is None else self._ostream
503
504
504 def _set_ostream(self, val):
505 def _set_ostream(self, val):
505 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
506 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
506 self._ostream = val
507 self._ostream = val
507
508
508 ostream = property(_get_ostream, _set_ostream)
509 ostream = property(_get_ostream, _set_ostream)
509
510
510 def set_colors(self, *args, **kw):
511 def set_colors(self, *args, **kw):
511 """Shorthand access to the color table scheme selector method."""
512 """Shorthand access to the color table scheme selector method."""
512
513
513 # Set own color table
514 # Set own color table
514 self.color_scheme_table.set_active_scheme(*args, **kw)
515 self.color_scheme_table.set_active_scheme(*args, **kw)
515 # for convenience, set Colors to the active scheme
516 # for convenience, set Colors to the active scheme
516 self.Colors = self.color_scheme_table.active_colors
517 self.Colors = self.color_scheme_table.active_colors
517 # Also set colors of debugger
518 # Also set colors of debugger
518 if hasattr(self, 'pdb') and self.pdb is not None:
519 if hasattr(self, 'pdb') and self.pdb is not None:
519 self.pdb.set_colors(*args, **kw)
520 self.pdb.set_colors(*args, **kw)
520
521
521 def color_toggle(self):
522 def color_toggle(self):
522 """Toggle between the currently active color scheme and NoColor."""
523 """Toggle between the currently active color scheme and NoColor."""
523
524
524 if self.color_scheme_table.active_scheme_name == 'NoColor':
525 if self.color_scheme_table.active_scheme_name == 'NoColor':
525 self.color_scheme_table.set_active_scheme(self.old_scheme)
526 self.color_scheme_table.set_active_scheme(self.old_scheme)
526 self.Colors = self.color_scheme_table.active_colors
527 self.Colors = self.color_scheme_table.active_colors
527 else:
528 else:
528 self.old_scheme = self.color_scheme_table.active_scheme_name
529 self.old_scheme = self.color_scheme_table.active_scheme_name
529 self.color_scheme_table.set_active_scheme('NoColor')
530 self.color_scheme_table.set_active_scheme('NoColor')
530 self.Colors = self.color_scheme_table.active_colors
531 self.Colors = self.color_scheme_table.active_colors
531
532
532 def stb2text(self, stb):
533 def stb2text(self, stb):
533 """Convert a structured traceback (a list) to a string."""
534 """Convert a structured traceback (a list) to a string."""
534 return '\n'.join(stb)
535 return '\n'.join(stb)
535
536
536 def text(self, etype, value, tb, tb_offset=None, context=5):
537 def text(self, etype, value, tb, tb_offset=None, context=5):
537 """Return formatted traceback.
538 """Return formatted traceback.
538
539
539 Subclasses may override this if they add extra arguments.
540 Subclasses may override this if they add extra arguments.
540 """
541 """
541 tb_list = self.structured_traceback(etype, value, tb,
542 tb_list = self.structured_traceback(etype, value, tb,
542 tb_offset, context)
543 tb_offset, context)
543 return self.stb2text(tb_list)
544 return self.stb2text(tb_list)
544
545
545 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
546 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
546 context=5, mode=None):
547 context=5, mode=None):
547 """Return a list of traceback frames.
548 """Return a list of traceback frames.
548
549
549 Must be implemented by each class.
550 Must be implemented by each class.
550 """
551 """
551 raise NotImplementedError()
552 raise NotImplementedError()
552
553
553
554
554 #---------------------------------------------------------------------------
555 #---------------------------------------------------------------------------
555 class ListTB(TBTools):
556 class ListTB(TBTools):
556 """Print traceback information from a traceback list, with optional color.
557 """Print traceback information from a traceback list, with optional color.
557
558
558 Calling requires 3 arguments: (etype, evalue, elist)
559 Calling requires 3 arguments: (etype, evalue, elist)
559 as would be obtained by::
560 as would be obtained by::
560
561
561 etype, evalue, tb = sys.exc_info()
562 etype, evalue, tb = sys.exc_info()
562 if tb:
563 if tb:
563 elist = traceback.extract_tb(tb)
564 elist = traceback.extract_tb(tb)
564 else:
565 else:
565 elist = None
566 elist = None
566
567
567 It can thus be used by programs which need to process the traceback before
568 It can thus be used by programs which need to process the traceback before
568 printing (such as console replacements based on the code module from the
569 printing (such as console replacements based on the code module from the
569 standard library).
570 standard library).
570
571
571 Because they are meant to be called without a full traceback (only a
572 Because they are meant to be called without a full traceback (only a
572 list), instances of this class can't call the interactive pdb debugger."""
573 list), instances of this class can't call the interactive pdb debugger."""
573
574
574 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
575 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
575 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
576 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
576 ostream=ostream, parent=parent,config=config)
577 ostream=ostream, parent=parent,config=config)
577
578
578 def __call__(self, etype, value, elist):
579 def __call__(self, etype, value, elist):
579 self.ostream.flush()
580 self.ostream.flush()
580 self.ostream.write(self.text(etype, value, elist))
581 self.ostream.write(self.text(etype, value, elist))
581 self.ostream.write('\n')
582 self.ostream.write('\n')
582
583
583 def structured_traceback(self, etype, value, elist, tb_offset=None,
584 def structured_traceback(self, etype, value, elist, tb_offset=None,
584 context=5):
585 context=5):
585 """Return a color formatted string with the traceback info.
586 """Return a color formatted string with the traceback info.
586
587
587 Parameters
588 Parameters
588 ----------
589 ----------
589 etype : exception type
590 etype : exception type
590 Type of the exception raised.
591 Type of the exception raised.
591
592
592 value : object
593 value : object
593 Data stored in the exception
594 Data stored in the exception
594
595
595 elist : list
596 elist : list
596 List of frames, see class docstring for details.
597 List of frames, see class docstring for details.
597
598
598 tb_offset : int, optional
599 tb_offset : int, optional
599 Number of frames in the traceback to skip. If not given, the
600 Number of frames in the traceback to skip. If not given, the
600 instance value is used (set in constructor).
601 instance value is used (set in constructor).
601
602
602 context : int, optional
603 context : int, optional
603 Number of lines of context information to print.
604 Number of lines of context information to print.
604
605
605 Returns
606 Returns
606 -------
607 -------
607 String with formatted exception.
608 String with formatted exception.
608 """
609 """
609 tb_offset = self.tb_offset if tb_offset is None else tb_offset
610 tb_offset = self.tb_offset if tb_offset is None else tb_offset
610 Colors = self.Colors
611 Colors = self.Colors
611 out_list = []
612 out_list = []
612 if elist:
613 if elist:
613
614
614 if tb_offset and len(elist) > tb_offset:
615 if tb_offset and len(elist) > tb_offset:
615 elist = elist[tb_offset:]
616 elist = elist[tb_offset:]
616
617
617 out_list.append('Traceback %s(most recent call last)%s:' %
618 out_list.append('Traceback %s(most recent call last)%s:' %
618 (Colors.normalEm, Colors.Normal) + '\n')
619 (Colors.normalEm, Colors.Normal) + '\n')
619 out_list.extend(self._format_list(elist))
620 out_list.extend(self._format_list(elist))
620 # The exception info should be a single entry in the list.
621 # The exception info should be a single entry in the list.
621 lines = ''.join(self._format_exception_only(etype, value))
622 lines = ''.join(self._format_exception_only(etype, value))
622 out_list.append(lines)
623 out_list.append(lines)
623
624
624 # Note: this code originally read:
625 # Note: this code originally read:
625
626
626 ## for line in lines[:-1]:
627 ## for line in lines[:-1]:
627 ## out_list.append(" "+line)
628 ## out_list.append(" "+line)
628 ## out_list.append(lines[-1])
629 ## out_list.append(lines[-1])
629
630
630 # This means it was indenting everything but the last line by a little
631 # This means it was indenting everything but the last line by a little
631 # bit. I've disabled this for now, but if we see ugliness somewhere we
632 # bit. I've disabled this for now, but if we see ugliness somewhere we
632 # can restore it.
633 # can restore it.
633
634
634 return out_list
635 return out_list
635
636
636 def _format_list(self, extracted_list):
637 def _format_list(self, extracted_list):
637 """Format a list of traceback entry tuples for printing.
638 """Format a list of traceback entry tuples for printing.
638
639
639 Given a list of tuples as returned by extract_tb() or
640 Given a list of tuples as returned by extract_tb() or
640 extract_stack(), return a list of strings ready for printing.
641 extract_stack(), return a list of strings ready for printing.
641 Each string in the resulting list corresponds to the item with the
642 Each string in the resulting list corresponds to the item with the
642 same index in the argument list. Each string ends in a newline;
643 same index in the argument list. Each string ends in a newline;
643 the strings may contain internal newlines as well, for those items
644 the strings may contain internal newlines as well, for those items
644 whose source text line is not None.
645 whose source text line is not None.
645
646
646 Lifted almost verbatim from traceback.py
647 Lifted almost verbatim from traceback.py
647 """
648 """
648
649
649 Colors = self.Colors
650 Colors = self.Colors
650 list = []
651 list = []
651 for filename, lineno, name, line in extracted_list[:-1]:
652 for filename, lineno, name, line in extracted_list[:-1]:
652 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
653 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
653 (Colors.filename, filename, Colors.Normal,
654 (Colors.filename, filename, Colors.Normal,
654 Colors.lineno, lineno, Colors.Normal,
655 Colors.lineno, lineno, Colors.Normal,
655 Colors.name, name, Colors.Normal)
656 Colors.name, name, Colors.Normal)
656 if line:
657 if line:
657 item += ' %s\n' % line.strip()
658 item += ' %s\n' % line.strip()
658 list.append(item)
659 list.append(item)
659 # Emphasize the last entry
660 # Emphasize the last entry
660 filename, lineno, name, line = extracted_list[-1]
661 filename, lineno, name, line = extracted_list[-1]
661 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
662 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
662 (Colors.normalEm,
663 (Colors.normalEm,
663 Colors.filenameEm, filename, Colors.normalEm,
664 Colors.filenameEm, filename, Colors.normalEm,
664 Colors.linenoEm, lineno, Colors.normalEm,
665 Colors.linenoEm, lineno, Colors.normalEm,
665 Colors.nameEm, name, Colors.normalEm,
666 Colors.nameEm, name, Colors.normalEm,
666 Colors.Normal)
667 Colors.Normal)
667 if line:
668 if line:
668 item += '%s %s%s\n' % (Colors.line, line.strip(),
669 item += '%s %s%s\n' % (Colors.line, line.strip(),
669 Colors.Normal)
670 Colors.Normal)
670 list.append(item)
671 list.append(item)
671 return list
672 return list
672
673
673 def _format_exception_only(self, etype, value):
674 def _format_exception_only(self, etype, value):
674 """Format the exception part of a traceback.
675 """Format the exception part of a traceback.
675
676
676 The arguments are the exception type and value such as given by
677 The arguments are the exception type and value such as given by
677 sys.exc_info()[:2]. The return value is a list of strings, each ending
678 sys.exc_info()[:2]. The return value is a list of strings, each ending
678 in a newline. Normally, the list contains a single string; however,
679 in a newline. Normally, the list contains a single string; however,
679 for SyntaxError exceptions, it contains several lines that (when
680 for SyntaxError exceptions, it contains several lines that (when
680 printed) display detailed information about where the syntax error
681 printed) display detailed information about where the syntax error
681 occurred. The message indicating which exception occurred is the
682 occurred. The message indicating which exception occurred is the
682 always last string in the list.
683 always last string in the list.
683
684
684 Also lifted nearly verbatim from traceback.py
685 Also lifted nearly verbatim from traceback.py
685 """
686 """
686 have_filedata = False
687 have_filedata = False
687 Colors = self.Colors
688 Colors = self.Colors
688 list = []
689 list = []
689 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
690 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
690 if value is None:
691 if value is None:
691 # Not sure if this can still happen in Python 2.6 and above
692 # Not sure if this can still happen in Python 2.6 and above
692 list.append(stype + '\n')
693 list.append(stype + '\n')
693 else:
694 else:
694 if issubclass(etype, SyntaxError):
695 if issubclass(etype, SyntaxError):
695 have_filedata = True
696 have_filedata = True
696 if not value.filename: value.filename = "<string>"
697 if not value.filename: value.filename = "<string>"
697 if value.lineno:
698 if value.lineno:
698 lineno = value.lineno
699 lineno = value.lineno
699 textline = linecache.getline(value.filename, value.lineno)
700 textline = linecache.getline(value.filename, value.lineno)
700 else:
701 else:
701 lineno = 'unknown'
702 lineno = 'unknown'
702 textline = ''
703 textline = ''
703 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
704 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
704 (Colors.normalEm,
705 (Colors.normalEm,
705 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
706 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
706 Colors.linenoEm, lineno, Colors.Normal ))
707 Colors.linenoEm, lineno, Colors.Normal ))
707 if textline == '':
708 if textline == '':
708 textline = py3compat.cast_unicode(value.text, "utf-8")
709 textline = py3compat.cast_unicode(value.text, "utf-8")
709
710
710 if textline is not None:
711 if textline is not None:
711 i = 0
712 i = 0
712 while i < len(textline) and textline[i].isspace():
713 while i < len(textline) and textline[i].isspace():
713 i += 1
714 i += 1
714 list.append('%s %s%s\n' % (Colors.line,
715 list.append('%s %s%s\n' % (Colors.line,
715 textline.strip(),
716 textline.strip(),
716 Colors.Normal))
717 Colors.Normal))
717 if value.offset is not None:
718 if value.offset is not None:
718 s = ' '
719 s = ' '
719 for c in textline[i:value.offset - 1]:
720 for c in textline[i:value.offset - 1]:
720 if c.isspace():
721 if c.isspace():
721 s += c
722 s += c
722 else:
723 else:
723 s += ' '
724 s += ' '
724 list.append('%s%s^%s\n' % (Colors.caret, s,
725 list.append('%s%s^%s\n' % (Colors.caret, s,
725 Colors.Normal))
726 Colors.Normal))
726
727
727 try:
728 try:
728 s = value.msg
729 s = value.msg
729 except Exception:
730 except Exception:
730 s = self._some_str(value)
731 s = self._some_str(value)
731 if s:
732 if s:
732 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
733 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
733 Colors.Normal, s))
734 Colors.Normal, s))
734 else:
735 else:
735 list.append('%s\n' % stype)
736 list.append('%s\n' % stype)
736
737
737 # sync with user hooks
738 # sync with user hooks
738 if have_filedata:
739 if have_filedata:
739 ipinst = get_ipython()
740 ipinst = get_ipython()
740 if ipinst is not None:
741 if ipinst is not None:
741 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
742 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
742
743
743 return list
744 return list
744
745
745 def get_exception_only(self, etype, value):
746 def get_exception_only(self, etype, value):
746 """Only print the exception type and message, without a traceback.
747 """Only print the exception type and message, without a traceback.
747
748
748 Parameters
749 Parameters
749 ----------
750 ----------
750 etype : exception type
751 etype : exception type
751 value : exception value
752 value : exception value
752 """
753 """
753 return ListTB.structured_traceback(self, etype, value, [])
754 return ListTB.structured_traceback(self, etype, value, [])
754
755
755 def show_exception_only(self, etype, evalue):
756 def show_exception_only(self, etype, evalue):
756 """Only print the exception type and message, without a traceback.
757 """Only print the exception type and message, without a traceback.
757
758
758 Parameters
759 Parameters
759 ----------
760 ----------
760 etype : exception type
761 etype : exception type
761 value : exception value
762 value : exception value
762 """
763 """
763 # This method needs to use __call__ from *this* class, not the one from
764 # This method needs to use __call__ from *this* class, not the one from
764 # a subclass whose signature or behavior may be different
765 # a subclass whose signature or behavior may be different
765 ostream = self.ostream
766 ostream = self.ostream
766 ostream.flush()
767 ostream.flush()
767 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
768 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
768 ostream.flush()
769 ostream.flush()
769
770
770 def _some_str(self, value):
771 def _some_str(self, value):
771 # Lifted from traceback.py
772 # Lifted from traceback.py
772 try:
773 try:
773 return py3compat.cast_unicode(str(value))
774 return py3compat.cast_unicode(str(value))
774 except:
775 except:
775 return u'<unprintable %s object>' % type(value).__name__
776 return u'<unprintable %s object>' % type(value).__name__
776
777
777
778
778 #----------------------------------------------------------------------------
779 #----------------------------------------------------------------------------
779 class VerboseTB(TBTools):
780 class VerboseTB(TBTools):
780 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
781 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
781 of HTML. Requires inspect and pydoc. Crazy, man.
782 of HTML. Requires inspect and pydoc. Crazy, man.
782
783
783 Modified version which optionally strips the topmost entries from the
784 Modified version which optionally strips the topmost entries from the
784 traceback, to be used with alternate interpreters (because their own code
785 traceback, to be used with alternate interpreters (because their own code
785 would appear in the traceback)."""
786 would appear in the traceback)."""
786
787
787 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
788 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
788 tb_offset=0, long_header=False, include_vars=True,
789 tb_offset=0, long_header=False, include_vars=True,
789 check_cache=None, debugger_cls = None,
790 check_cache=None, debugger_cls = None,
790 parent=None, config=None):
791 parent=None, config=None):
791 """Specify traceback offset, headers and color scheme.
792 """Specify traceback offset, headers and color scheme.
792
793
793 Define how many frames to drop from the tracebacks. Calling it with
794 Define how many frames to drop from the tracebacks. Calling it with
794 tb_offset=1 allows use of this handler in interpreters which will have
795 tb_offset=1 allows use of this handler in interpreters which will have
795 their own code at the top of the traceback (VerboseTB will first
796 their own code at the top of the traceback (VerboseTB will first
796 remove that frame before printing the traceback info)."""
797 remove that frame before printing the traceback info)."""
797 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
798 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
798 ostream=ostream, parent=parent, config=config)
799 ostream=ostream, parent=parent, config=config)
799 self.tb_offset = tb_offset
800 self.tb_offset = tb_offset
800 self.long_header = long_header
801 self.long_header = long_header
801 self.include_vars = include_vars
802 self.include_vars = include_vars
802 # By default we use linecache.checkcache, but the user can provide a
803 # By default we use linecache.checkcache, but the user can provide a
803 # different check_cache implementation. This is used by the IPython
804 # different check_cache implementation. This is used by the IPython
804 # kernel to provide tracebacks for interactive code that is cached,
805 # kernel to provide tracebacks for interactive code that is cached,
805 # by a compiler instance that flushes the linecache but preserves its
806 # by a compiler instance that flushes the linecache but preserves its
806 # own code cache.
807 # own code cache.
807 if check_cache is None:
808 if check_cache is None:
808 check_cache = linecache.checkcache
809 check_cache = linecache.checkcache
809 self.check_cache = check_cache
810 self.check_cache = check_cache
810
811
811 self.debugger_cls = debugger_cls or debugger.Pdb
812 self.debugger_cls = debugger_cls or debugger.Pdb
812
813
813 def format_records(self, records, last_unique, recursion_repeat):
814 def format_records(self, records, last_unique, recursion_repeat):
814 """Format the stack frames of the traceback"""
815 """Format the stack frames of the traceback"""
815 frames = []
816 frames = []
816 for r in records[:last_unique+recursion_repeat+1]:
817 for r in records[:last_unique+recursion_repeat+1]:
817 #print '*** record:',file,lnum,func,lines,index # dbg
818 #print '*** record:',file,lnum,func,lines,index # dbg
818 frames.append(self.format_record(*r))
819 frames.append(self.format_record(*r))
819
820
820 if recursion_repeat:
821 if recursion_repeat:
821 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
822 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
822 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
823 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
823
824
824 return frames
825 return frames
825
826
826 def format_record(self, frame, file, lnum, func, lines, index):
827 def format_record(self, frame, file, lnum, func, lines, index):
827 """Format a single stack frame"""
828 """Format a single stack frame"""
828 Colors = self.Colors # just a shorthand + quicker name lookup
829 Colors = self.Colors # just a shorthand + quicker name lookup
829 ColorsNormal = Colors.Normal # used a lot
830 ColorsNormal = Colors.Normal # used a lot
830 col_scheme = self.color_scheme_table.active_scheme_name
831 col_scheme = self.color_scheme_table.active_scheme_name
831 indent = ' ' * INDENT_SIZE
832 indent = ' ' * INDENT_SIZE
832 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
833 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
833 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
834 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
834 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
835 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
835 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
836 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
836 ColorsNormal)
837 ColorsNormal)
837 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
838 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
838 (Colors.vName, Colors.valEm, ColorsNormal)
839 (Colors.vName, Colors.valEm, ColorsNormal)
839 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
840 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
840 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
841 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
841 Colors.vName, ColorsNormal)
842 Colors.vName, ColorsNormal)
842 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
843 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
843
844
844 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
845 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
845 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
846 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
846 ColorsNormal)
847 ColorsNormal)
847
848
848 abspath = os.path.abspath
849 abspath = os.path.abspath
849
850
850
851
851 if not file:
852 if not file:
852 file = '?'
853 file = '?'
853 elif file.startswith(str("<")) and file.endswith(str(">")):
854 elif file.startswith(str("<")) and file.endswith(str(">")):
854 # Not a real filename, no problem...
855 # Not a real filename, no problem...
855 pass
856 pass
856 elif not os.path.isabs(file):
857 elif not os.path.isabs(file):
857 # Try to make the filename absolute by trying all
858 # Try to make the filename absolute by trying all
858 # sys.path entries (which is also what linecache does)
859 # sys.path entries (which is also what linecache does)
859 for dirname in sys.path:
860 for dirname in sys.path:
860 try:
861 try:
861 fullname = os.path.join(dirname, file)
862 fullname = os.path.join(dirname, file)
862 if os.path.isfile(fullname):
863 if os.path.isfile(fullname):
863 file = os.path.abspath(fullname)
864 file = os.path.abspath(fullname)
864 break
865 break
865 except Exception:
866 except Exception:
866 # Just in case that sys.path contains very
867 # Just in case that sys.path contains very
867 # strange entries...
868 # strange entries...
868 pass
869 pass
869
870
870 file = py3compat.cast_unicode(file, util_path.fs_encoding)
871 file = py3compat.cast_unicode(file, util_path.fs_encoding)
871 link = tpl_link % util_path.compress_user(file)
872 link = tpl_link % util_path.compress_user(file)
872 args, varargs, varkw, locals = inspect.getargvalues(frame)
873 args, varargs, varkw, locals = inspect.getargvalues(frame)
873
874
874 if func == '?':
875 if func == '?':
875 call = ''
876 call = ''
876 else:
877 else:
877 # Decide whether to include variable details or not
878 # Decide whether to include variable details or not
878 var_repr = self.include_vars and eqrepr or nullrepr
879 var_repr = self.include_vars and eqrepr or nullrepr
879 try:
880 try:
880 call = tpl_call % (func, inspect.formatargvalues(args,
881 call = tpl_call % (func, inspect.formatargvalues(args,
881 varargs, varkw,
882 varargs, varkw,
882 locals, formatvalue=var_repr))
883 locals, formatvalue=var_repr))
883 except KeyError:
884 except KeyError:
884 # This happens in situations like errors inside generator
885 # This happens in situations like errors inside generator
885 # expressions, where local variables are listed in the
886 # expressions, where local variables are listed in the
886 # line, but can't be extracted from the frame. I'm not
887 # line, but can't be extracted from the frame. I'm not
887 # 100% sure this isn't actually a bug in inspect itself,
888 # 100% sure this isn't actually a bug in inspect itself,
888 # but since there's no info for us to compute with, the
889 # but since there's no info for us to compute with, the
889 # best we can do is report the failure and move on. Here
890 # best we can do is report the failure and move on. Here
890 # we must *not* call any traceback construction again,
891 # we must *not* call any traceback construction again,
891 # because that would mess up use of %debug later on. So we
892 # because that would mess up use of %debug later on. So we
892 # simply report the failure and move on. The only
893 # simply report the failure and move on. The only
893 # limitation will be that this frame won't have locals
894 # limitation will be that this frame won't have locals
894 # listed in the call signature. Quite subtle problem...
895 # listed in the call signature. Quite subtle problem...
895 # I can't think of a good way to validate this in a unit
896 # I can't think of a good way to validate this in a unit
896 # test, but running a script consisting of:
897 # test, but running a script consisting of:
897 # dict( (k,v.strip()) for (k,v) in range(10) )
898 # dict( (k,v.strip()) for (k,v) in range(10) )
898 # will illustrate the error, if this exception catch is
899 # will illustrate the error, if this exception catch is
899 # disabled.
900 # disabled.
900 call = tpl_call_fail % func
901 call = tpl_call_fail % func
901
902
902 # Don't attempt to tokenize binary files.
903 # Don't attempt to tokenize binary files.
903 if file.endswith(('.so', '.pyd', '.dll')):
904 if file.endswith(('.so', '.pyd', '.dll')):
904 return '%s %s\n' % (link, call)
905 return '%s %s\n' % (link, call)
905
906
906 elif file.endswith(('.pyc', '.pyo')):
907 elif file.endswith(('.pyc', '.pyo')):
907 # Look up the corresponding source file.
908 # Look up the corresponding source file.
908 try:
909 try:
909 file = openpy.source_from_cache(file)
910 file = source_from_cache(file)
910 except ValueError:
911 except ValueError:
911 # Failed to get the source file for some reason
912 # Failed to get the source file for some reason
912 # E.g. https://github.com/ipython/ipython/issues/9486
913 # E.g. https://github.com/ipython/ipython/issues/9486
913 return '%s %s\n' % (link, call)
914 return '%s %s\n' % (link, call)
914
915
915 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
916 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
916 line = getline(file, lnum[0])
917 line = getline(file, lnum[0])
917 lnum[0] += 1
918 lnum[0] += 1
918 return line
919 return line
919
920
920 # Build the list of names on this line of code where the exception
921 # Build the list of names on this line of code where the exception
921 # occurred.
922 # occurred.
922 try:
923 try:
923 names = []
924 names = []
924 name_cont = False
925 name_cont = False
925
926
926 for token_type, token, start, end, line in generate_tokens(linereader):
927 for token_type, token, start, end, line in generate_tokens(linereader):
927 # build composite names
928 # build composite names
928 if token_type == tokenize.NAME and token not in keyword.kwlist:
929 if token_type == tokenize.NAME and token not in keyword.kwlist:
929 if name_cont:
930 if name_cont:
930 # Continuation of a dotted name
931 # Continuation of a dotted name
931 try:
932 try:
932 names[-1].append(token)
933 names[-1].append(token)
933 except IndexError:
934 except IndexError:
934 names.append([token])
935 names.append([token])
935 name_cont = False
936 name_cont = False
936 else:
937 else:
937 # Regular new names. We append everything, the caller
938 # Regular new names. We append everything, the caller
938 # will be responsible for pruning the list later. It's
939 # will be responsible for pruning the list later. It's
939 # very tricky to try to prune as we go, b/c composite
940 # very tricky to try to prune as we go, b/c composite
940 # names can fool us. The pruning at the end is easy
941 # names can fool us. The pruning at the end is easy
941 # to do (or the caller can print a list with repeated
942 # to do (or the caller can print a list with repeated
942 # names if so desired.
943 # names if so desired.
943 names.append([token])
944 names.append([token])
944 elif token == '.':
945 elif token == '.':
945 name_cont = True
946 name_cont = True
946 elif token_type == tokenize.NEWLINE:
947 elif token_type == tokenize.NEWLINE:
947 break
948 break
948
949
949 except (IndexError, UnicodeDecodeError, SyntaxError):
950 except (IndexError, UnicodeDecodeError, SyntaxError):
950 # signals exit of tokenizer
951 # signals exit of tokenizer
951 # SyntaxError can occur if the file is not actually Python
952 # SyntaxError can occur if the file is not actually Python
952 # - see gh-6300
953 # - see gh-6300
953 pass
954 pass
954 except tokenize.TokenError as msg:
955 except tokenize.TokenError as msg:
955 # Tokenizing may fail for various reasons, many of which are
956 # Tokenizing may fail for various reasons, many of which are
956 # harmless. (A good example is when the line in question is the
957 # harmless. (A good example is when the line in question is the
957 # close of a triple-quoted string, cf gh-6864). We don't want to
958 # close of a triple-quoted string, cf gh-6864). We don't want to
958 # show this to users, but want make it available for debugging
959 # show this to users, but want make it available for debugging
959 # purposes.
960 # purposes.
960 _m = ("An unexpected error occurred while tokenizing input\n"
961 _m = ("An unexpected error occurred while tokenizing input\n"
961 "The following traceback may be corrupted or invalid\n"
962 "The following traceback may be corrupted or invalid\n"
962 "The error message is: %s\n" % msg)
963 "The error message is: %s\n" % msg)
963 debug(_m)
964 debug(_m)
964
965
965 # Join composite names (e.g. "dict.fromkeys")
966 # Join composite names (e.g. "dict.fromkeys")
966 names = ['.'.join(n) for n in names]
967 names = ['.'.join(n) for n in names]
967 # prune names list of duplicates, but keep the right order
968 # prune names list of duplicates, but keep the right order
968 unique_names = uniq_stable(names)
969 unique_names = uniq_stable(names)
969
970
970 # Start loop over vars
971 # Start loop over vars
971 lvals = []
972 lvals = []
972 if self.include_vars:
973 if self.include_vars:
973 for name_full in unique_names:
974 for name_full in unique_names:
974 name_base = name_full.split('.', 1)[0]
975 name_base = name_full.split('.', 1)[0]
975 if name_base in frame.f_code.co_varnames:
976 if name_base in frame.f_code.co_varnames:
976 if name_base in locals:
977 if name_base in locals:
977 try:
978 try:
978 value = repr(eval(name_full, locals))
979 value = repr(eval(name_full, locals))
979 except:
980 except:
980 value = undefined
981 value = undefined
981 else:
982 else:
982 value = undefined
983 value = undefined
983 name = tpl_local_var % name_full
984 name = tpl_local_var % name_full
984 else:
985 else:
985 if name_base in frame.f_globals:
986 if name_base in frame.f_globals:
986 try:
987 try:
987 value = repr(eval(name_full, frame.f_globals))
988 value = repr(eval(name_full, frame.f_globals))
988 except:
989 except:
989 value = undefined
990 value = undefined
990 else:
991 else:
991 value = undefined
992 value = undefined
992 name = tpl_global_var % name_full
993 name = tpl_global_var % name_full
993 lvals.append(tpl_name_val % (name, value))
994 lvals.append(tpl_name_val % (name, value))
994 if lvals:
995 if lvals:
995 lvals = '%s%s' % (indent, em_normal.join(lvals))
996 lvals = '%s%s' % (indent, em_normal.join(lvals))
996 else:
997 else:
997 lvals = ''
998 lvals = ''
998
999
999 level = '%s %s\n' % (link, call)
1000 level = '%s %s\n' % (link, call)
1000
1001
1001 if index is None:
1002 if index is None:
1002 return level
1003 return level
1003 else:
1004 else:
1004 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1005 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1005 return '%s%s' % (level, ''.join(
1006 return '%s%s' % (level, ''.join(
1006 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1007 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1007 _line_format)))
1008 _line_format)))
1008
1009
1009 def prepare_chained_exception_message(self, cause):
1010 def prepare_chained_exception_message(self, cause):
1010 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1011 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1011 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1012 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1012
1013
1013 if cause:
1014 if cause:
1014 message = [[direct_cause]]
1015 message = [[direct_cause]]
1015 else:
1016 else:
1016 message = [[exception_during_handling]]
1017 message = [[exception_during_handling]]
1017 return message
1018 return message
1018
1019
1019 def prepare_header(self, etype, long_version=False):
1020 def prepare_header(self, etype, long_version=False):
1020 colors = self.Colors # just a shorthand + quicker name lookup
1021 colors = self.Colors # just a shorthand + quicker name lookup
1021 colorsnormal = colors.Normal # used a lot
1022 colorsnormal = colors.Normal # used a lot
1022 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1023 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1023 width = min(75, get_terminal_size()[0])
1024 width = min(75, get_terminal_size()[0])
1024 if long_version:
1025 if long_version:
1025 # Header with the exception type, python version, and date
1026 # Header with the exception type, python version, and date
1026 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1027 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1027 date = time.ctime(time.time())
1028 date = time.ctime(time.time())
1028
1029
1029 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1030 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1030 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1031 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1031 pyver, date.rjust(width) )
1032 pyver, date.rjust(width) )
1032 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1033 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1033 "\ncalls leading up to the error, with the most recent (innermost) call last."
1034 "\ncalls leading up to the error, with the most recent (innermost) call last."
1034 else:
1035 else:
1035 # Simplified header
1036 # Simplified header
1036 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1037 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1037 rjust(width - len(str(etype))) )
1038 rjust(width - len(str(etype))) )
1038
1039
1039 return head
1040 return head
1040
1041
1041 def format_exception(self, etype, evalue):
1042 def format_exception(self, etype, evalue):
1042 colors = self.Colors # just a shorthand + quicker name lookup
1043 colors = self.Colors # just a shorthand + quicker name lookup
1043 colorsnormal = colors.Normal # used a lot
1044 colorsnormal = colors.Normal # used a lot
1044 indent = ' ' * INDENT_SIZE
1045 indent = ' ' * INDENT_SIZE
1045 # Get (safely) a string form of the exception info
1046 # Get (safely) a string form of the exception info
1046 try:
1047 try:
1047 etype_str, evalue_str = map(str, (etype, evalue))
1048 etype_str, evalue_str = map(str, (etype, evalue))
1048 except:
1049 except:
1049 # User exception is improperly defined.
1050 # User exception is improperly defined.
1050 etype, evalue = str, sys.exc_info()[:2]
1051 etype, evalue = str, sys.exc_info()[:2]
1051 etype_str, evalue_str = map(str, (etype, evalue))
1052 etype_str, evalue_str = map(str, (etype, evalue))
1052 # ... and format it
1053 # ... and format it
1053 return ['%s%s%s: %s' % (colors.excName, etype_str,
1054 return ['%s%s%s: %s' % (colors.excName, etype_str,
1054 colorsnormal, py3compat.cast_unicode(evalue_str))]
1055 colorsnormal, py3compat.cast_unicode(evalue_str))]
1055
1056
1056 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1057 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1057 """Formats the header, traceback and exception message for a single exception.
1058 """Formats the header, traceback and exception message for a single exception.
1058
1059
1059 This may be called multiple times by Python 3 exception chaining
1060 This may be called multiple times by Python 3 exception chaining
1060 (PEP 3134).
1061 (PEP 3134).
1061 """
1062 """
1062 # some locals
1063 # some locals
1063 orig_etype = etype
1064 orig_etype = etype
1064 try:
1065 try:
1065 etype = etype.__name__
1066 etype = etype.__name__
1066 except AttributeError:
1067 except AttributeError:
1067 pass
1068 pass
1068
1069
1069 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1070 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1070 head = self.prepare_header(etype, self.long_header)
1071 head = self.prepare_header(etype, self.long_header)
1071 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1072 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1072
1073
1073 if records is None:
1074 if records is None:
1074 return ""
1075 return ""
1075
1076
1076 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1077 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1077
1078
1078 frames = self.format_records(records, last_unique, recursion_repeat)
1079 frames = self.format_records(records, last_unique, recursion_repeat)
1079
1080
1080 formatted_exception = self.format_exception(etype, evalue)
1081 formatted_exception = self.format_exception(etype, evalue)
1081 if records:
1082 if records:
1082 filepath, lnum = records[-1][1:3]
1083 filepath, lnum = records[-1][1:3]
1083 filepath = os.path.abspath(filepath)
1084 filepath = os.path.abspath(filepath)
1084 ipinst = get_ipython()
1085 ipinst = get_ipython()
1085 if ipinst is not None:
1086 if ipinst is not None:
1086 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1087 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1087
1088
1088 return [[head] + frames + [''.join(formatted_exception[0])]]
1089 return [[head] + frames + [''.join(formatted_exception[0])]]
1089
1090
1090 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1091 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1091 try:
1092 try:
1092 # Try the default getinnerframes and Alex's: Alex's fixes some
1093 # Try the default getinnerframes and Alex's: Alex's fixes some
1093 # problems, but it generates empty tracebacks for console errors
1094 # problems, but it generates empty tracebacks for console errors
1094 # (5 blanks lines) where none should be returned.
1095 # (5 blanks lines) where none should be returned.
1095 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1096 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1096 except UnicodeDecodeError:
1097 except UnicodeDecodeError:
1097 # This can occur if a file's encoding magic comment is wrong.
1098 # This can occur if a file's encoding magic comment is wrong.
1098 # I can't see a way to recover without duplicating a bunch of code
1099 # I can't see a way to recover without duplicating a bunch of code
1099 # from the stdlib traceback module. --TK
1100 # from the stdlib traceback module. --TK
1100 error('\nUnicodeDecodeError while processing traceback.\n')
1101 error('\nUnicodeDecodeError while processing traceback.\n')
1101 return None
1102 return None
1102 except:
1103 except:
1103 # FIXME: I've been getting many crash reports from python 2.3
1104 # FIXME: I've been getting many crash reports from python 2.3
1104 # users, traceable to inspect.py. If I can find a small test-case
1105 # users, traceable to inspect.py. If I can find a small test-case
1105 # to reproduce this, I should either write a better workaround or
1106 # to reproduce this, I should either write a better workaround or
1106 # file a bug report against inspect (if that's the real problem).
1107 # file a bug report against inspect (if that's the real problem).
1107 # So far, I haven't been able to find an isolated example to
1108 # So far, I haven't been able to find an isolated example to
1108 # reproduce the problem.
1109 # reproduce the problem.
1109 inspect_error()
1110 inspect_error()
1110 traceback.print_exc(file=self.ostream)
1111 traceback.print_exc(file=self.ostream)
1111 info('\nUnfortunately, your original traceback can not be constructed.\n')
1112 info('\nUnfortunately, your original traceback can not be constructed.\n')
1112 return None
1113 return None
1113
1114
1114 def get_parts_of_chained_exception(self, evalue):
1115 def get_parts_of_chained_exception(self, evalue):
1115 def get_chained_exception(exception_value):
1116 def get_chained_exception(exception_value):
1116 cause = getattr(exception_value, '__cause__', None)
1117 cause = getattr(exception_value, '__cause__', None)
1117 if cause:
1118 if cause:
1118 return cause
1119 return cause
1119 if getattr(exception_value, '__suppress_context__', False):
1120 if getattr(exception_value, '__suppress_context__', False):
1120 return None
1121 return None
1121 return getattr(exception_value, '__context__', None)
1122 return getattr(exception_value, '__context__', None)
1122
1123
1123 chained_evalue = get_chained_exception(evalue)
1124 chained_evalue = get_chained_exception(evalue)
1124
1125
1125 if chained_evalue:
1126 if chained_evalue:
1126 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1127 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1127
1128
1128 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1129 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1129 number_of_lines_of_context=5):
1130 number_of_lines_of_context=5):
1130 """Return a nice text document describing the traceback."""
1131 """Return a nice text document describing the traceback."""
1131
1132
1132 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1133 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1133 tb_offset)
1134 tb_offset)
1134
1135
1135 colors = self.Colors # just a shorthand + quicker name lookup
1136 colors = self.Colors # just a shorthand + quicker name lookup
1136 colorsnormal = colors.Normal # used a lot
1137 colorsnormal = colors.Normal # used a lot
1137 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1138 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1138 structured_traceback_parts = [head]
1139 structured_traceback_parts = [head]
1139 chained_exceptions_tb_offset = 0
1140 chained_exceptions_tb_offset = 0
1140 lines_of_context = 3
1141 lines_of_context = 3
1141 formatted_exceptions = formatted_exception
1142 formatted_exceptions = formatted_exception
1142 exception = self.get_parts_of_chained_exception(evalue)
1143 exception = self.get_parts_of_chained_exception(evalue)
1143 if exception:
1144 if exception:
1144 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1145 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1145 etype, evalue, etb = exception
1146 etype, evalue, etb = exception
1146 else:
1147 else:
1147 evalue = None
1148 evalue = None
1148 chained_exc_ids = set()
1149 chained_exc_ids = set()
1149 while evalue:
1150 while evalue:
1150 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1151 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1151 chained_exceptions_tb_offset)
1152 chained_exceptions_tb_offset)
1152 exception = self.get_parts_of_chained_exception(evalue)
1153 exception = self.get_parts_of_chained_exception(evalue)
1153
1154
1154 if exception and not id(exception[1]) in chained_exc_ids:
1155 if exception and not id(exception[1]) in chained_exc_ids:
1155 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1156 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1156 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1157 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1157 etype, evalue, etb = exception
1158 etype, evalue, etb = exception
1158 else:
1159 else:
1159 evalue = None
1160 evalue = None
1160
1161
1161 # we want to see exceptions in a reversed order:
1162 # we want to see exceptions in a reversed order:
1162 # the first exception should be on top
1163 # the first exception should be on top
1163 for formatted_exception in reversed(formatted_exceptions):
1164 for formatted_exception in reversed(formatted_exceptions):
1164 structured_traceback_parts += formatted_exception
1165 structured_traceback_parts += formatted_exception
1165
1166
1166 return structured_traceback_parts
1167 return structured_traceback_parts
1167
1168
1168 def debugger(self, force=False):
1169 def debugger(self, force=False):
1169 """Call up the pdb debugger if desired, always clean up the tb
1170 """Call up the pdb debugger if desired, always clean up the tb
1170 reference.
1171 reference.
1171
1172
1172 Keywords:
1173 Keywords:
1173
1174
1174 - force(False): by default, this routine checks the instance call_pdb
1175 - force(False): by default, this routine checks the instance call_pdb
1175 flag and does not actually invoke the debugger if the flag is false.
1176 flag and does not actually invoke the debugger if the flag is false.
1176 The 'force' option forces the debugger to activate even if the flag
1177 The 'force' option forces the debugger to activate even if the flag
1177 is false.
1178 is false.
1178
1179
1179 If the call_pdb flag is set, the pdb interactive debugger is
1180 If the call_pdb flag is set, the pdb interactive debugger is
1180 invoked. In all cases, the self.tb reference to the current traceback
1181 invoked. In all cases, the self.tb reference to the current traceback
1181 is deleted to prevent lingering references which hamper memory
1182 is deleted to prevent lingering references which hamper memory
1182 management.
1183 management.
1183
1184
1184 Note that each call to pdb() does an 'import readline', so if your app
1185 Note that each call to pdb() does an 'import readline', so if your app
1185 requires a special setup for the readline completers, you'll have to
1186 requires a special setup for the readline completers, you'll have to
1186 fix that by hand after invoking the exception handler."""
1187 fix that by hand after invoking the exception handler."""
1187
1188
1188 if force or self.call_pdb:
1189 if force or self.call_pdb:
1189 if self.pdb is None:
1190 if self.pdb is None:
1190 self.pdb = self.debugger_cls()
1191 self.pdb = self.debugger_cls()
1191 # the system displayhook may have changed, restore the original
1192 # the system displayhook may have changed, restore the original
1192 # for pdb
1193 # for pdb
1193 display_trap = DisplayTrap(hook=sys.__displayhook__)
1194 display_trap = DisplayTrap(hook=sys.__displayhook__)
1194 with display_trap:
1195 with display_trap:
1195 self.pdb.reset()
1196 self.pdb.reset()
1196 # Find the right frame so we don't pop up inside ipython itself
1197 # Find the right frame so we don't pop up inside ipython itself
1197 if hasattr(self, 'tb') and self.tb is not None:
1198 if hasattr(self, 'tb') and self.tb is not None:
1198 etb = self.tb
1199 etb = self.tb
1199 else:
1200 else:
1200 etb = self.tb = sys.last_traceback
1201 etb = self.tb = sys.last_traceback
1201 while self.tb is not None and self.tb.tb_next is not None:
1202 while self.tb is not None and self.tb.tb_next is not None:
1202 self.tb = self.tb.tb_next
1203 self.tb = self.tb.tb_next
1203 if etb and etb.tb_next:
1204 if etb and etb.tb_next:
1204 etb = etb.tb_next
1205 etb = etb.tb_next
1205 self.pdb.botframe = etb.tb_frame
1206 self.pdb.botframe = etb.tb_frame
1206 self.pdb.interaction(self.tb.tb_frame, self.tb)
1207 self.pdb.interaction(self.tb.tb_frame, self.tb)
1207
1208
1208 if hasattr(self, 'tb'):
1209 if hasattr(self, 'tb'):
1209 del self.tb
1210 del self.tb
1210
1211
1211 def handler(self, info=None):
1212 def handler(self, info=None):
1212 (etype, evalue, etb) = info or sys.exc_info()
1213 (etype, evalue, etb) = info or sys.exc_info()
1213 self.tb = etb
1214 self.tb = etb
1214 ostream = self.ostream
1215 ostream = self.ostream
1215 ostream.flush()
1216 ostream.flush()
1216 ostream.write(self.text(etype, evalue, etb))
1217 ostream.write(self.text(etype, evalue, etb))
1217 ostream.write('\n')
1218 ostream.write('\n')
1218 ostream.flush()
1219 ostream.flush()
1219
1220
1220 # Changed so an instance can just be called as VerboseTB_inst() and print
1221 # Changed so an instance can just be called as VerboseTB_inst() and print
1221 # out the right info on its own.
1222 # out the right info on its own.
1222 def __call__(self, etype=None, evalue=None, etb=None):
1223 def __call__(self, etype=None, evalue=None, etb=None):
1223 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1224 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1224 if etb is None:
1225 if etb is None:
1225 self.handler()
1226 self.handler()
1226 else:
1227 else:
1227 self.handler((etype, evalue, etb))
1228 self.handler((etype, evalue, etb))
1228 try:
1229 try:
1229 self.debugger()
1230 self.debugger()
1230 except KeyboardInterrupt:
1231 except KeyboardInterrupt:
1231 print("\nKeyboardInterrupt")
1232 print("\nKeyboardInterrupt")
1232
1233
1233
1234
1234 #----------------------------------------------------------------------------
1235 #----------------------------------------------------------------------------
1235 class FormattedTB(VerboseTB, ListTB):
1236 class FormattedTB(VerboseTB, ListTB):
1236 """Subclass ListTB but allow calling with a traceback.
1237 """Subclass ListTB but allow calling with a traceback.
1237
1238
1238 It can thus be used as a sys.excepthook for Python > 2.1.
1239 It can thus be used as a sys.excepthook for Python > 2.1.
1239
1240
1240 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1241 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1241
1242
1242 Allows a tb_offset to be specified. This is useful for situations where
1243 Allows a tb_offset to be specified. This is useful for situations where
1243 one needs to remove a number of topmost frames from the traceback (such as
1244 one needs to remove a number of topmost frames from the traceback (such as
1244 occurs with python programs that themselves execute other python code,
1245 occurs with python programs that themselves execute other python code,
1245 like Python shells). """
1246 like Python shells). """
1246
1247
1247 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1248 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1248 ostream=None,
1249 ostream=None,
1249 tb_offset=0, long_header=False, include_vars=False,
1250 tb_offset=0, long_header=False, include_vars=False,
1250 check_cache=None, debugger_cls=None,
1251 check_cache=None, debugger_cls=None,
1251 parent=None, config=None):
1252 parent=None, config=None):
1252
1253
1253 # NEVER change the order of this list. Put new modes at the end:
1254 # NEVER change the order of this list. Put new modes at the end:
1254 self.valid_modes = ['Plain', 'Context', 'Verbose']
1255 self.valid_modes = ['Plain', 'Context', 'Verbose']
1255 self.verbose_modes = self.valid_modes[1:3]
1256 self.verbose_modes = self.valid_modes[1:3]
1256
1257
1257 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1258 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1258 ostream=ostream, tb_offset=tb_offset,
1259 ostream=ostream, tb_offset=tb_offset,
1259 long_header=long_header, include_vars=include_vars,
1260 long_header=long_header, include_vars=include_vars,
1260 check_cache=check_cache, debugger_cls=debugger_cls,
1261 check_cache=check_cache, debugger_cls=debugger_cls,
1261 parent=parent, config=config)
1262 parent=parent, config=config)
1262
1263
1263 # Different types of tracebacks are joined with different separators to
1264 # Different types of tracebacks are joined with different separators to
1264 # form a single string. They are taken from this dict
1265 # form a single string. They are taken from this dict
1265 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1266 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1266 # set_mode also sets the tb_join_char attribute
1267 # set_mode also sets the tb_join_char attribute
1267 self.set_mode(mode)
1268 self.set_mode(mode)
1268
1269
1269 def _extract_tb(self, tb):
1270 def _extract_tb(self, tb):
1270 if tb:
1271 if tb:
1271 return traceback.extract_tb(tb)
1272 return traceback.extract_tb(tb)
1272 else:
1273 else:
1273 return None
1274 return None
1274
1275
1275 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1276 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1276 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1277 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1277 mode = self.mode
1278 mode = self.mode
1278 if mode in self.verbose_modes:
1279 if mode in self.verbose_modes:
1279 # Verbose modes need a full traceback
1280 # Verbose modes need a full traceback
1280 return VerboseTB.structured_traceback(
1281 return VerboseTB.structured_traceback(
1281 self, etype, value, tb, tb_offset, number_of_lines_of_context
1282 self, etype, value, tb, tb_offset, number_of_lines_of_context
1282 )
1283 )
1283 else:
1284 else:
1284 # We must check the source cache because otherwise we can print
1285 # We must check the source cache because otherwise we can print
1285 # out-of-date source code.
1286 # out-of-date source code.
1286 self.check_cache()
1287 self.check_cache()
1287 # Now we can extract and format the exception
1288 # Now we can extract and format the exception
1288 elist = self._extract_tb(tb)
1289 elist = self._extract_tb(tb)
1289 return ListTB.structured_traceback(
1290 return ListTB.structured_traceback(
1290 self, etype, value, elist, tb_offset, number_of_lines_of_context
1291 self, etype, value, elist, tb_offset, number_of_lines_of_context
1291 )
1292 )
1292
1293
1293 def stb2text(self, stb):
1294 def stb2text(self, stb):
1294 """Convert a structured traceback (a list) to a string."""
1295 """Convert a structured traceback (a list) to a string."""
1295 return self.tb_join_char.join(stb)
1296 return self.tb_join_char.join(stb)
1296
1297
1297
1298
1298 def set_mode(self, mode=None):
1299 def set_mode(self, mode=None):
1299 """Switch to the desired mode.
1300 """Switch to the desired mode.
1300
1301
1301 If mode is not specified, cycles through the available modes."""
1302 If mode is not specified, cycles through the available modes."""
1302
1303
1303 if not mode:
1304 if not mode:
1304 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1305 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1305 len(self.valid_modes)
1306 len(self.valid_modes)
1306 self.mode = self.valid_modes[new_idx]
1307 self.mode = self.valid_modes[new_idx]
1307 elif mode not in self.valid_modes:
1308 elif mode not in self.valid_modes:
1308 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1309 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1309 'Valid modes: ' + str(self.valid_modes))
1310 'Valid modes: ' + str(self.valid_modes))
1310 else:
1311 else:
1311 self.mode = mode
1312 self.mode = mode
1312 # include variable details only in 'Verbose' mode
1313 # include variable details only in 'Verbose' mode
1313 self.include_vars = (self.mode == self.valid_modes[2])
1314 self.include_vars = (self.mode == self.valid_modes[2])
1314 # Set the join character for generating text tracebacks
1315 # Set the join character for generating text tracebacks
1315 self.tb_join_char = self._join_chars[self.mode]
1316 self.tb_join_char = self._join_chars[self.mode]
1316
1317
1317 # some convenient shortcuts
1318 # some convenient shortcuts
1318 def plain(self):
1319 def plain(self):
1319 self.set_mode(self.valid_modes[0])
1320 self.set_mode(self.valid_modes[0])
1320
1321
1321 def context(self):
1322 def context(self):
1322 self.set_mode(self.valid_modes[1])
1323 self.set_mode(self.valid_modes[1])
1323
1324
1324 def verbose(self):
1325 def verbose(self):
1325 self.set_mode(self.valid_modes[2])
1326 self.set_mode(self.valid_modes[2])
1326
1327
1327
1328
1328 #----------------------------------------------------------------------------
1329 #----------------------------------------------------------------------------
1329 class AutoFormattedTB(FormattedTB):
1330 class AutoFormattedTB(FormattedTB):
1330 """A traceback printer which can be called on the fly.
1331 """A traceback printer which can be called on the fly.
1331
1332
1332 It will find out about exceptions by itself.
1333 It will find out about exceptions by itself.
1333
1334
1334 A brief example::
1335 A brief example::
1335
1336
1336 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1337 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1337 try:
1338 try:
1338 ...
1339 ...
1339 except:
1340 except:
1340 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1341 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1341 """
1342 """
1342
1343
1343 def __call__(self, etype=None, evalue=None, etb=None,
1344 def __call__(self, etype=None, evalue=None, etb=None,
1344 out=None, tb_offset=None):
1345 out=None, tb_offset=None):
1345 """Print out a formatted exception traceback.
1346 """Print out a formatted exception traceback.
1346
1347
1347 Optional arguments:
1348 Optional arguments:
1348 - out: an open file-like object to direct output to.
1349 - out: an open file-like object to direct output to.
1349
1350
1350 - tb_offset: the number of frames to skip over in the stack, on a
1351 - tb_offset: the number of frames to skip over in the stack, on a
1351 per-call basis (this overrides temporarily the instance's tb_offset
1352 per-call basis (this overrides temporarily the instance's tb_offset
1352 given at initialization time. """
1353 given at initialization time. """
1353
1354
1354 if out is None:
1355 if out is None:
1355 out = self.ostream
1356 out = self.ostream
1356 out.flush()
1357 out.flush()
1357 out.write(self.text(etype, evalue, etb, tb_offset))
1358 out.write(self.text(etype, evalue, etb, tb_offset))
1358 out.write('\n')
1359 out.write('\n')
1359 out.flush()
1360 out.flush()
1360 # FIXME: we should remove the auto pdb behavior from here and leave
1361 # FIXME: we should remove the auto pdb behavior from here and leave
1361 # that to the clients.
1362 # that to the clients.
1362 try:
1363 try:
1363 self.debugger()
1364 self.debugger()
1364 except KeyboardInterrupt:
1365 except KeyboardInterrupt:
1365 print("\nKeyboardInterrupt")
1366 print("\nKeyboardInterrupt")
1366
1367
1367 def structured_traceback(self, etype=None, value=None, tb=None,
1368 def structured_traceback(self, etype=None, value=None, tb=None,
1368 tb_offset=None, number_of_lines_of_context=5):
1369 tb_offset=None, number_of_lines_of_context=5):
1369 if etype is None:
1370 if etype is None:
1370 etype, value, tb = sys.exc_info()
1371 etype, value, tb = sys.exc_info()
1371 self.tb = tb
1372 self.tb = tb
1372 return FormattedTB.structured_traceback(
1373 return FormattedTB.structured_traceback(
1373 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1374 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1374
1375
1375
1376
1376 #---------------------------------------------------------------------------
1377 #---------------------------------------------------------------------------
1377
1378
1378 # A simple class to preserve Nathan's original functionality.
1379 # A simple class to preserve Nathan's original functionality.
1379 class ColorTB(FormattedTB):
1380 class ColorTB(FormattedTB):
1380 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1381 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1381
1382
1382 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1383 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1383 FormattedTB.__init__(self, color_scheme=color_scheme,
1384 FormattedTB.__init__(self, color_scheme=color_scheme,
1384 call_pdb=call_pdb, **kwargs)
1385 call_pdb=call_pdb, **kwargs)
1385
1386
1386
1387
1387 class SyntaxTB(ListTB):
1388 class SyntaxTB(ListTB):
1388 """Extension which holds some state: the last exception value"""
1389 """Extension which holds some state: the last exception value"""
1389
1390
1390 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1391 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1391 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1392 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1392 self.last_syntax_error = None
1393 self.last_syntax_error = None
1393
1394
1394 def __call__(self, etype, value, elist):
1395 def __call__(self, etype, value, elist):
1395 self.last_syntax_error = value
1396 self.last_syntax_error = value
1396
1397
1397 ListTB.__call__(self, etype, value, elist)
1398 ListTB.__call__(self, etype, value, elist)
1398
1399
1399 def structured_traceback(self, etype, value, elist, tb_offset=None,
1400 def structured_traceback(self, etype, value, elist, tb_offset=None,
1400 context=5):
1401 context=5):
1401 # If the source file has been edited, the line in the syntax error can
1402 # If the source file has been edited, the line in the syntax error can
1402 # be wrong (retrieved from an outdated cache). This replaces it with
1403 # be wrong (retrieved from an outdated cache). This replaces it with
1403 # the current value.
1404 # the current value.
1404 if isinstance(value, SyntaxError) \
1405 if isinstance(value, SyntaxError) \
1405 and isinstance(value.filename, str) \
1406 and isinstance(value.filename, str) \
1406 and isinstance(value.lineno, int):
1407 and isinstance(value.lineno, int):
1407 linecache.checkcache(value.filename)
1408 linecache.checkcache(value.filename)
1408 newtext = linecache.getline(value.filename, value.lineno)
1409 newtext = linecache.getline(value.filename, value.lineno)
1409 if newtext:
1410 if newtext:
1410 value.text = newtext
1411 value.text = newtext
1411 self.last_syntax_error = value
1412 self.last_syntax_error = value
1412 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1413 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1413 tb_offset=tb_offset, context=context)
1414 tb_offset=tb_offset, context=context)
1414
1415
1415 def clear_err_state(self):
1416 def clear_err_state(self):
1416 """Return the current error state and clear it"""
1417 """Return the current error state and clear it"""
1417 e = self.last_syntax_error
1418 e = self.last_syntax_error
1418 self.last_syntax_error = None
1419 self.last_syntax_error = None
1419 return e
1420 return e
1420
1421
1421 def stb2text(self, stb):
1422 def stb2text(self, stb):
1422 """Convert a structured traceback (a list) to a string."""
1423 """Convert a structured traceback (a list) to a string."""
1423 return ''.join(stb)
1424 return ''.join(stb)
1424
1425
1425
1426
1426 # some internal-use functions
1427 # some internal-use functions
1427 def text_repr(value):
1428 def text_repr(value):
1428 """Hopefully pretty robust repr equivalent."""
1429 """Hopefully pretty robust repr equivalent."""
1429 # this is pretty horrible but should always return *something*
1430 # this is pretty horrible but should always return *something*
1430 try:
1431 try:
1431 return pydoc.text.repr(value)
1432 return pydoc.text.repr(value)
1432 except KeyboardInterrupt:
1433 except KeyboardInterrupt:
1433 raise
1434 raise
1434 except:
1435 except:
1435 try:
1436 try:
1436 return repr(value)
1437 return repr(value)
1437 except KeyboardInterrupt:
1438 except KeyboardInterrupt:
1438 raise
1439 raise
1439 except:
1440 except:
1440 try:
1441 try:
1441 # all still in an except block so we catch
1442 # all still in an except block so we catch
1442 # getattr raising
1443 # getattr raising
1443 name = getattr(value, '__name__', None)
1444 name = getattr(value, '__name__', None)
1444 if name:
1445 if name:
1445 # ick, recursion
1446 # ick, recursion
1446 return text_repr(name)
1447 return text_repr(name)
1447 klass = getattr(value, '__class__', None)
1448 klass = getattr(value, '__class__', None)
1448 if klass:
1449 if klass:
1449 return '%s instance' % text_repr(klass)
1450 return '%s instance' % text_repr(klass)
1450 except KeyboardInterrupt:
1451 except KeyboardInterrupt:
1451 raise
1452 raise
1452 except:
1453 except:
1453 return 'UNRECOVERABLE REPR FAILURE'
1454 return 'UNRECOVERABLE REPR FAILURE'
1454
1455
1455
1456
1456 def eqrepr(value, repr=text_repr):
1457 def eqrepr(value, repr=text_repr):
1457 return '=%s' % repr(value)
1458 return '=%s' % repr(value)
1458
1459
1459
1460
1460 def nullrepr(value, repr=text_repr):
1461 def nullrepr(value, repr=text_repr):
1461 return ''
1462 return ''
@@ -1,524 +1,523 b''
1 """IPython extension to reload modules before executing user code.
1 """IPython extension to reload modules before executing user code.
2
2
3 ``autoreload`` reloads modules automatically before entering the execution of
3 ``autoreload`` reloads modules automatically before entering the execution of
4 code typed at the IPython prompt.
4 code typed at the IPython prompt.
5
5
6 This makes for example the following workflow possible:
6 This makes for example the following workflow possible:
7
7
8 .. sourcecode:: ipython
8 .. sourcecode:: ipython
9
9
10 In [1]: %load_ext autoreload
10 In [1]: %load_ext autoreload
11
11
12 In [2]: %autoreload 2
12 In [2]: %autoreload 2
13
13
14 In [3]: from foo import some_function
14 In [3]: from foo import some_function
15
15
16 In [4]: some_function()
16 In [4]: some_function()
17 Out[4]: 42
17 Out[4]: 42
18
18
19 In [5]: # open foo.py in an editor and change some_function to return 43
19 In [5]: # open foo.py in an editor and change some_function to return 43
20
20
21 In [6]: some_function()
21 In [6]: some_function()
22 Out[6]: 43
22 Out[6]: 43
23
23
24 The module was reloaded without reloading it explicitly, and the object
24 The module was reloaded without reloading it explicitly, and the object
25 imported with ``from foo import ...`` was also updated.
25 imported with ``from foo import ...`` was also updated.
26
26
27 Usage
27 Usage
28 =====
28 =====
29
29
30 The following magic commands are provided:
30 The following magic commands are provided:
31
31
32 ``%autoreload``
32 ``%autoreload``
33
33
34 Reload all modules (except those excluded by ``%aimport``)
34 Reload all modules (except those excluded by ``%aimport``)
35 automatically now.
35 automatically now.
36
36
37 ``%autoreload 0``
37 ``%autoreload 0``
38
38
39 Disable automatic reloading.
39 Disable automatic reloading.
40
40
41 ``%autoreload 1``
41 ``%autoreload 1``
42
42
43 Reload all modules imported with ``%aimport`` every time before
43 Reload all modules imported with ``%aimport`` every time before
44 executing the Python code typed.
44 executing the Python code typed.
45
45
46 ``%autoreload 2``
46 ``%autoreload 2``
47
47
48 Reload all modules (except those excluded by ``%aimport``) every
48 Reload all modules (except those excluded by ``%aimport``) every
49 time before executing the Python code typed.
49 time before executing the Python code typed.
50
50
51 ``%aimport``
51 ``%aimport``
52
52
53 List modules which are to be automatically imported or not to be imported.
53 List modules which are to be automatically imported or not to be imported.
54
54
55 ``%aimport foo``
55 ``%aimport foo``
56
56
57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
58
58
59 ``%aimport foo, bar``
59 ``%aimport foo, bar``
60
60
61 Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1``
61 Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1``
62
62
63 ``%aimport -foo``
63 ``%aimport -foo``
64
64
65 Mark module 'foo' to not be autoreloaded.
65 Mark module 'foo' to not be autoreloaded.
66
66
67 Caveats
67 Caveats
68 =======
68 =======
69
69
70 Reloading Python modules in a reliable way is in general difficult,
70 Reloading Python modules in a reliable way is in general difficult,
71 and unexpected things may occur. ``%autoreload`` tries to work around
71 and unexpected things may occur. ``%autoreload`` tries to work around
72 common pitfalls by replacing function code objects and parts of
72 common pitfalls by replacing function code objects and parts of
73 classes previously in the module with new versions. This makes the
73 classes previously in the module with new versions. This makes the
74 following things to work:
74 following things to work:
75
75
76 - Functions and classes imported via 'from xxx import foo' are upgraded
76 - Functions and classes imported via 'from xxx import foo' are upgraded
77 to new versions when 'xxx' is reloaded.
77 to new versions when 'xxx' is reloaded.
78
78
79 - Methods and properties of classes are upgraded on reload, so that
79 - Methods and properties of classes are upgraded on reload, so that
80 calling 'c.foo()' on an object 'c' created before the reload causes
80 calling 'c.foo()' on an object 'c' created before the reload causes
81 the new code for 'foo' to be executed.
81 the new code for 'foo' to be executed.
82
82
83 Some of the known remaining caveats are:
83 Some of the known remaining caveats are:
84
84
85 - Replacing code objects does not always succeed: changing a @property
85 - Replacing code objects does not always succeed: changing a @property
86 in a class to an ordinary method or a method to a member variable
86 in a class to an ordinary method or a method to a member variable
87 can cause problems (but in old objects only).
87 can cause problems (but in old objects only).
88
88
89 - Functions that are removed (eg. via monkey-patching) from a module
89 - Functions that are removed (eg. via monkey-patching) from a module
90 before it is reloaded are not upgraded.
90 before it is reloaded are not upgraded.
91
91
92 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
92 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
93 """
93 """
94
94
95 skip_doctest = True
95 skip_doctest = True
96
96
97 #-----------------------------------------------------------------------------
97 #-----------------------------------------------------------------------------
98 # Copyright (C) 2000 Thomas Heller
98 # Copyright (C) 2000 Thomas Heller
99 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
99 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
100 # Copyright (C) 2012 The IPython Development Team
100 # Copyright (C) 2012 The IPython Development Team
101 #
101 #
102 # Distributed under the terms of the BSD License. The full license is in
102 # Distributed under the terms of the BSD License. The full license is in
103 # the file COPYING, distributed as part of this software.
103 # the file COPYING, distributed as part of this software.
104 #-----------------------------------------------------------------------------
104 #-----------------------------------------------------------------------------
105 #
105 #
106 # This IPython module is written by Pauli Virtanen, based on the autoreload
106 # This IPython module is written by Pauli Virtanen, based on the autoreload
107 # code by Thomas Heller.
107 # code by Thomas Heller.
108
108
109 #-----------------------------------------------------------------------------
109 #-----------------------------------------------------------------------------
110 # Imports
110 # Imports
111 #-----------------------------------------------------------------------------
111 #-----------------------------------------------------------------------------
112
112
113 import os
113 import os
114 import sys
114 import sys
115 import traceback
115 import traceback
116 import types
116 import types
117 import weakref
117 import weakref
118 from importlib import import_module
118 from importlib import import_module
119 from importlib.util import source_from_cache
119 from imp import reload
120 from imp import reload
120
121
121 from IPython.utils import openpy
122
123 #------------------------------------------------------------------------------
122 #------------------------------------------------------------------------------
124 # Autoreload functionality
123 # Autoreload functionality
125 #------------------------------------------------------------------------------
124 #------------------------------------------------------------------------------
126
125
127 class ModuleReloader(object):
126 class ModuleReloader(object):
128 enabled = False
127 enabled = False
129 """Whether this reloader is enabled"""
128 """Whether this reloader is enabled"""
130
129
131 check_all = True
130 check_all = True
132 """Autoreload all modules, not just those listed in 'modules'"""
131 """Autoreload all modules, not just those listed in 'modules'"""
133
132
134 def __init__(self):
133 def __init__(self):
135 # Modules that failed to reload: {module: mtime-on-failed-reload, ...}
134 # Modules that failed to reload: {module: mtime-on-failed-reload, ...}
136 self.failed = {}
135 self.failed = {}
137 # Modules specially marked as autoreloadable.
136 # Modules specially marked as autoreloadable.
138 self.modules = {}
137 self.modules = {}
139 # Modules specially marked as not autoreloadable.
138 # Modules specially marked as not autoreloadable.
140 self.skip_modules = {}
139 self.skip_modules = {}
141 # (module-name, name) -> weakref, for replacing old code objects
140 # (module-name, name) -> weakref, for replacing old code objects
142 self.old_objects = {}
141 self.old_objects = {}
143 # Module modification timestamps
142 # Module modification timestamps
144 self.modules_mtimes = {}
143 self.modules_mtimes = {}
145
144
146 # Cache module modification times
145 # Cache module modification times
147 self.check(check_all=True, do_reload=False)
146 self.check(check_all=True, do_reload=False)
148
147
149 def mark_module_skipped(self, module_name):
148 def mark_module_skipped(self, module_name):
150 """Skip reloading the named module in the future"""
149 """Skip reloading the named module in the future"""
151 try:
150 try:
152 del self.modules[module_name]
151 del self.modules[module_name]
153 except KeyError:
152 except KeyError:
154 pass
153 pass
155 self.skip_modules[module_name] = True
154 self.skip_modules[module_name] = True
156
155
157 def mark_module_reloadable(self, module_name):
156 def mark_module_reloadable(self, module_name):
158 """Reload the named module in the future (if it is imported)"""
157 """Reload the named module in the future (if it is imported)"""
159 try:
158 try:
160 del self.skip_modules[module_name]
159 del self.skip_modules[module_name]
161 except KeyError:
160 except KeyError:
162 pass
161 pass
163 self.modules[module_name] = True
162 self.modules[module_name] = True
164
163
165 def aimport_module(self, module_name):
164 def aimport_module(self, module_name):
166 """Import a module, and mark it reloadable
165 """Import a module, and mark it reloadable
167
166
168 Returns
167 Returns
169 -------
168 -------
170 top_module : module
169 top_module : module
171 The imported module if it is top-level, or the top-level
170 The imported module if it is top-level, or the top-level
172 top_name : module
171 top_name : module
173 Name of top_module
172 Name of top_module
174
173
175 """
174 """
176 self.mark_module_reloadable(module_name)
175 self.mark_module_reloadable(module_name)
177
176
178 import_module(module_name)
177 import_module(module_name)
179 top_name = module_name.split('.')[0]
178 top_name = module_name.split('.')[0]
180 top_module = sys.modules[top_name]
179 top_module = sys.modules[top_name]
181 return top_module, top_name
180 return top_module, top_name
182
181
183 def filename_and_mtime(self, module):
182 def filename_and_mtime(self, module):
184 if not hasattr(module, '__file__') or module.__file__ is None:
183 if not hasattr(module, '__file__') or module.__file__ is None:
185 return None, None
184 return None, None
186
185
187 if getattr(module, '__name__', None) in [None, '__mp_main__', '__main__']:
186 if getattr(module, '__name__', None) in [None, '__mp_main__', '__main__']:
188 # we cannot reload(__main__) or reload(__mp_main__)
187 # we cannot reload(__main__) or reload(__mp_main__)
189 return None, None
188 return None, None
190
189
191 filename = module.__file__
190 filename = module.__file__
192 path, ext = os.path.splitext(filename)
191 path, ext = os.path.splitext(filename)
193
192
194 if ext.lower() == '.py':
193 if ext.lower() == '.py':
195 py_filename = filename
194 py_filename = filename
196 else:
195 else:
197 try:
196 try:
198 py_filename = openpy.source_from_cache(filename)
197 py_filename = source_from_cache(filename)
199 except ValueError:
198 except ValueError:
200 return None, None
199 return None, None
201
200
202 try:
201 try:
203 pymtime = os.stat(py_filename).st_mtime
202 pymtime = os.stat(py_filename).st_mtime
204 except OSError:
203 except OSError:
205 return None, None
204 return None, None
206
205
207 return py_filename, pymtime
206 return py_filename, pymtime
208
207
209 def check(self, check_all=False, do_reload=True):
208 def check(self, check_all=False, do_reload=True):
210 """Check whether some modules need to be reloaded."""
209 """Check whether some modules need to be reloaded."""
211
210
212 if not self.enabled and not check_all:
211 if not self.enabled and not check_all:
213 return
212 return
214
213
215 if check_all or self.check_all:
214 if check_all or self.check_all:
216 modules = list(sys.modules.keys())
215 modules = list(sys.modules.keys())
217 else:
216 else:
218 modules = list(self.modules.keys())
217 modules = list(self.modules.keys())
219
218
220 for modname in modules:
219 for modname in modules:
221 m = sys.modules.get(modname, None)
220 m = sys.modules.get(modname, None)
222
221
223 if modname in self.skip_modules:
222 if modname in self.skip_modules:
224 continue
223 continue
225
224
226 py_filename, pymtime = self.filename_and_mtime(m)
225 py_filename, pymtime = self.filename_and_mtime(m)
227 if py_filename is None:
226 if py_filename is None:
228 continue
227 continue
229
228
230 try:
229 try:
231 if pymtime <= self.modules_mtimes[modname]:
230 if pymtime <= self.modules_mtimes[modname]:
232 continue
231 continue
233 except KeyError:
232 except KeyError:
234 self.modules_mtimes[modname] = pymtime
233 self.modules_mtimes[modname] = pymtime
235 continue
234 continue
236 else:
235 else:
237 if self.failed.get(py_filename, None) == pymtime:
236 if self.failed.get(py_filename, None) == pymtime:
238 continue
237 continue
239
238
240 self.modules_mtimes[modname] = pymtime
239 self.modules_mtimes[modname] = pymtime
241
240
242 # If we've reached this point, we should try to reload the module
241 # If we've reached this point, we should try to reload the module
243 if do_reload:
242 if do_reload:
244 try:
243 try:
245 superreload(m, reload, self.old_objects)
244 superreload(m, reload, self.old_objects)
246 if py_filename in self.failed:
245 if py_filename in self.failed:
247 del self.failed[py_filename]
246 del self.failed[py_filename]
248 except:
247 except:
249 print("[autoreload of %s failed: %s]" % (
248 print("[autoreload of %s failed: %s]" % (
250 modname, traceback.format_exc(10)), file=sys.stderr)
249 modname, traceback.format_exc(10)), file=sys.stderr)
251 self.failed[py_filename] = pymtime
250 self.failed[py_filename] = pymtime
252
251
253 #------------------------------------------------------------------------------
252 #------------------------------------------------------------------------------
254 # superreload
253 # superreload
255 #------------------------------------------------------------------------------
254 #------------------------------------------------------------------------------
256
255
257
256
258 func_attrs = ['__code__', '__defaults__', '__doc__',
257 func_attrs = ['__code__', '__defaults__', '__doc__',
259 '__closure__', '__globals__', '__dict__']
258 '__closure__', '__globals__', '__dict__']
260
259
261
260
262 def update_function(old, new):
261 def update_function(old, new):
263 """Upgrade the code object of a function"""
262 """Upgrade the code object of a function"""
264 for name in func_attrs:
263 for name in func_attrs:
265 try:
264 try:
266 setattr(old, name, getattr(new, name))
265 setattr(old, name, getattr(new, name))
267 except (AttributeError, TypeError):
266 except (AttributeError, TypeError):
268 pass
267 pass
269
268
270
269
271 def update_class(old, new):
270 def update_class(old, new):
272 """Replace stuff in the __dict__ of a class, and upgrade
271 """Replace stuff in the __dict__ of a class, and upgrade
273 method code objects"""
272 method code objects"""
274 for key in list(old.__dict__.keys()):
273 for key in list(old.__dict__.keys()):
275 old_obj = getattr(old, key)
274 old_obj = getattr(old, key)
276 try:
275 try:
277 new_obj = getattr(new, key)
276 new_obj = getattr(new, key)
278 if old_obj == new_obj:
277 if old_obj == new_obj:
279 continue
278 continue
280 except AttributeError:
279 except AttributeError:
281 # obsolete attribute: remove it
280 # obsolete attribute: remove it
282 try:
281 try:
283 delattr(old, key)
282 delattr(old, key)
284 except (AttributeError, TypeError):
283 except (AttributeError, TypeError):
285 pass
284 pass
286 continue
285 continue
287
286
288 if update_generic(old_obj, new_obj): continue
287 if update_generic(old_obj, new_obj): continue
289
288
290 try:
289 try:
291 setattr(old, key, getattr(new, key))
290 setattr(old, key, getattr(new, key))
292 except (AttributeError, TypeError):
291 except (AttributeError, TypeError):
293 pass # skip non-writable attributes
292 pass # skip non-writable attributes
294
293
295
294
296 def update_property(old, new):
295 def update_property(old, new):
297 """Replace get/set/del functions of a property"""
296 """Replace get/set/del functions of a property"""
298 update_generic(old.fdel, new.fdel)
297 update_generic(old.fdel, new.fdel)
299 update_generic(old.fget, new.fget)
298 update_generic(old.fget, new.fget)
300 update_generic(old.fset, new.fset)
299 update_generic(old.fset, new.fset)
301
300
302
301
303 def isinstance2(a, b, typ):
302 def isinstance2(a, b, typ):
304 return isinstance(a, typ) and isinstance(b, typ)
303 return isinstance(a, typ) and isinstance(b, typ)
305
304
306
305
307 UPDATE_RULES = [
306 UPDATE_RULES = [
308 (lambda a, b: isinstance2(a, b, type),
307 (lambda a, b: isinstance2(a, b, type),
309 update_class),
308 update_class),
310 (lambda a, b: isinstance2(a, b, types.FunctionType),
309 (lambda a, b: isinstance2(a, b, types.FunctionType),
311 update_function),
310 update_function),
312 (lambda a, b: isinstance2(a, b, property),
311 (lambda a, b: isinstance2(a, b, property),
313 update_property),
312 update_property),
314 ]
313 ]
315 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
314 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
316 lambda a, b: update_function(a.__func__, b.__func__)),
315 lambda a, b: update_function(a.__func__, b.__func__)),
317 ])
316 ])
318
317
319
318
320 def update_generic(a, b):
319 def update_generic(a, b):
321 for type_check, update in UPDATE_RULES:
320 for type_check, update in UPDATE_RULES:
322 if type_check(a, b):
321 if type_check(a, b):
323 update(a, b)
322 update(a, b)
324 return True
323 return True
325 return False
324 return False
326
325
327
326
328 class StrongRef(object):
327 class StrongRef(object):
329 def __init__(self, obj):
328 def __init__(self, obj):
330 self.obj = obj
329 self.obj = obj
331 def __call__(self):
330 def __call__(self):
332 return self.obj
331 return self.obj
333
332
334
333
335 def superreload(module, reload=reload, old_objects={}):
334 def superreload(module, reload=reload, old_objects={}):
336 """Enhanced version of the builtin reload function.
335 """Enhanced version of the builtin reload function.
337
336
338 superreload remembers objects previously in the module, and
337 superreload remembers objects previously in the module, and
339
338
340 - upgrades the class dictionary of every old class in the module
339 - upgrades the class dictionary of every old class in the module
341 - upgrades the code object of every old function and method
340 - upgrades the code object of every old function and method
342 - clears the module's namespace before reloading
341 - clears the module's namespace before reloading
343
342
344 """
343 """
345
344
346 # collect old objects in the module
345 # collect old objects in the module
347 for name, obj in list(module.__dict__.items()):
346 for name, obj in list(module.__dict__.items()):
348 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
347 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
349 continue
348 continue
350 key = (module.__name__, name)
349 key = (module.__name__, name)
351 try:
350 try:
352 old_objects.setdefault(key, []).append(weakref.ref(obj))
351 old_objects.setdefault(key, []).append(weakref.ref(obj))
353 except TypeError:
352 except TypeError:
354 pass
353 pass
355
354
356 # reload module
355 # reload module
357 try:
356 try:
358 # clear namespace first from old cruft
357 # clear namespace first from old cruft
359 old_dict = module.__dict__.copy()
358 old_dict = module.__dict__.copy()
360 old_name = module.__name__
359 old_name = module.__name__
361 module.__dict__.clear()
360 module.__dict__.clear()
362 module.__dict__['__name__'] = old_name
361 module.__dict__['__name__'] = old_name
363 module.__dict__['__loader__'] = old_dict['__loader__']
362 module.__dict__['__loader__'] = old_dict['__loader__']
364 except (TypeError, AttributeError, KeyError):
363 except (TypeError, AttributeError, KeyError):
365 pass
364 pass
366
365
367 try:
366 try:
368 module = reload(module)
367 module = reload(module)
369 except:
368 except:
370 # restore module dictionary on failed reload
369 # restore module dictionary on failed reload
371 module.__dict__.update(old_dict)
370 module.__dict__.update(old_dict)
372 raise
371 raise
373
372
374 # iterate over all objects and update functions & classes
373 # iterate over all objects and update functions & classes
375 for name, new_obj in list(module.__dict__.items()):
374 for name, new_obj in list(module.__dict__.items()):
376 key = (module.__name__, name)
375 key = (module.__name__, name)
377 if key not in old_objects: continue
376 if key not in old_objects: continue
378
377
379 new_refs = []
378 new_refs = []
380 for old_ref in old_objects[key]:
379 for old_ref in old_objects[key]:
381 old_obj = old_ref()
380 old_obj = old_ref()
382 if old_obj is None: continue
381 if old_obj is None: continue
383 new_refs.append(old_ref)
382 new_refs.append(old_ref)
384 update_generic(old_obj, new_obj)
383 update_generic(old_obj, new_obj)
385
384
386 if new_refs:
385 if new_refs:
387 old_objects[key] = new_refs
386 old_objects[key] = new_refs
388 else:
387 else:
389 del old_objects[key]
388 del old_objects[key]
390
389
391 return module
390 return module
392
391
393 #------------------------------------------------------------------------------
392 #------------------------------------------------------------------------------
394 # IPython connectivity
393 # IPython connectivity
395 #------------------------------------------------------------------------------
394 #------------------------------------------------------------------------------
396
395
397 from IPython.core.magic import Magics, magics_class, line_magic
396 from IPython.core.magic import Magics, magics_class, line_magic
398
397
399 @magics_class
398 @magics_class
400 class AutoreloadMagics(Magics):
399 class AutoreloadMagics(Magics):
401 def __init__(self, *a, **kw):
400 def __init__(self, *a, **kw):
402 super(AutoreloadMagics, self).__init__(*a, **kw)
401 super(AutoreloadMagics, self).__init__(*a, **kw)
403 self._reloader = ModuleReloader()
402 self._reloader = ModuleReloader()
404 self._reloader.check_all = False
403 self._reloader.check_all = False
405 self.loaded_modules = set(sys.modules)
404 self.loaded_modules = set(sys.modules)
406
405
407 @line_magic
406 @line_magic
408 def autoreload(self, parameter_s=''):
407 def autoreload(self, parameter_s=''):
409 r"""%autoreload => Reload modules automatically
408 r"""%autoreload => Reload modules automatically
410
409
411 %autoreload
410 %autoreload
412 Reload all modules (except those excluded by %aimport) automatically
411 Reload all modules (except those excluded by %aimport) automatically
413 now.
412 now.
414
413
415 %autoreload 0
414 %autoreload 0
416 Disable automatic reloading.
415 Disable automatic reloading.
417
416
418 %autoreload 1
417 %autoreload 1
419 Reload all modules imported with %aimport every time before executing
418 Reload all modules imported with %aimport every time before executing
420 the Python code typed.
419 the Python code typed.
421
420
422 %autoreload 2
421 %autoreload 2
423 Reload all modules (except those excluded by %aimport) every time
422 Reload all modules (except those excluded by %aimport) every time
424 before executing the Python code typed.
423 before executing the Python code typed.
425
424
426 Reloading Python modules in a reliable way is in general
425 Reloading Python modules in a reliable way is in general
427 difficult, and unexpected things may occur. %autoreload tries to
426 difficult, and unexpected things may occur. %autoreload tries to
428 work around common pitfalls by replacing function code objects and
427 work around common pitfalls by replacing function code objects and
429 parts of classes previously in the module with new versions. This
428 parts of classes previously in the module with new versions. This
430 makes the following things to work:
429 makes the following things to work:
431
430
432 - Functions and classes imported via 'from xxx import foo' are upgraded
431 - Functions and classes imported via 'from xxx import foo' are upgraded
433 to new versions when 'xxx' is reloaded.
432 to new versions when 'xxx' is reloaded.
434
433
435 - Methods and properties of classes are upgraded on reload, so that
434 - Methods and properties of classes are upgraded on reload, so that
436 calling 'c.foo()' on an object 'c' created before the reload causes
435 calling 'c.foo()' on an object 'c' created before the reload causes
437 the new code for 'foo' to be executed.
436 the new code for 'foo' to be executed.
438
437
439 Some of the known remaining caveats are:
438 Some of the known remaining caveats are:
440
439
441 - Replacing code objects does not always succeed: changing a @property
440 - Replacing code objects does not always succeed: changing a @property
442 in a class to an ordinary method or a method to a member variable
441 in a class to an ordinary method or a method to a member variable
443 can cause problems (but in old objects only).
442 can cause problems (but in old objects only).
444
443
445 - Functions that are removed (eg. via monkey-patching) from a module
444 - Functions that are removed (eg. via monkey-patching) from a module
446 before it is reloaded are not upgraded.
445 before it is reloaded are not upgraded.
447
446
448 - C extension modules cannot be reloaded, and so cannot be
447 - C extension modules cannot be reloaded, and so cannot be
449 autoreloaded.
448 autoreloaded.
450
449
451 """
450 """
452 if parameter_s == '':
451 if parameter_s == '':
453 self._reloader.check(True)
452 self._reloader.check(True)
454 elif parameter_s == '0':
453 elif parameter_s == '0':
455 self._reloader.enabled = False
454 self._reloader.enabled = False
456 elif parameter_s == '1':
455 elif parameter_s == '1':
457 self._reloader.check_all = False
456 self._reloader.check_all = False
458 self._reloader.enabled = True
457 self._reloader.enabled = True
459 elif parameter_s == '2':
458 elif parameter_s == '2':
460 self._reloader.check_all = True
459 self._reloader.check_all = True
461 self._reloader.enabled = True
460 self._reloader.enabled = True
462
461
463 @line_magic
462 @line_magic
464 def aimport(self, parameter_s='', stream=None):
463 def aimport(self, parameter_s='', stream=None):
465 """%aimport => Import modules for automatic reloading.
464 """%aimport => Import modules for automatic reloading.
466
465
467 %aimport
466 %aimport
468 List modules to automatically import and not to import.
467 List modules to automatically import and not to import.
469
468
470 %aimport foo
469 %aimport foo
471 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
470 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
472
471
473 %aimport foo, bar
472 %aimport foo, bar
474 Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload 1
473 Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload 1
475
474
476 %aimport -foo
475 %aimport -foo
477 Mark module 'foo' to not be autoreloaded for %autoreload 1
476 Mark module 'foo' to not be autoreloaded for %autoreload 1
478 """
477 """
479 modname = parameter_s
478 modname = parameter_s
480 if not modname:
479 if not modname:
481 to_reload = sorted(self._reloader.modules.keys())
480 to_reload = sorted(self._reloader.modules.keys())
482 to_skip = sorted(self._reloader.skip_modules.keys())
481 to_skip = sorted(self._reloader.skip_modules.keys())
483 if stream is None:
482 if stream is None:
484 stream = sys.stdout
483 stream = sys.stdout
485 if self._reloader.check_all:
484 if self._reloader.check_all:
486 stream.write("Modules to reload:\nall-except-skipped\n")
485 stream.write("Modules to reload:\nall-except-skipped\n")
487 else:
486 else:
488 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
487 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
489 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
488 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
490 elif modname.startswith('-'):
489 elif modname.startswith('-'):
491 modname = modname[1:]
490 modname = modname[1:]
492 self._reloader.mark_module_skipped(modname)
491 self._reloader.mark_module_skipped(modname)
493 else:
492 else:
494 for _module in ([_.strip() for _ in modname.split(',')]):
493 for _module in ([_.strip() for _ in modname.split(',')]):
495 top_module, top_name = self._reloader.aimport_module(_module)
494 top_module, top_name = self._reloader.aimport_module(_module)
496
495
497 # Inject module to user namespace
496 # Inject module to user namespace
498 self.shell.push({top_name: top_module})
497 self.shell.push({top_name: top_module})
499
498
500 def pre_run_cell(self):
499 def pre_run_cell(self):
501 if self._reloader.enabled:
500 if self._reloader.enabled:
502 try:
501 try:
503 self._reloader.check()
502 self._reloader.check()
504 except:
503 except:
505 pass
504 pass
506
505
507 def post_execute_hook(self):
506 def post_execute_hook(self):
508 """Cache the modification times of any modules imported in this execution
507 """Cache the modification times of any modules imported in this execution
509 """
508 """
510 newly_loaded_modules = set(sys.modules) - self.loaded_modules
509 newly_loaded_modules = set(sys.modules) - self.loaded_modules
511 for modname in newly_loaded_modules:
510 for modname in newly_loaded_modules:
512 _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname])
511 _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname])
513 if pymtime is not None:
512 if pymtime is not None:
514 self._reloader.modules_mtimes[modname] = pymtime
513 self._reloader.modules_mtimes[modname] = pymtime
515
514
516 self.loaded_modules.update(newly_loaded_modules)
515 self.loaded_modules.update(newly_loaded_modules)
517
516
518
517
519 def load_ipython_extension(ip):
518 def load_ipython_extension(ip):
520 """Load the extension in IPython."""
519 """Load the extension in IPython."""
521 auto_reload = AutoreloadMagics(ip)
520 auto_reload = AutoreloadMagics(ip)
522 ip.register_magics(auto_reload)
521 ip.register_magics(auto_reload)
523 ip.events.register('pre_run_cell', auto_reload.pre_run_cell)
522 ip.events.register('pre_run_cell', auto_reload.pre_run_cell)
524 ip.events.register('post_execute', auto_reload.post_execute_hook)
523 ip.events.register('post_execute', auto_reload.post_execute_hook)
@@ -1,117 +1,105 b''
1 """
1 """
2 Tools to open .py files as Unicode, using the encoding specified within the file,
2 Tools to open .py files as Unicode, using the encoding specified within the file,
3 as per PEP 263.
3 as per PEP 263.
4
4
5 Much of the code is taken from the tokenize module in Python 3.2.
5 Much of the code is taken from the tokenize module in Python 3.2.
6 """
6 """
7
7
8 import io
8 import io
9 from io import TextIOWrapper, BytesIO
9 from io import TextIOWrapper, BytesIO
10 import re
10 import re
11 from tokenize import open, detect_encoding
11 from tokenize import open, detect_encoding
12
12
13 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
13 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
14 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
14 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
15
15
16 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
16 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
17 """Converts a bytes string with python source code to unicode.
17 """Converts a bytes string with python source code to unicode.
18
18
19 Unicode strings are passed through unchanged. Byte strings are checked
19 Unicode strings are passed through unchanged. Byte strings are checked
20 for the python source file encoding cookie to determine encoding.
20 for the python source file encoding cookie to determine encoding.
21 txt can be either a bytes buffer or a string containing the source
21 txt can be either a bytes buffer or a string containing the source
22 code.
22 code.
23 """
23 """
24 if isinstance(txt, str):
24 if isinstance(txt, str):
25 return txt
25 return txt
26 if isinstance(txt, bytes):
26 if isinstance(txt, bytes):
27 buffer = BytesIO(txt)
27 buffer = BytesIO(txt)
28 else:
28 else:
29 buffer = txt
29 buffer = txt
30 try:
30 try:
31 encoding, _ = detect_encoding(buffer.readline)
31 encoding, _ = detect_encoding(buffer.readline)
32 except SyntaxError:
32 except SyntaxError:
33 encoding = "ascii"
33 encoding = "ascii"
34 buffer.seek(0)
34 buffer.seek(0)
35 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
35 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
36 text.mode = 'r'
36 text.mode = 'r'
37 if skip_encoding_cookie:
37 if skip_encoding_cookie:
38 return u"".join(strip_encoding_cookie(text))
38 return u"".join(strip_encoding_cookie(text))
39 else:
39 else:
40 return text.read()
40 return text.read()
41
41
42 def strip_encoding_cookie(filelike):
42 def strip_encoding_cookie(filelike):
43 """Generator to pull lines from a text-mode file, skipping the encoding
43 """Generator to pull lines from a text-mode file, skipping the encoding
44 cookie if it is found in the first two lines.
44 cookie if it is found in the first two lines.
45 """
45 """
46 it = iter(filelike)
46 it = iter(filelike)
47 try:
47 try:
48 first = next(it)
48 first = next(it)
49 if not cookie_comment_re.match(first):
49 if not cookie_comment_re.match(first):
50 yield first
50 yield first
51 second = next(it)
51 second = next(it)
52 if not cookie_comment_re.match(second):
52 if not cookie_comment_re.match(second):
53 yield second
53 yield second
54 except StopIteration:
54 except StopIteration:
55 return
55 return
56
56
57 for line in it:
57 for line in it:
58 yield line
58 yield line
59
59
60 def read_py_file(filename, skip_encoding_cookie=True):
60 def read_py_file(filename, skip_encoding_cookie=True):
61 """Read a Python file, using the encoding declared inside the file.
61 """Read a Python file, using the encoding declared inside the file.
62
62
63 Parameters
63 Parameters
64 ----------
64 ----------
65 filename : str
65 filename : str
66 The path to the file to read.
66 The path to the file to read.
67 skip_encoding_cookie : bool
67 skip_encoding_cookie : bool
68 If True (the default), and the encoding declaration is found in the first
68 If True (the default), and the encoding declaration is found in the first
69 two lines, that line will be excluded from the output - compiling a
69 two lines, that line will be excluded from the output - compiling a
70 unicode string with an encoding declaration is a SyntaxError in Python 2.
70 unicode string with an encoding declaration is a SyntaxError in Python 2.
71
71
72 Returns
72 Returns
73 -------
73 -------
74 A unicode string containing the contents of the file.
74 A unicode string containing the contents of the file.
75 """
75 """
76 with open(filename) as f: # the open function defined in this module.
76 with open(filename) as f: # the open function defined in this module.
77 if skip_encoding_cookie:
77 if skip_encoding_cookie:
78 return "".join(strip_encoding_cookie(f))
78 return "".join(strip_encoding_cookie(f))
79 else:
79 else:
80 return f.read()
80 return f.read()
81
81
82 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
82 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
83 """Read a Python file from a URL, using the encoding declared inside the file.
83 """Read a Python file from a URL, using the encoding declared inside the file.
84
84
85 Parameters
85 Parameters
86 ----------
86 ----------
87 url : str
87 url : str
88 The URL from which to fetch the file.
88 The URL from which to fetch the file.
89 errors : str
89 errors : str
90 How to handle decoding errors in the file. Options are the same as for
90 How to handle decoding errors in the file. Options are the same as for
91 bytes.decode(), but here 'replace' is the default.
91 bytes.decode(), but here 'replace' is the default.
92 skip_encoding_cookie : bool
92 skip_encoding_cookie : bool
93 If True (the default), and the encoding declaration is found in the first
93 If True (the default), and the encoding declaration is found in the first
94 two lines, that line will be excluded from the output - compiling a
94 two lines, that line will be excluded from the output - compiling a
95 unicode string with an encoding declaration is a SyntaxError in Python 2.
95 unicode string with an encoding declaration is a SyntaxError in Python 2.
96
96
97 Returns
97 Returns
98 -------
98 -------
99 A unicode string containing the contents of the file.
99 A unicode string containing the contents of the file.
100 """
100 """
101 # Deferred import for faster start
101 # Deferred import for faster start
102 from urllib.request import urlopen
102 from urllib.request import urlopen
103 response = urlopen(url)
103 response = urlopen(url)
104 buffer = io.BytesIO(response.read())
104 buffer = io.BytesIO(response.read())
105 return source_to_unicode(buffer, errors, skip_encoding_cookie)
105 return source_to_unicode(buffer, errors, skip_encoding_cookie)
106
107 def _list_readline(x):
108 """Given a list, returns a readline() function that returns the next element
109 with each call.
110 """
111 x = iter(x)
112 def readline():
113 return next(x)
114 return readline
115
116 # Code for going between .py files and cached .pyc files ----------------------
117 from importlib.util import source_from_cache, cache_from_source
@@ -1,39 +1,31 b''
1 import io
1 import io
2 import os.path
2 import os.path
3 import nose.tools as nt
3 import nose.tools as nt
4
4
5 from IPython.utils import openpy
5 from IPython.utils import openpy
6
6
7 mydir = os.path.dirname(__file__)
7 mydir = os.path.dirname(__file__)
8 nonascii_path = os.path.join(mydir, '../../core/tests/nonascii.py')
8 nonascii_path = os.path.join(mydir, '../../core/tests/nonascii.py')
9
9
10 def test_detect_encoding():
10 def test_detect_encoding():
11 f = open(nonascii_path, 'rb')
11 f = open(nonascii_path, 'rb')
12 enc, lines = openpy.detect_encoding(f.readline)
12 enc, lines = openpy.detect_encoding(f.readline)
13 nt.assert_equal(enc, 'iso-8859-5')
13 nt.assert_equal(enc, 'iso-8859-5')
14
14
15 def test_read_file():
15 def test_read_file():
16 read_specified_enc = io.open(nonascii_path, encoding='iso-8859-5').read()
16 read_specified_enc = io.open(nonascii_path, encoding='iso-8859-5').read()
17 read_detected_enc = openpy.read_py_file(nonascii_path, skip_encoding_cookie=False)
17 read_detected_enc = openpy.read_py_file(nonascii_path, skip_encoding_cookie=False)
18 nt.assert_equal(read_detected_enc, read_specified_enc)
18 nt.assert_equal(read_detected_enc, read_specified_enc)
19 assert u'coding: iso-8859-5' in read_detected_enc
19 assert u'coding: iso-8859-5' in read_detected_enc
20
20
21 read_strip_enc_cookie = openpy.read_py_file(nonascii_path, skip_encoding_cookie=True)
21 read_strip_enc_cookie = openpy.read_py_file(nonascii_path, skip_encoding_cookie=True)
22 assert u'coding: iso-8859-5' not in read_strip_enc_cookie
22 assert u'coding: iso-8859-5' not in read_strip_enc_cookie
23
23
24 def test_source_to_unicode():
24 def test_source_to_unicode():
25 with io.open(nonascii_path, 'rb') as f:
25 with io.open(nonascii_path, 'rb') as f:
26 source_bytes = f.read()
26 source_bytes = f.read()
27 nt.assert_equal(openpy.source_to_unicode(source_bytes, skip_encoding_cookie=False).splitlines(),
27 nt.assert_equal(openpy.source_to_unicode(source_bytes, skip_encoding_cookie=False).splitlines(),
28 source_bytes.decode('iso-8859-5').splitlines())
28 source_bytes.decode('iso-8859-5').splitlines())
29
29
30 source_no_cookie = openpy.source_to_unicode(source_bytes, skip_encoding_cookie=True)
30 source_no_cookie = openpy.source_to_unicode(source_bytes, skip_encoding_cookie=True)
31 nt.assert_not_in(u'coding: iso-8859-5', source_no_cookie)
31 nt.assert_not_in(u'coding: iso-8859-5', source_no_cookie)
32
33 def test_list_readline():
34 l = ['a', 'b']
35 readline = openpy._list_readline(l)
36 nt.assert_equal(readline(), 'a')
37 nt.assert_equal(readline(), 'b')
38 with nt.assert_raises(StopIteration):
39 readline() No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now