##// END OF EJS Templates
Prepend In [x] in traceback with "Input " to avoid messing doctest...
Matthias Bussonnier -
Show More
@@ -1,1132 +1,1132 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 unencrypted
44 potentially leak sensitive information like access keys, or unencrypted
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 inspect
92 import inspect
93 import linecache
93 import linecache
94 import pydoc
94 import pydoc
95 import sys
95 import sys
96 import time
96 import time
97 import traceback
97 import traceback
98
98
99 import stack_data
99 import stack_data
100 from pygments.formatters.terminal256 import Terminal256Formatter
100 from pygments.formatters.terminal256 import Terminal256Formatter
101 from pygments.styles import get_style_by_name
101 from pygments.styles import get_style_by_name
102
102
103 # IPython's own modules
103 # IPython's own modules
104 from IPython import get_ipython
104 from IPython import get_ipython
105 from IPython.core import debugger
105 from IPython.core import debugger
106 from IPython.core.display_trap import DisplayTrap
106 from IPython.core.display_trap import DisplayTrap
107 from IPython.core.excolors import exception_colors
107 from IPython.core.excolors import exception_colors
108 from IPython.utils import path as util_path
108 from IPython.utils import path as util_path
109 from IPython.utils import py3compat
109 from IPython.utils import py3compat
110 from IPython.utils.terminal import get_terminal_size
110 from IPython.utils.terminal import get_terminal_size
111
111
112 import IPython.utils.colorable as colorable
112 import IPython.utils.colorable as colorable
113
113
114 # Globals
114 # Globals
115 # amount of space to put line numbers before verbose tracebacks
115 # amount of space to put line numbers before verbose tracebacks
116 INDENT_SIZE = 8
116 INDENT_SIZE = 8
117
117
118 # Default color scheme. This is used, for example, by the traceback
118 # Default color scheme. This is used, for example, by the traceback
119 # formatter. When running in an actual IPython instance, the user's rc.colors
119 # formatter. When running in an actual IPython instance, the user's rc.colors
120 # value is used, but having a module global makes this functionality available
120 # value is used, but having a module global makes this functionality available
121 # to users of ultratb who are NOT running inside ipython.
121 # to users of ultratb who are NOT running inside ipython.
122 DEFAULT_SCHEME = 'NoColor'
122 DEFAULT_SCHEME = 'NoColor'
123
123
124 # ---------------------------------------------------------------------------
124 # ---------------------------------------------------------------------------
125 # Code begins
125 # Code begins
126
126
127 # Helper function -- largely belongs to VerboseTB, but we need the same
127 # Helper function -- largely belongs to VerboseTB, but we need the same
128 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
128 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
129 # can be recognized properly by ipython.el's py-traceback-line-re
129 # can be recognized properly by ipython.el's py-traceback-line-re
130 # (SyntaxErrors have to be treated specially because they have no traceback)
130 # (SyntaxErrors have to be treated specially because they have no traceback)
131
131
132
132
133 def _format_traceback_lines(lines, Colors, has_colors, lvals):
133 def _format_traceback_lines(lines, Colors, has_colors, lvals):
134 """
134 """
135 Format tracebacks lines with pointing arrow, leading numbers...
135 Format tracebacks lines with pointing arrow, leading numbers...
136
136
137 Parameters
137 Parameters
138 ----------
138 ----------
139 lines : list[Line]
139 lines : list[Line]
140 Colors
140 Colors
141 ColorScheme used.
141 ColorScheme used.
142 lvals : str
142 lvals : str
143 Values of local variables, already colored, to inject just after the error line.
143 Values of local variables, already colored, to inject just after the error line.
144 """
144 """
145 numbers_width = INDENT_SIZE - 1
145 numbers_width = INDENT_SIZE - 1
146 res = []
146 res = []
147
147
148 for stack_line in lines:
148 for stack_line in lines:
149 if stack_line is stack_data.LINE_GAP:
149 if stack_line is stack_data.LINE_GAP:
150 res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal))
150 res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal))
151 continue
151 continue
152
152
153 line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n'
153 line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n'
154 lineno = stack_line.lineno
154 lineno = stack_line.lineno
155 if stack_line.is_current:
155 if stack_line.is_current:
156 # This is the line with the error
156 # This is the line with the error
157 pad = numbers_width - len(str(lineno))
157 pad = numbers_width - len(str(lineno))
158 num = '%s%s' % (debugger.make_arrow(pad), str(lineno))
158 num = '%s%s' % (debugger.make_arrow(pad), str(lineno))
159 start_color = Colors.linenoEm
159 start_color = Colors.linenoEm
160 else:
160 else:
161 num = '%*s' % (numbers_width, lineno)
161 num = '%*s' % (numbers_width, lineno)
162 start_color = Colors.lineno
162 start_color = Colors.lineno
163
163
164 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
164 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
165
165
166 res.append(line)
166 res.append(line)
167 if lvals and stack_line.is_current:
167 if lvals and stack_line.is_current:
168 res.append(lvals + '\n')
168 res.append(lvals + '\n')
169 return res
169 return res
170
170
171
171
172 def _format_filename(file, ColorFilename, ColorNormal):
172 def _format_filename(file, ColorFilename, ColorNormal):
173 """
173 """
174 Format filename lines with `In [n]` if it's the nth code cell or `File *.py` if it's a module.
174 Format filename lines with `In [n]` if it's the nth code cell or `File *.py` if it's a module.
175
175
176 Parameters
176 Parameters
177 ----------
177 ----------
178 file : str
178 file : str
179 ColorFilename
179 ColorFilename
180 ColorScheme's filename coloring to be used.
180 ColorScheme's filename coloring to be used.
181 ColorNormal
181 ColorNormal
182 ColorScheme's normal coloring to be used.
182 ColorScheme's normal coloring to be used.
183 """
183 """
184 ipinst = get_ipython()
184 ipinst = get_ipython()
185
185
186 if ipinst is not None and file in ipinst.compile._filename_map:
186 if ipinst is not None and file in ipinst.compile._filename_map:
187 file = "[%s]" % ipinst.compile._filename_map[file]
187 file = "[%s]" % ipinst.compile._filename_map[file]
188 tpl_link = "In %s%%s%s" % (ColorFilename, ColorNormal)
188 tpl_link = "Input %sIn %%s%s" % (ColorFilename, ColorNormal)
189 else:
189 else:
190 file = util_path.compress_user(
190 file = util_path.compress_user(
191 py3compat.cast_unicode(file, util_path.fs_encoding)
191 py3compat.cast_unicode(file, util_path.fs_encoding)
192 )
192 )
193 tpl_link = "File %s%%s%s" % (ColorFilename, ColorNormal)
193 tpl_link = "File %s%%s%s" % (ColorFilename, ColorNormal)
194
194
195 return tpl_link % file
195 return tpl_link % file
196
196
197 #---------------------------------------------------------------------------
197 #---------------------------------------------------------------------------
198 # Module classes
198 # Module classes
199 class TBTools(colorable.Colorable):
199 class TBTools(colorable.Colorable):
200 """Basic tools used by all traceback printer classes."""
200 """Basic tools used by all traceback printer classes."""
201
201
202 # Number of frames to skip when reporting tracebacks
202 # Number of frames to skip when reporting tracebacks
203 tb_offset = 0
203 tb_offset = 0
204
204
205 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
205 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
206 # Whether to call the interactive pdb debugger after printing
206 # Whether to call the interactive pdb debugger after printing
207 # tracebacks or not
207 # tracebacks or not
208 super(TBTools, self).__init__(parent=parent, config=config)
208 super(TBTools, self).__init__(parent=parent, config=config)
209 self.call_pdb = call_pdb
209 self.call_pdb = call_pdb
210
210
211 # Output stream to write to. Note that we store the original value in
211 # Output stream to write to. Note that we store the original value in
212 # a private attribute and then make the public ostream a property, so
212 # a private attribute and then make the public ostream a property, so
213 # that we can delay accessing sys.stdout until runtime. The way
213 # that we can delay accessing sys.stdout until runtime. The way
214 # things are written now, the sys.stdout object is dynamically managed
214 # things are written now, the sys.stdout object is dynamically managed
215 # so a reference to it should NEVER be stored statically. This
215 # so a reference to it should NEVER be stored statically. This
216 # property approach confines this detail to a single location, and all
216 # property approach confines this detail to a single location, and all
217 # subclasses can simply access self.ostream for writing.
217 # subclasses can simply access self.ostream for writing.
218 self._ostream = ostream
218 self._ostream = ostream
219
219
220 # Create color table
220 # Create color table
221 self.color_scheme_table = exception_colors()
221 self.color_scheme_table = exception_colors()
222
222
223 self.set_colors(color_scheme)
223 self.set_colors(color_scheme)
224 self.old_scheme = color_scheme # save initial value for toggles
224 self.old_scheme = color_scheme # save initial value for toggles
225
225
226 if call_pdb:
226 if call_pdb:
227 self.pdb = debugger.Pdb()
227 self.pdb = debugger.Pdb()
228 else:
228 else:
229 self.pdb = None
229 self.pdb = None
230
230
231 def _get_ostream(self):
231 def _get_ostream(self):
232 """Output stream that exceptions are written to.
232 """Output stream that exceptions are written to.
233
233
234 Valid values are:
234 Valid values are:
235
235
236 - None: the default, which means that IPython will dynamically resolve
236 - None: the default, which means that IPython will dynamically resolve
237 to sys.stdout. This ensures compatibility with most tools, including
237 to sys.stdout. This ensures compatibility with most tools, including
238 Windows (where plain stdout doesn't recognize ANSI escapes).
238 Windows (where plain stdout doesn't recognize ANSI escapes).
239
239
240 - Any object with 'write' and 'flush' attributes.
240 - Any object with 'write' and 'flush' attributes.
241 """
241 """
242 return sys.stdout if self._ostream is None else self._ostream
242 return sys.stdout if self._ostream is None else self._ostream
243
243
244 def _set_ostream(self, val):
244 def _set_ostream(self, val):
245 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
245 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
246 self._ostream = val
246 self._ostream = val
247
247
248 ostream = property(_get_ostream, _set_ostream)
248 ostream = property(_get_ostream, _set_ostream)
249
249
250 def get_parts_of_chained_exception(self, evalue):
250 def get_parts_of_chained_exception(self, evalue):
251 def get_chained_exception(exception_value):
251 def get_chained_exception(exception_value):
252 cause = getattr(exception_value, '__cause__', None)
252 cause = getattr(exception_value, '__cause__', None)
253 if cause:
253 if cause:
254 return cause
254 return cause
255 if getattr(exception_value, '__suppress_context__', False):
255 if getattr(exception_value, '__suppress_context__', False):
256 return None
256 return None
257 return getattr(exception_value, '__context__', None)
257 return getattr(exception_value, '__context__', None)
258
258
259 chained_evalue = get_chained_exception(evalue)
259 chained_evalue = get_chained_exception(evalue)
260
260
261 if chained_evalue:
261 if chained_evalue:
262 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
262 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
263
263
264 def prepare_chained_exception_message(self, cause):
264 def prepare_chained_exception_message(self, cause):
265 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
265 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
266 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
266 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
267
267
268 if cause:
268 if cause:
269 message = [[direct_cause]]
269 message = [[direct_cause]]
270 else:
270 else:
271 message = [[exception_during_handling]]
271 message = [[exception_during_handling]]
272 return message
272 return message
273
273
274 @property
274 @property
275 def has_colors(self):
275 def has_colors(self):
276 return self.color_scheme_table.active_scheme_name.lower() != "nocolor"
276 return self.color_scheme_table.active_scheme_name.lower() != "nocolor"
277
277
278 def set_colors(self, *args, **kw):
278 def set_colors(self, *args, **kw):
279 """Shorthand access to the color table scheme selector method."""
279 """Shorthand access to the color table scheme selector method."""
280
280
281 # Set own color table
281 # Set own color table
282 self.color_scheme_table.set_active_scheme(*args, **kw)
282 self.color_scheme_table.set_active_scheme(*args, **kw)
283 # for convenience, set Colors to the active scheme
283 # for convenience, set Colors to the active scheme
284 self.Colors = self.color_scheme_table.active_colors
284 self.Colors = self.color_scheme_table.active_colors
285 # Also set colors of debugger
285 # Also set colors of debugger
286 if hasattr(self, 'pdb') and self.pdb is not None:
286 if hasattr(self, 'pdb') and self.pdb is not None:
287 self.pdb.set_colors(*args, **kw)
287 self.pdb.set_colors(*args, **kw)
288
288
289 def color_toggle(self):
289 def color_toggle(self):
290 """Toggle between the currently active color scheme and NoColor."""
290 """Toggle between the currently active color scheme and NoColor."""
291
291
292 if self.color_scheme_table.active_scheme_name == 'NoColor':
292 if self.color_scheme_table.active_scheme_name == 'NoColor':
293 self.color_scheme_table.set_active_scheme(self.old_scheme)
293 self.color_scheme_table.set_active_scheme(self.old_scheme)
294 self.Colors = self.color_scheme_table.active_colors
294 self.Colors = self.color_scheme_table.active_colors
295 else:
295 else:
296 self.old_scheme = self.color_scheme_table.active_scheme_name
296 self.old_scheme = self.color_scheme_table.active_scheme_name
297 self.color_scheme_table.set_active_scheme('NoColor')
297 self.color_scheme_table.set_active_scheme('NoColor')
298 self.Colors = self.color_scheme_table.active_colors
298 self.Colors = self.color_scheme_table.active_colors
299
299
300 def stb2text(self, stb):
300 def stb2text(self, stb):
301 """Convert a structured traceback (a list) to a string."""
301 """Convert a structured traceback (a list) to a string."""
302 return '\n'.join(stb)
302 return '\n'.join(stb)
303
303
304 def text(self, etype, value, tb, tb_offset=None, context=5):
304 def text(self, etype, value, tb, tb_offset=None, context=5):
305 """Return formatted traceback.
305 """Return formatted traceback.
306
306
307 Subclasses may override this if they add extra arguments.
307 Subclasses may override this if they add extra arguments.
308 """
308 """
309 tb_list = self.structured_traceback(etype, value, tb,
309 tb_list = self.structured_traceback(etype, value, tb,
310 tb_offset, context)
310 tb_offset, context)
311 return self.stb2text(tb_list)
311 return self.stb2text(tb_list)
312
312
313 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
313 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
314 context=5, mode=None):
314 context=5, mode=None):
315 """Return a list of traceback frames.
315 """Return a list of traceback frames.
316
316
317 Must be implemented by each class.
317 Must be implemented by each class.
318 """
318 """
319 raise NotImplementedError()
319 raise NotImplementedError()
320
320
321
321
322 #---------------------------------------------------------------------------
322 #---------------------------------------------------------------------------
323 class ListTB(TBTools):
323 class ListTB(TBTools):
324 """Print traceback information from a traceback list, with optional color.
324 """Print traceback information from a traceback list, with optional color.
325
325
326 Calling requires 3 arguments: (etype, evalue, elist)
326 Calling requires 3 arguments: (etype, evalue, elist)
327 as would be obtained by::
327 as would be obtained by::
328
328
329 etype, evalue, tb = sys.exc_info()
329 etype, evalue, tb = sys.exc_info()
330 if tb:
330 if tb:
331 elist = traceback.extract_tb(tb)
331 elist = traceback.extract_tb(tb)
332 else:
332 else:
333 elist = None
333 elist = None
334
334
335 It can thus be used by programs which need to process the traceback before
335 It can thus be used by programs which need to process the traceback before
336 printing (such as console replacements based on the code module from the
336 printing (such as console replacements based on the code module from the
337 standard library).
337 standard library).
338
338
339 Because they are meant to be called without a full traceback (only a
339 Because they are meant to be called without a full traceback (only a
340 list), instances of this class can't call the interactive pdb debugger."""
340 list), instances of this class can't call the interactive pdb debugger."""
341
341
342 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
342 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
343 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
343 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
344 ostream=ostream, parent=parent,config=config)
344 ostream=ostream, parent=parent,config=config)
345
345
346 def __call__(self, etype, value, elist):
346 def __call__(self, etype, value, elist):
347 self.ostream.flush()
347 self.ostream.flush()
348 self.ostream.write(self.text(etype, value, elist))
348 self.ostream.write(self.text(etype, value, elist))
349 self.ostream.write('\n')
349 self.ostream.write('\n')
350
350
351 def _extract_tb(self, tb):
351 def _extract_tb(self, tb):
352 if tb:
352 if tb:
353 return traceback.extract_tb(tb)
353 return traceback.extract_tb(tb)
354 else:
354 else:
355 return None
355 return None
356
356
357 def structured_traceback(self, etype, evalue, etb=None, tb_offset=None,
357 def structured_traceback(self, etype, evalue, etb=None, tb_offset=None,
358 context=5):
358 context=5):
359 """Return a color formatted string with the traceback info.
359 """Return a color formatted string with the traceback info.
360
360
361 Parameters
361 Parameters
362 ----------
362 ----------
363 etype : exception type
363 etype : exception type
364 Type of the exception raised.
364 Type of the exception raised.
365 evalue : object
365 evalue : object
366 Data stored in the exception
366 Data stored in the exception
367 etb : object
367 etb : object
368 If list: List of frames, see class docstring for details.
368 If list: List of frames, see class docstring for details.
369 If Traceback: Traceback of the exception.
369 If Traceback: Traceback of the exception.
370 tb_offset : int, optional
370 tb_offset : int, optional
371 Number of frames in the traceback to skip. If not given, the
371 Number of frames in the traceback to skip. If not given, the
372 instance evalue is used (set in constructor).
372 instance evalue is used (set in constructor).
373 context : int, optional
373 context : int, optional
374 Number of lines of context information to print.
374 Number of lines of context information to print.
375
375
376 Returns
376 Returns
377 -------
377 -------
378 String with formatted exception.
378 String with formatted exception.
379 """
379 """
380 # This is a workaround to get chained_exc_ids in recursive calls
380 # This is a workaround to get chained_exc_ids in recursive calls
381 # etb should not be a tuple if structured_traceback is not recursive
381 # etb should not be a tuple if structured_traceback is not recursive
382 if isinstance(etb, tuple):
382 if isinstance(etb, tuple):
383 etb, chained_exc_ids = etb
383 etb, chained_exc_ids = etb
384 else:
384 else:
385 chained_exc_ids = set()
385 chained_exc_ids = set()
386
386
387 if isinstance(etb, list):
387 if isinstance(etb, list):
388 elist = etb
388 elist = etb
389 elif etb is not None:
389 elif etb is not None:
390 elist = self._extract_tb(etb)
390 elist = self._extract_tb(etb)
391 else:
391 else:
392 elist = []
392 elist = []
393 tb_offset = self.tb_offset if tb_offset is None else tb_offset
393 tb_offset = self.tb_offset if tb_offset is None else tb_offset
394 Colors = self.Colors
394 Colors = self.Colors
395 out_list = []
395 out_list = []
396 if elist:
396 if elist:
397
397
398 if tb_offset and len(elist) > tb_offset:
398 if tb_offset and len(elist) > tb_offset:
399 elist = elist[tb_offset:]
399 elist = elist[tb_offset:]
400
400
401 out_list.append('Traceback %s(most recent call last)%s:' %
401 out_list.append('Traceback %s(most recent call last)%s:' %
402 (Colors.normalEm, Colors.Normal) + '\n')
402 (Colors.normalEm, Colors.Normal) + '\n')
403 out_list.extend(self._format_list(elist))
403 out_list.extend(self._format_list(elist))
404 # The exception info should be a single entry in the list.
404 # The exception info should be a single entry in the list.
405 lines = ''.join(self._format_exception_only(etype, evalue))
405 lines = ''.join(self._format_exception_only(etype, evalue))
406 out_list.append(lines)
406 out_list.append(lines)
407
407
408 exception = self.get_parts_of_chained_exception(evalue)
408 exception = self.get_parts_of_chained_exception(evalue)
409
409
410 if exception and not id(exception[1]) in chained_exc_ids:
410 if exception and not id(exception[1]) in chained_exc_ids:
411 chained_exception_message = self.prepare_chained_exception_message(
411 chained_exception_message = self.prepare_chained_exception_message(
412 evalue.__cause__)[0]
412 evalue.__cause__)[0]
413 etype, evalue, etb = exception
413 etype, evalue, etb = exception
414 # Trace exception to avoid infinite 'cause' loop
414 # Trace exception to avoid infinite 'cause' loop
415 chained_exc_ids.add(id(exception[1]))
415 chained_exc_ids.add(id(exception[1]))
416 chained_exceptions_tb_offset = 0
416 chained_exceptions_tb_offset = 0
417 out_list = (
417 out_list = (
418 self.structured_traceback(
418 self.structured_traceback(
419 etype, evalue, (etb, chained_exc_ids),
419 etype, evalue, (etb, chained_exc_ids),
420 chained_exceptions_tb_offset, context)
420 chained_exceptions_tb_offset, context)
421 + chained_exception_message
421 + chained_exception_message
422 + out_list)
422 + out_list)
423
423
424 return out_list
424 return out_list
425
425
426 def _format_list(self, extracted_list):
426 def _format_list(self, extracted_list):
427 """Format a list of traceback entry tuples for printing.
427 """Format a list of traceback entry tuples for printing.
428
428
429 Given a list of tuples as returned by extract_tb() or
429 Given a list of tuples as returned by extract_tb() or
430 extract_stack(), return a list of strings ready for printing.
430 extract_stack(), return a list of strings ready for printing.
431 Each string in the resulting list corresponds to the item with the
431 Each string in the resulting list corresponds to the item with the
432 same index in the argument list. Each string ends in a newline;
432 same index in the argument list. Each string ends in a newline;
433 the strings may contain internal newlines as well, for those items
433 the strings may contain internal newlines as well, for those items
434 whose source text line is not None.
434 whose source text line is not None.
435
435
436 Lifted almost verbatim from traceback.py
436 Lifted almost verbatim from traceback.py
437 """
437 """
438
438
439 Colors = self.Colors
439 Colors = self.Colors
440 list = []
440 list = []
441 for filename, lineno, name, line in extracted_list[:-1]:
441 for filename, lineno, name, line in extracted_list[:-1]:
442 item = " %s, line %s%d%s, in %s%s%s\n" % (
442 item = " %s, line %s%d%s, in %s%s%s\n" % (
443 _format_filename(filename, Colors.filename, Colors.Normal),
443 _format_filename(filename, Colors.filename, Colors.Normal),
444 Colors.lineno,
444 Colors.lineno,
445 lineno,
445 lineno,
446 Colors.Normal,
446 Colors.Normal,
447 Colors.name,
447 Colors.name,
448 name,
448 name,
449 Colors.Normal,
449 Colors.Normal,
450 )
450 )
451 if line:
451 if line:
452 item += ' %s\n' % line.strip()
452 item += ' %s\n' % line.strip()
453 list.append(item)
453 list.append(item)
454 # Emphasize the last entry
454 # Emphasize the last entry
455 filename, lineno, name, line = extracted_list[-1]
455 filename, lineno, name, line = extracted_list[-1]
456 item = "%s %s, line %s%d%s, in %s%s%s%s\n" % (
456 item = "%s %s, line %s%d%s, in %s%s%s%s\n" % (
457 Colors.normalEm,
457 Colors.normalEm,
458 _format_filename(filename, Colors.filenameEm, Colors.normalEm),
458 _format_filename(filename, Colors.filenameEm, Colors.normalEm),
459 Colors.linenoEm,
459 Colors.linenoEm,
460 lineno,
460 lineno,
461 Colors.normalEm,
461 Colors.normalEm,
462 Colors.nameEm,
462 Colors.nameEm,
463 name,
463 name,
464 Colors.normalEm,
464 Colors.normalEm,
465 Colors.Normal,
465 Colors.Normal,
466 )
466 )
467 if line:
467 if line:
468 item += '%s %s%s\n' % (Colors.line, line.strip(),
468 item += '%s %s%s\n' % (Colors.line, line.strip(),
469 Colors.Normal)
469 Colors.Normal)
470 list.append(item)
470 list.append(item)
471 return list
471 return list
472
472
473 def _format_exception_only(self, etype, value):
473 def _format_exception_only(self, etype, value):
474 """Format the exception part of a traceback.
474 """Format the exception part of a traceback.
475
475
476 The arguments are the exception type and value such as given by
476 The arguments are the exception type and value such as given by
477 sys.exc_info()[:2]. The return value is a list of strings, each ending
477 sys.exc_info()[:2]. The return value is a list of strings, each ending
478 in a newline. Normally, the list contains a single string; however,
478 in a newline. Normally, the list contains a single string; however,
479 for SyntaxError exceptions, it contains several lines that (when
479 for SyntaxError exceptions, it contains several lines that (when
480 printed) display detailed information about where the syntax error
480 printed) display detailed information about where the syntax error
481 occurred. The message indicating which exception occurred is the
481 occurred. The message indicating which exception occurred is the
482 always last string in the list.
482 always last string in the list.
483
483
484 Also lifted nearly verbatim from traceback.py
484 Also lifted nearly verbatim from traceback.py
485 """
485 """
486 have_filedata = False
486 have_filedata = False
487 Colors = self.Colors
487 Colors = self.Colors
488 list = []
488 list = []
489 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
489 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
490 if value is None:
490 if value is None:
491 # Not sure if this can still happen in Python 2.6 and above
491 # Not sure if this can still happen in Python 2.6 and above
492 list.append(stype + '\n')
492 list.append(stype + '\n')
493 else:
493 else:
494 if issubclass(etype, SyntaxError):
494 if issubclass(etype, SyntaxError):
495 have_filedata = True
495 have_filedata = True
496 if not value.filename: value.filename = "<string>"
496 if not value.filename: value.filename = "<string>"
497 if value.lineno:
497 if value.lineno:
498 lineno = value.lineno
498 lineno = value.lineno
499 textline = linecache.getline(value.filename, value.lineno)
499 textline = linecache.getline(value.filename, value.lineno)
500 else:
500 else:
501 lineno = "unknown"
501 lineno = "unknown"
502 textline = ""
502 textline = ""
503 list.append(
503 list.append(
504 "%s %s, line %s%s%s\n"
504 "%s %s, line %s%s%s\n"
505 % (
505 % (
506 Colors.normalEm,
506 Colors.normalEm,
507 _format_filename(
507 _format_filename(
508 value.filename, Colors.filenameEm, Colors.normalEm
508 value.filename, Colors.filenameEm, Colors.normalEm
509 ),
509 ),
510 Colors.linenoEm,
510 Colors.linenoEm,
511 lineno,
511 lineno,
512 Colors.Normal,
512 Colors.Normal,
513 )
513 )
514 )
514 )
515 if textline == "":
515 if textline == "":
516 textline = py3compat.cast_unicode(value.text, "utf-8")
516 textline = py3compat.cast_unicode(value.text, "utf-8")
517
517
518 if textline is not None:
518 if textline is not None:
519 i = 0
519 i = 0
520 while i < len(textline) and textline[i].isspace():
520 while i < len(textline) and textline[i].isspace():
521 i += 1
521 i += 1
522 list.append('%s %s%s\n' % (Colors.line,
522 list.append('%s %s%s\n' % (Colors.line,
523 textline.strip(),
523 textline.strip(),
524 Colors.Normal))
524 Colors.Normal))
525 if value.offset is not None:
525 if value.offset is not None:
526 s = ' '
526 s = ' '
527 for c in textline[i:value.offset - 1]:
527 for c in textline[i:value.offset - 1]:
528 if c.isspace():
528 if c.isspace():
529 s += c
529 s += c
530 else:
530 else:
531 s += ' '
531 s += ' '
532 list.append('%s%s^%s\n' % (Colors.caret, s,
532 list.append('%s%s^%s\n' % (Colors.caret, s,
533 Colors.Normal))
533 Colors.Normal))
534
534
535 try:
535 try:
536 s = value.msg
536 s = value.msg
537 except Exception:
537 except Exception:
538 s = self._some_str(value)
538 s = self._some_str(value)
539 if s:
539 if s:
540 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
540 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
541 Colors.Normal, s))
541 Colors.Normal, s))
542 else:
542 else:
543 list.append('%s\n' % stype)
543 list.append('%s\n' % stype)
544
544
545 # sync with user hooks
545 # sync with user hooks
546 if have_filedata:
546 if have_filedata:
547 ipinst = get_ipython()
547 ipinst = get_ipython()
548 if ipinst is not None:
548 if ipinst is not None:
549 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
549 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
550
550
551 return list
551 return list
552
552
553 def get_exception_only(self, etype, value):
553 def get_exception_only(self, etype, value):
554 """Only print the exception type and message, without a traceback.
554 """Only print the exception type and message, without a traceback.
555
555
556 Parameters
556 Parameters
557 ----------
557 ----------
558 etype : exception type
558 etype : exception type
559 value : exception value
559 value : exception value
560 """
560 """
561 return ListTB.structured_traceback(self, etype, value)
561 return ListTB.structured_traceback(self, etype, value)
562
562
563 def show_exception_only(self, etype, evalue):
563 def show_exception_only(self, etype, evalue):
564 """Only print the exception type and message, without a traceback.
564 """Only print the exception type and message, without a traceback.
565
565
566 Parameters
566 Parameters
567 ----------
567 ----------
568 etype : exception type
568 etype : exception type
569 evalue : exception value
569 evalue : exception value
570 """
570 """
571 # This method needs to use __call__ from *this* class, not the one from
571 # This method needs to use __call__ from *this* class, not the one from
572 # a subclass whose signature or behavior may be different
572 # a subclass whose signature or behavior may be different
573 ostream = self.ostream
573 ostream = self.ostream
574 ostream.flush()
574 ostream.flush()
575 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
575 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
576 ostream.flush()
576 ostream.flush()
577
577
578 def _some_str(self, value):
578 def _some_str(self, value):
579 # Lifted from traceback.py
579 # Lifted from traceback.py
580 try:
580 try:
581 return py3compat.cast_unicode(str(value))
581 return py3compat.cast_unicode(str(value))
582 except:
582 except:
583 return u'<unprintable %s object>' % type(value).__name__
583 return u'<unprintable %s object>' % type(value).__name__
584
584
585
585
586 #----------------------------------------------------------------------------
586 #----------------------------------------------------------------------------
587 class VerboseTB(TBTools):
587 class VerboseTB(TBTools):
588 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
588 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
589 of HTML. Requires inspect and pydoc. Crazy, man.
589 of HTML. Requires inspect and pydoc. Crazy, man.
590
590
591 Modified version which optionally strips the topmost entries from the
591 Modified version which optionally strips the topmost entries from the
592 traceback, to be used with alternate interpreters (because their own code
592 traceback, to be used with alternate interpreters (because their own code
593 would appear in the traceback)."""
593 would appear in the traceback)."""
594
594
595 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
595 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
596 tb_offset=0, long_header=False, include_vars=True,
596 tb_offset=0, long_header=False, include_vars=True,
597 check_cache=None, debugger_cls = None,
597 check_cache=None, debugger_cls = None,
598 parent=None, config=None):
598 parent=None, config=None):
599 """Specify traceback offset, headers and color scheme.
599 """Specify traceback offset, headers and color scheme.
600
600
601 Define how many frames to drop from the tracebacks. Calling it with
601 Define how many frames to drop from the tracebacks. Calling it with
602 tb_offset=1 allows use of this handler in interpreters which will have
602 tb_offset=1 allows use of this handler in interpreters which will have
603 their own code at the top of the traceback (VerboseTB will first
603 their own code at the top of the traceback (VerboseTB will first
604 remove that frame before printing the traceback info)."""
604 remove that frame before printing the traceback info)."""
605 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
605 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
606 ostream=ostream, parent=parent, config=config)
606 ostream=ostream, parent=parent, config=config)
607 self.tb_offset = tb_offset
607 self.tb_offset = tb_offset
608 self.long_header = long_header
608 self.long_header = long_header
609 self.include_vars = include_vars
609 self.include_vars = include_vars
610 # By default we use linecache.checkcache, but the user can provide a
610 # By default we use linecache.checkcache, but the user can provide a
611 # different check_cache implementation. This is used by the IPython
611 # different check_cache implementation. This is used by the IPython
612 # kernel to provide tracebacks for interactive code that is cached,
612 # kernel to provide tracebacks for interactive code that is cached,
613 # by a compiler instance that flushes the linecache but preserves its
613 # by a compiler instance that flushes the linecache but preserves its
614 # own code cache.
614 # own code cache.
615 if check_cache is None:
615 if check_cache is None:
616 check_cache = linecache.checkcache
616 check_cache = linecache.checkcache
617 self.check_cache = check_cache
617 self.check_cache = check_cache
618
618
619 self.debugger_cls = debugger_cls or debugger.Pdb
619 self.debugger_cls = debugger_cls or debugger.Pdb
620 self.skip_hidden = True
620 self.skip_hidden = True
621
621
622 def format_record(self, frame_info):
622 def format_record(self, frame_info):
623 """Format a single stack frame"""
623 """Format a single stack frame"""
624 Colors = self.Colors # just a shorthand + quicker name lookup
624 Colors = self.Colors # just a shorthand + quicker name lookup
625 ColorsNormal = Colors.Normal # used a lot
625 ColorsNormal = Colors.Normal # used a lot
626
626
627 if isinstance(frame_info, stack_data.RepeatedFrames):
627 if isinstance(frame_info, stack_data.RepeatedFrames):
628 return ' %s[... skipping similar frames: %s]%s\n' % (
628 return ' %s[... skipping similar frames: %s]%s\n' % (
629 Colors.excName, frame_info.description, ColorsNormal)
629 Colors.excName, frame_info.description, ColorsNormal)
630
630
631 indent = ' ' * INDENT_SIZE
631 indent = ' ' * INDENT_SIZE
632 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
632 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
633 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
633 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
634 ColorsNormal)
634 ColorsNormal)
635 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
635 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
636 (Colors.vName, Colors.valEm, ColorsNormal)
636 (Colors.vName, Colors.valEm, ColorsNormal)
637 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
637 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
638
638
639 link = _format_filename(frame_info.filename, Colors.filenameEm, ColorsNormal)
639 link = _format_filename(frame_info.filename, Colors.filenameEm, ColorsNormal)
640 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
640 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
641
641
642 func = frame_info.executing.code_qualname()
642 func = frame_info.executing.code_qualname()
643 if func == '<module>':
643 if func == '<module>':
644 call = tpl_call % (func, '')
644 call = tpl_call % (func, '')
645 else:
645 else:
646 # Decide whether to include variable details or not
646 # Decide whether to include variable details or not
647 var_repr = eqrepr if self.include_vars else nullrepr
647 var_repr = eqrepr if self.include_vars else nullrepr
648 try:
648 try:
649 call = tpl_call % (func, inspect.formatargvalues(args,
649 call = tpl_call % (func, inspect.formatargvalues(args,
650 varargs, varkw,
650 varargs, varkw,
651 locals_, formatvalue=var_repr))
651 locals_, formatvalue=var_repr))
652 except KeyError:
652 except KeyError:
653 # This happens in situations like errors inside generator
653 # This happens in situations like errors inside generator
654 # expressions, where local variables are listed in the
654 # expressions, where local variables are listed in the
655 # line, but can't be extracted from the frame. I'm not
655 # line, but can't be extracted from the frame. I'm not
656 # 100% sure this isn't actually a bug in inspect itself,
656 # 100% sure this isn't actually a bug in inspect itself,
657 # but since there's no info for us to compute with, the
657 # but since there's no info for us to compute with, the
658 # best we can do is report the failure and move on. Here
658 # best we can do is report the failure and move on. Here
659 # we must *not* call any traceback construction again,
659 # we must *not* call any traceback construction again,
660 # because that would mess up use of %debug later on. So we
660 # because that would mess up use of %debug later on. So we
661 # simply report the failure and move on. The only
661 # simply report the failure and move on. The only
662 # limitation will be that this frame won't have locals
662 # limitation will be that this frame won't have locals
663 # listed in the call signature. Quite subtle problem...
663 # listed in the call signature. Quite subtle problem...
664 # I can't think of a good way to validate this in a unit
664 # I can't think of a good way to validate this in a unit
665 # test, but running a script consisting of:
665 # test, but running a script consisting of:
666 # dict( (k,v.strip()) for (k,v) in range(10) )
666 # dict( (k,v.strip()) for (k,v) in range(10) )
667 # will illustrate the error, if this exception catch is
667 # will illustrate the error, if this exception catch is
668 # disabled.
668 # disabled.
669 call = tpl_call_fail % func
669 call = tpl_call_fail % func
670
670
671 lvals = ''
671 lvals = ''
672 lvals_list = []
672 lvals_list = []
673 if self.include_vars:
673 if self.include_vars:
674 try:
674 try:
675 # we likely want to fix stackdata at some point, but
675 # we likely want to fix stackdata at some point, but
676 # still need a workaround.
676 # still need a workaround.
677 fibp = frame_info.variables_in_executing_piece
677 fibp = frame_info.variables_in_executing_piece
678 for var in fibp:
678 for var in fibp:
679 lvals_list.append(tpl_name_val % (var.name, repr(var.value)))
679 lvals_list.append(tpl_name_val % (var.name, repr(var.value)))
680 except Exception:
680 except Exception:
681 lvals_list.append(
681 lvals_list.append(
682 "Exception trying to inspect frame. No more locals available."
682 "Exception trying to inspect frame. No more locals available."
683 )
683 )
684 if lvals_list:
684 if lvals_list:
685 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
685 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
686
686
687 result = "%s, %s\n" % (link, call)
687 result = "%s, %s\n" % (link, call)
688
688
689 result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals))
689 result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals))
690 return result
690 return result
691
691
692 def prepare_header(self, etype, long_version=False):
692 def prepare_header(self, etype, long_version=False):
693 colors = self.Colors # just a shorthand + quicker name lookup
693 colors = self.Colors # just a shorthand + quicker name lookup
694 colorsnormal = colors.Normal # used a lot
694 colorsnormal = colors.Normal # used a lot
695 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
695 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
696 width = min(75, get_terminal_size()[0])
696 width = min(75, get_terminal_size()[0])
697 if long_version:
697 if long_version:
698 # Header with the exception type, python version, and date
698 # Header with the exception type, python version, and date
699 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
699 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
700 date = time.ctime(time.time())
700 date = time.ctime(time.time())
701
701
702 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
702 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
703 exc, ' ' * (width - len(str(etype)) - len(pyver)),
703 exc, ' ' * (width - len(str(etype)) - len(pyver)),
704 pyver, date.rjust(width) )
704 pyver, date.rjust(width) )
705 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
705 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
706 "\ncalls leading up to the error, with the most recent (innermost) call last."
706 "\ncalls leading up to the error, with the most recent (innermost) call last."
707 else:
707 else:
708 # Simplified header
708 # Simplified header
709 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
709 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
710 rjust(width - len(str(etype))) )
710 rjust(width - len(str(etype))) )
711
711
712 return head
712 return head
713
713
714 def format_exception(self, etype, evalue):
714 def format_exception(self, etype, evalue):
715 colors = self.Colors # just a shorthand + quicker name lookup
715 colors = self.Colors # just a shorthand + quicker name lookup
716 colorsnormal = colors.Normal # used a lot
716 colorsnormal = colors.Normal # used a lot
717 # Get (safely) a string form of the exception info
717 # Get (safely) a string form of the exception info
718 try:
718 try:
719 etype_str, evalue_str = map(str, (etype, evalue))
719 etype_str, evalue_str = map(str, (etype, evalue))
720 except:
720 except:
721 # User exception is improperly defined.
721 # User exception is improperly defined.
722 etype, evalue = str, sys.exc_info()[:2]
722 etype, evalue = str, sys.exc_info()[:2]
723 etype_str, evalue_str = map(str, (etype, evalue))
723 etype_str, evalue_str = map(str, (etype, evalue))
724 # ... and format it
724 # ... and format it
725 return ['%s%s%s: %s' % (colors.excName, etype_str,
725 return ['%s%s%s: %s' % (colors.excName, etype_str,
726 colorsnormal, py3compat.cast_unicode(evalue_str))]
726 colorsnormal, py3compat.cast_unicode(evalue_str))]
727
727
728 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
728 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
729 """Formats the header, traceback and exception message for a single exception.
729 """Formats the header, traceback and exception message for a single exception.
730
730
731 This may be called multiple times by Python 3 exception chaining
731 This may be called multiple times by Python 3 exception chaining
732 (PEP 3134).
732 (PEP 3134).
733 """
733 """
734 # some locals
734 # some locals
735 orig_etype = etype
735 orig_etype = etype
736 try:
736 try:
737 etype = etype.__name__
737 etype = etype.__name__
738 except AttributeError:
738 except AttributeError:
739 pass
739 pass
740
740
741 tb_offset = self.tb_offset if tb_offset is None else tb_offset
741 tb_offset = self.tb_offset if tb_offset is None else tb_offset
742 head = self.prepare_header(etype, self.long_header)
742 head = self.prepare_header(etype, self.long_header)
743 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
743 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
744
744
745 frames = []
745 frames = []
746 skipped = 0
746 skipped = 0
747 lastrecord = len(records) - 1
747 lastrecord = len(records) - 1
748 for i, r in enumerate(records):
748 for i, r in enumerate(records):
749 if not isinstance(r, stack_data.RepeatedFrames) and self.skip_hidden:
749 if not isinstance(r, stack_data.RepeatedFrames) and self.skip_hidden:
750 if r.frame.f_locals.get("__tracebackhide__", 0) and i != lastrecord:
750 if r.frame.f_locals.get("__tracebackhide__", 0) and i != lastrecord:
751 skipped += 1
751 skipped += 1
752 continue
752 continue
753 if skipped:
753 if skipped:
754 Colors = self.Colors # just a shorthand + quicker name lookup
754 Colors = self.Colors # just a shorthand + quicker name lookup
755 ColorsNormal = Colors.Normal # used a lot
755 ColorsNormal = Colors.Normal # used a lot
756 frames.append(
756 frames.append(
757 " %s[... skipping hidden %s frame]%s\n"
757 " %s[... skipping hidden %s frame]%s\n"
758 % (Colors.excName, skipped, ColorsNormal)
758 % (Colors.excName, skipped, ColorsNormal)
759 )
759 )
760 skipped = 0
760 skipped = 0
761 frames.append(self.format_record(r))
761 frames.append(self.format_record(r))
762 if skipped:
762 if skipped:
763 Colors = self.Colors # just a shorthand + quicker name lookup
763 Colors = self.Colors # just a shorthand + quicker name lookup
764 ColorsNormal = Colors.Normal # used a lot
764 ColorsNormal = Colors.Normal # used a lot
765 frames.append(
765 frames.append(
766 " %s[... skipping hidden %s frame]%s\n"
766 " %s[... skipping hidden %s frame]%s\n"
767 % (Colors.excName, skipped, ColorsNormal)
767 % (Colors.excName, skipped, ColorsNormal)
768 )
768 )
769
769
770 formatted_exception = self.format_exception(etype, evalue)
770 formatted_exception = self.format_exception(etype, evalue)
771 if records:
771 if records:
772 frame_info = records[-1]
772 frame_info = records[-1]
773 ipinst = get_ipython()
773 ipinst = get_ipython()
774 if ipinst is not None:
774 if ipinst is not None:
775 ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0)
775 ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0)
776
776
777 return [[head] + frames + [''.join(formatted_exception[0])]]
777 return [[head] + frames + [''.join(formatted_exception[0])]]
778
778
779 def get_records(self, etb, number_of_lines_of_context, tb_offset):
779 def get_records(self, etb, number_of_lines_of_context, tb_offset):
780 context = number_of_lines_of_context - 1
780 context = number_of_lines_of_context - 1
781 after = context // 2
781 after = context // 2
782 before = context - after
782 before = context - after
783 if self.has_colors:
783 if self.has_colors:
784 style = get_style_by_name('default')
784 style = get_style_by_name('default')
785 style = stack_data.style_with_executing_node(style, 'bg:#00005f')
785 style = stack_data.style_with_executing_node(style, 'bg:#00005f')
786 formatter = Terminal256Formatter(style=style)
786 formatter = Terminal256Formatter(style=style)
787 else:
787 else:
788 formatter = None
788 formatter = None
789 options = stack_data.Options(
789 options = stack_data.Options(
790 before=before,
790 before=before,
791 after=after,
791 after=after,
792 pygments_formatter=formatter,
792 pygments_formatter=formatter,
793 )
793 )
794 return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
794 return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
795
795
796 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
796 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
797 number_of_lines_of_context=5):
797 number_of_lines_of_context=5):
798 """Return a nice text document describing the traceback."""
798 """Return a nice text document describing the traceback."""
799
799
800 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
800 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
801 tb_offset)
801 tb_offset)
802
802
803 colors = self.Colors # just a shorthand + quicker name lookup
803 colors = self.Colors # just a shorthand + quicker name lookup
804 colorsnormal = colors.Normal # used a lot
804 colorsnormal = colors.Normal # used a lot
805 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
805 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
806 structured_traceback_parts = [head]
806 structured_traceback_parts = [head]
807 chained_exceptions_tb_offset = 0
807 chained_exceptions_tb_offset = 0
808 lines_of_context = 3
808 lines_of_context = 3
809 formatted_exceptions = formatted_exception
809 formatted_exceptions = formatted_exception
810 exception = self.get_parts_of_chained_exception(evalue)
810 exception = self.get_parts_of_chained_exception(evalue)
811 if exception:
811 if exception:
812 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
812 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
813 etype, evalue, etb = exception
813 etype, evalue, etb = exception
814 else:
814 else:
815 evalue = None
815 evalue = None
816 chained_exc_ids = set()
816 chained_exc_ids = set()
817 while evalue:
817 while evalue:
818 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
818 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
819 chained_exceptions_tb_offset)
819 chained_exceptions_tb_offset)
820 exception = self.get_parts_of_chained_exception(evalue)
820 exception = self.get_parts_of_chained_exception(evalue)
821
821
822 if exception and not id(exception[1]) in chained_exc_ids:
822 if exception and not id(exception[1]) in chained_exc_ids:
823 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
823 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
824 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
824 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
825 etype, evalue, etb = exception
825 etype, evalue, etb = exception
826 else:
826 else:
827 evalue = None
827 evalue = None
828
828
829 # we want to see exceptions in a reversed order:
829 # we want to see exceptions in a reversed order:
830 # the first exception should be on top
830 # the first exception should be on top
831 for formatted_exception in reversed(formatted_exceptions):
831 for formatted_exception in reversed(formatted_exceptions):
832 structured_traceback_parts += formatted_exception
832 structured_traceback_parts += formatted_exception
833
833
834 return structured_traceback_parts
834 return structured_traceback_parts
835
835
836 def debugger(self, force=False):
836 def debugger(self, force=False):
837 """Call up the pdb debugger if desired, always clean up the tb
837 """Call up the pdb debugger if desired, always clean up the tb
838 reference.
838 reference.
839
839
840 Keywords:
840 Keywords:
841
841
842 - force(False): by default, this routine checks the instance call_pdb
842 - force(False): by default, this routine checks the instance call_pdb
843 flag and does not actually invoke the debugger if the flag is false.
843 flag and does not actually invoke the debugger if the flag is false.
844 The 'force' option forces the debugger to activate even if the flag
844 The 'force' option forces the debugger to activate even if the flag
845 is false.
845 is false.
846
846
847 If the call_pdb flag is set, the pdb interactive debugger is
847 If the call_pdb flag is set, the pdb interactive debugger is
848 invoked. In all cases, the self.tb reference to the current traceback
848 invoked. In all cases, the self.tb reference to the current traceback
849 is deleted to prevent lingering references which hamper memory
849 is deleted to prevent lingering references which hamper memory
850 management.
850 management.
851
851
852 Note that each call to pdb() does an 'import readline', so if your app
852 Note that each call to pdb() does an 'import readline', so if your app
853 requires a special setup for the readline completers, you'll have to
853 requires a special setup for the readline completers, you'll have to
854 fix that by hand after invoking the exception handler."""
854 fix that by hand after invoking the exception handler."""
855
855
856 if force or self.call_pdb:
856 if force or self.call_pdb:
857 if self.pdb is None:
857 if self.pdb is None:
858 self.pdb = self.debugger_cls()
858 self.pdb = self.debugger_cls()
859 # the system displayhook may have changed, restore the original
859 # the system displayhook may have changed, restore the original
860 # for pdb
860 # for pdb
861 display_trap = DisplayTrap(hook=sys.__displayhook__)
861 display_trap = DisplayTrap(hook=sys.__displayhook__)
862 with display_trap:
862 with display_trap:
863 self.pdb.reset()
863 self.pdb.reset()
864 # Find the right frame so we don't pop up inside ipython itself
864 # Find the right frame so we don't pop up inside ipython itself
865 if hasattr(self, 'tb') and self.tb is not None:
865 if hasattr(self, 'tb') and self.tb is not None:
866 etb = self.tb
866 etb = self.tb
867 else:
867 else:
868 etb = self.tb = sys.last_traceback
868 etb = self.tb = sys.last_traceback
869 while self.tb is not None and self.tb.tb_next is not None:
869 while self.tb is not None and self.tb.tb_next is not None:
870 self.tb = self.tb.tb_next
870 self.tb = self.tb.tb_next
871 if etb and etb.tb_next:
871 if etb and etb.tb_next:
872 etb = etb.tb_next
872 etb = etb.tb_next
873 self.pdb.botframe = etb.tb_frame
873 self.pdb.botframe = etb.tb_frame
874 self.pdb.interaction(None, etb)
874 self.pdb.interaction(None, etb)
875
875
876 if hasattr(self, 'tb'):
876 if hasattr(self, 'tb'):
877 del self.tb
877 del self.tb
878
878
879 def handler(self, info=None):
879 def handler(self, info=None):
880 (etype, evalue, etb) = info or sys.exc_info()
880 (etype, evalue, etb) = info or sys.exc_info()
881 self.tb = etb
881 self.tb = etb
882 ostream = self.ostream
882 ostream = self.ostream
883 ostream.flush()
883 ostream.flush()
884 ostream.write(self.text(etype, evalue, etb))
884 ostream.write(self.text(etype, evalue, etb))
885 ostream.write('\n')
885 ostream.write('\n')
886 ostream.flush()
886 ostream.flush()
887
887
888 # Changed so an instance can just be called as VerboseTB_inst() and print
888 # Changed so an instance can just be called as VerboseTB_inst() and print
889 # out the right info on its own.
889 # out the right info on its own.
890 def __call__(self, etype=None, evalue=None, etb=None):
890 def __call__(self, etype=None, evalue=None, etb=None):
891 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
891 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
892 if etb is None:
892 if etb is None:
893 self.handler()
893 self.handler()
894 else:
894 else:
895 self.handler((etype, evalue, etb))
895 self.handler((etype, evalue, etb))
896 try:
896 try:
897 self.debugger()
897 self.debugger()
898 except KeyboardInterrupt:
898 except KeyboardInterrupt:
899 print("\nKeyboardInterrupt")
899 print("\nKeyboardInterrupt")
900
900
901
901
902 #----------------------------------------------------------------------------
902 #----------------------------------------------------------------------------
903 class FormattedTB(VerboseTB, ListTB):
903 class FormattedTB(VerboseTB, ListTB):
904 """Subclass ListTB but allow calling with a traceback.
904 """Subclass ListTB but allow calling with a traceback.
905
905
906 It can thus be used as a sys.excepthook for Python > 2.1.
906 It can thus be used as a sys.excepthook for Python > 2.1.
907
907
908 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
908 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
909
909
910 Allows a tb_offset to be specified. This is useful for situations where
910 Allows a tb_offset to be specified. This is useful for situations where
911 one needs to remove a number of topmost frames from the traceback (such as
911 one needs to remove a number of topmost frames from the traceback (such as
912 occurs with python programs that themselves execute other python code,
912 occurs with python programs that themselves execute other python code,
913 like Python shells). """
913 like Python shells). """
914
914
915 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
915 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
916 ostream=None,
916 ostream=None,
917 tb_offset=0, long_header=False, include_vars=False,
917 tb_offset=0, long_header=False, include_vars=False,
918 check_cache=None, debugger_cls=None,
918 check_cache=None, debugger_cls=None,
919 parent=None, config=None):
919 parent=None, config=None):
920
920
921 # NEVER change the order of this list. Put new modes at the end:
921 # NEVER change the order of this list. Put new modes at the end:
922 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
922 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
923 self.verbose_modes = self.valid_modes[1:3]
923 self.verbose_modes = self.valid_modes[1:3]
924
924
925 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
925 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
926 ostream=ostream, tb_offset=tb_offset,
926 ostream=ostream, tb_offset=tb_offset,
927 long_header=long_header, include_vars=include_vars,
927 long_header=long_header, include_vars=include_vars,
928 check_cache=check_cache, debugger_cls=debugger_cls,
928 check_cache=check_cache, debugger_cls=debugger_cls,
929 parent=parent, config=config)
929 parent=parent, config=config)
930
930
931 # Different types of tracebacks are joined with different separators to
931 # Different types of tracebacks are joined with different separators to
932 # form a single string. They are taken from this dict
932 # form a single string. They are taken from this dict
933 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
933 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
934 Minimal='')
934 Minimal='')
935 # set_mode also sets the tb_join_char attribute
935 # set_mode also sets the tb_join_char attribute
936 self.set_mode(mode)
936 self.set_mode(mode)
937
937
938 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
938 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
939 tb_offset = self.tb_offset if tb_offset is None else tb_offset
939 tb_offset = self.tb_offset if tb_offset is None else tb_offset
940 mode = self.mode
940 mode = self.mode
941 if mode in self.verbose_modes:
941 if mode in self.verbose_modes:
942 # Verbose modes need a full traceback
942 # Verbose modes need a full traceback
943 return VerboseTB.structured_traceback(
943 return VerboseTB.structured_traceback(
944 self, etype, value, tb, tb_offset, number_of_lines_of_context
944 self, etype, value, tb, tb_offset, number_of_lines_of_context
945 )
945 )
946 elif mode == 'Minimal':
946 elif mode == 'Minimal':
947 return ListTB.get_exception_only(self, etype, value)
947 return ListTB.get_exception_only(self, etype, value)
948 else:
948 else:
949 # We must check the source cache because otherwise we can print
949 # We must check the source cache because otherwise we can print
950 # out-of-date source code.
950 # out-of-date source code.
951 self.check_cache()
951 self.check_cache()
952 # Now we can extract and format the exception
952 # Now we can extract and format the exception
953 return ListTB.structured_traceback(
953 return ListTB.structured_traceback(
954 self, etype, value, tb, tb_offset, number_of_lines_of_context
954 self, etype, value, tb, tb_offset, number_of_lines_of_context
955 )
955 )
956
956
957 def stb2text(self, stb):
957 def stb2text(self, stb):
958 """Convert a structured traceback (a list) to a string."""
958 """Convert a structured traceback (a list) to a string."""
959 return self.tb_join_char.join(stb)
959 return self.tb_join_char.join(stb)
960
960
961
961
962 def set_mode(self, mode=None):
962 def set_mode(self, mode=None):
963 """Switch to the desired mode.
963 """Switch to the desired mode.
964
964
965 If mode is not specified, cycles through the available modes."""
965 If mode is not specified, cycles through the available modes."""
966
966
967 if not mode:
967 if not mode:
968 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
968 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
969 len(self.valid_modes)
969 len(self.valid_modes)
970 self.mode = self.valid_modes[new_idx]
970 self.mode = self.valid_modes[new_idx]
971 elif mode not in self.valid_modes:
971 elif mode not in self.valid_modes:
972 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
972 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
973 'Valid modes: ' + str(self.valid_modes))
973 'Valid modes: ' + str(self.valid_modes))
974 else:
974 else:
975 self.mode = mode
975 self.mode = mode
976 # include variable details only in 'Verbose' mode
976 # include variable details only in 'Verbose' mode
977 self.include_vars = (self.mode == self.valid_modes[2])
977 self.include_vars = (self.mode == self.valid_modes[2])
978 # Set the join character for generating text tracebacks
978 # Set the join character for generating text tracebacks
979 self.tb_join_char = self._join_chars[self.mode]
979 self.tb_join_char = self._join_chars[self.mode]
980
980
981 # some convenient shortcuts
981 # some convenient shortcuts
982 def plain(self):
982 def plain(self):
983 self.set_mode(self.valid_modes[0])
983 self.set_mode(self.valid_modes[0])
984
984
985 def context(self):
985 def context(self):
986 self.set_mode(self.valid_modes[1])
986 self.set_mode(self.valid_modes[1])
987
987
988 def verbose(self):
988 def verbose(self):
989 self.set_mode(self.valid_modes[2])
989 self.set_mode(self.valid_modes[2])
990
990
991 def minimal(self):
991 def minimal(self):
992 self.set_mode(self.valid_modes[3])
992 self.set_mode(self.valid_modes[3])
993
993
994
994
995 #----------------------------------------------------------------------------
995 #----------------------------------------------------------------------------
996 class AutoFormattedTB(FormattedTB):
996 class AutoFormattedTB(FormattedTB):
997 """A traceback printer which can be called on the fly.
997 """A traceback printer which can be called on the fly.
998
998
999 It will find out about exceptions by itself.
999 It will find out about exceptions by itself.
1000
1000
1001 A brief example::
1001 A brief example::
1002
1002
1003 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1003 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1004 try:
1004 try:
1005 ...
1005 ...
1006 except:
1006 except:
1007 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1007 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1008 """
1008 """
1009
1009
1010 def __call__(self, etype=None, evalue=None, etb=None,
1010 def __call__(self, etype=None, evalue=None, etb=None,
1011 out=None, tb_offset=None):
1011 out=None, tb_offset=None):
1012 """Print out a formatted exception traceback.
1012 """Print out a formatted exception traceback.
1013
1013
1014 Optional arguments:
1014 Optional arguments:
1015 - out: an open file-like object to direct output to.
1015 - out: an open file-like object to direct output to.
1016
1016
1017 - tb_offset: the number of frames to skip over in the stack, on a
1017 - tb_offset: the number of frames to skip over in the stack, on a
1018 per-call basis (this overrides temporarily the instance's tb_offset
1018 per-call basis (this overrides temporarily the instance's tb_offset
1019 given at initialization time."""
1019 given at initialization time."""
1020
1020
1021 if out is None:
1021 if out is None:
1022 out = self.ostream
1022 out = self.ostream
1023 out.flush()
1023 out.flush()
1024 out.write(self.text(etype, evalue, etb, tb_offset))
1024 out.write(self.text(etype, evalue, etb, tb_offset))
1025 out.write('\n')
1025 out.write('\n')
1026 out.flush()
1026 out.flush()
1027 # FIXME: we should remove the auto pdb behavior from here and leave
1027 # FIXME: we should remove the auto pdb behavior from here and leave
1028 # that to the clients.
1028 # that to the clients.
1029 try:
1029 try:
1030 self.debugger()
1030 self.debugger()
1031 except KeyboardInterrupt:
1031 except KeyboardInterrupt:
1032 print("\nKeyboardInterrupt")
1032 print("\nKeyboardInterrupt")
1033
1033
1034 def structured_traceback(self, etype=None, value=None, tb=None,
1034 def structured_traceback(self, etype=None, value=None, tb=None,
1035 tb_offset=None, number_of_lines_of_context=5):
1035 tb_offset=None, number_of_lines_of_context=5):
1036 if etype is None:
1036 if etype is None:
1037 etype, value, tb = sys.exc_info()
1037 etype, value, tb = sys.exc_info()
1038 if isinstance(tb, tuple):
1038 if isinstance(tb, tuple):
1039 # tb is a tuple if this is a chained exception.
1039 # tb is a tuple if this is a chained exception.
1040 self.tb = tb[0]
1040 self.tb = tb[0]
1041 else:
1041 else:
1042 self.tb = tb
1042 self.tb = tb
1043 return FormattedTB.structured_traceback(
1043 return FormattedTB.structured_traceback(
1044 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1044 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1045
1045
1046
1046
1047 #---------------------------------------------------------------------------
1047 #---------------------------------------------------------------------------
1048
1048
1049 # A simple class to preserve Nathan's original functionality.
1049 # A simple class to preserve Nathan's original functionality.
1050 class ColorTB(FormattedTB):
1050 class ColorTB(FormattedTB):
1051 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1051 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1052
1052
1053 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1053 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1054 FormattedTB.__init__(self, color_scheme=color_scheme,
1054 FormattedTB.__init__(self, color_scheme=color_scheme,
1055 call_pdb=call_pdb, **kwargs)
1055 call_pdb=call_pdb, **kwargs)
1056
1056
1057
1057
1058 class SyntaxTB(ListTB):
1058 class SyntaxTB(ListTB):
1059 """Extension which holds some state: the last exception value"""
1059 """Extension which holds some state: the last exception value"""
1060
1060
1061 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1061 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1062 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1062 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1063 self.last_syntax_error = None
1063 self.last_syntax_error = None
1064
1064
1065 def __call__(self, etype, value, elist):
1065 def __call__(self, etype, value, elist):
1066 self.last_syntax_error = value
1066 self.last_syntax_error = value
1067
1067
1068 ListTB.__call__(self, etype, value, elist)
1068 ListTB.__call__(self, etype, value, elist)
1069
1069
1070 def structured_traceback(self, etype, value, elist, tb_offset=None,
1070 def structured_traceback(self, etype, value, elist, tb_offset=None,
1071 context=5):
1071 context=5):
1072 # If the source file has been edited, the line in the syntax error can
1072 # If the source file has been edited, the line in the syntax error can
1073 # be wrong (retrieved from an outdated cache). This replaces it with
1073 # be wrong (retrieved from an outdated cache). This replaces it with
1074 # the current value.
1074 # the current value.
1075 if isinstance(value, SyntaxError) \
1075 if isinstance(value, SyntaxError) \
1076 and isinstance(value.filename, str) \
1076 and isinstance(value.filename, str) \
1077 and isinstance(value.lineno, int):
1077 and isinstance(value.lineno, int):
1078 linecache.checkcache(value.filename)
1078 linecache.checkcache(value.filename)
1079 newtext = linecache.getline(value.filename, value.lineno)
1079 newtext = linecache.getline(value.filename, value.lineno)
1080 if newtext:
1080 if newtext:
1081 value.text = newtext
1081 value.text = newtext
1082 self.last_syntax_error = value
1082 self.last_syntax_error = value
1083 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1083 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1084 tb_offset=tb_offset, context=context)
1084 tb_offset=tb_offset, context=context)
1085
1085
1086 def clear_err_state(self):
1086 def clear_err_state(self):
1087 """Return the current error state and clear it"""
1087 """Return the current error state and clear it"""
1088 e = self.last_syntax_error
1088 e = self.last_syntax_error
1089 self.last_syntax_error = None
1089 self.last_syntax_error = None
1090 return e
1090 return e
1091
1091
1092 def stb2text(self, stb):
1092 def stb2text(self, stb):
1093 """Convert a structured traceback (a list) to a string."""
1093 """Convert a structured traceback (a list) to a string."""
1094 return ''.join(stb)
1094 return ''.join(stb)
1095
1095
1096
1096
1097 # some internal-use functions
1097 # some internal-use functions
1098 def text_repr(value):
1098 def text_repr(value):
1099 """Hopefully pretty robust repr equivalent."""
1099 """Hopefully pretty robust repr equivalent."""
1100 # this is pretty horrible but should always return *something*
1100 # this is pretty horrible but should always return *something*
1101 try:
1101 try:
1102 return pydoc.text.repr(value)
1102 return pydoc.text.repr(value)
1103 except KeyboardInterrupt:
1103 except KeyboardInterrupt:
1104 raise
1104 raise
1105 except:
1105 except:
1106 try:
1106 try:
1107 return repr(value)
1107 return repr(value)
1108 except KeyboardInterrupt:
1108 except KeyboardInterrupt:
1109 raise
1109 raise
1110 except:
1110 except:
1111 try:
1111 try:
1112 # all still in an except block so we catch
1112 # all still in an except block so we catch
1113 # getattr raising
1113 # getattr raising
1114 name = getattr(value, '__name__', None)
1114 name = getattr(value, '__name__', None)
1115 if name:
1115 if name:
1116 # ick, recursion
1116 # ick, recursion
1117 return text_repr(name)
1117 return text_repr(name)
1118 klass = getattr(value, '__class__', None)
1118 klass = getattr(value, '__class__', None)
1119 if klass:
1119 if klass:
1120 return '%s instance' % text_repr(klass)
1120 return '%s instance' % text_repr(klass)
1121 except KeyboardInterrupt:
1121 except KeyboardInterrupt:
1122 raise
1122 raise
1123 except:
1123 except:
1124 return 'UNRECOVERABLE REPR FAILURE'
1124 return 'UNRECOVERABLE REPR FAILURE'
1125
1125
1126
1126
1127 def eqrepr(value, repr=text_repr):
1127 def eqrepr(value, repr=text_repr):
1128 return '=%s' % repr(value)
1128 return '=%s' % repr(value)
1129
1129
1130
1130
1131 def nullrepr(value, repr=text_repr):
1131 def nullrepr(value, repr=text_repr):
1132 return ''
1132 return ''
@@ -1,437 +1,444 b''
1 =====================
1 =====================
2 Development version
2 Development version
3 =====================
3 =====================
4
4
5 This document describes in-flight development work.
5 This document describes in-flight development work.
6
6
7 .. warning::
7 .. warning::
8
8
9 Please do not edit this file by hand (doing so will likely cause merge
9 Please do not edit this file by hand (doing so will likely cause merge
10 conflicts for other Pull Requests). Instead, create a new file in the
10 conflicts for other Pull Requests). Instead, create a new file in the
11 `docs/source/whatsnew/pr` folder
11 `docs/source/whatsnew/pr` folder
12
12
13
13
14 Released .... ...., 2019
14 Released .... ...., 2019
15
15
16
16
17 Need to be updated:
17 Need to be updated:
18
18
19 .. toctree::
19 .. toctree::
20 :maxdepth: 2
20 :maxdepth: 2
21 :glob:
21 :glob:
22
22
23 pr/*
23 pr/*
24
24
25 IPython 8.0 is bringing a large number of new features and improvements to both the
25 IPython 8.0 is bringing a large number of new features and improvements to both the
26 user of the terminal and of the kernel via Jupyter. The removal of compatibility
26 user of the terminal and of the kernel via Jupyter. The removal of compatibility
27 with older version of Python is also the opportunity to do a couple of
27 with older version of Python is also the opportunity to do a couple of
28 performance improvement in particular with respect to startup time.
28 performance improvement in particular with respect to startup time.
29 The 8.x branch started diverging from its predecessor around IPython 7.12
29 The 8.x branch started diverging from its predecessor around IPython 7.12
30 (January 2020).
30 (January 2020).
31
31
32 This release contains 250+ Pull Requests, in addition to many of the features
32 This release contains 250+ Pull Requests, in addition to many of the features
33 and backports that have made it to the 7.x branch. All PRs that went into this
33 and backports that have made it to the 7.x branch. All PRs that went into this
34 released are properly tagged with the 8.0 milestone if you wish to have a more
34 released are properly tagged with the 8.0 milestone if you wish to have a more
35 in depth look at the changes.
35 in depth look at the changes.
36
36
37 Please fell free to send pull-requests to updates those notes after release,
37 Please fell free to send pull-requests to updates those notes after release,
38 I have likely forgotten a few things reviewing 250+ PRs.
38 I have likely forgotten a few things reviewing 250+ PRs.
39
39
40 Dependencies changes/downstream packaging
40 Dependencies changes/downstream packaging
41 -----------------------------------------
41 -----------------------------------------
42
42
43 Note that most of our building step have been changes to be (mostly) declarative
43 Note that most of our building step have been changes to be (mostly) declarative
44 and follow PEP 517, we are trying to completely remove ``setup.py`` (:ghpull:`13238`) and are
44 and follow PEP 517, we are trying to completely remove ``setup.py`` (:ghpull:`13238`) and are
45 looking for help to do so.
45 looking for help to do so.
46
46
47 - Minimum supported ``traitlets`` version if now 5+
47 - Minimum supported ``traitlets`` version if now 5+
48 - we now require ``stack_data``
48 - we now require ``stack_data``
49 - Minimal Python is now 3.8
49 - Minimal Python is now 3.8
50 - ``nose`` is not a testing requirement anymore
50 - ``nose`` is not a testing requirement anymore
51 - ``pytest`` replaces nose.
51 - ``pytest`` replaces nose.
52 - ``iptest``/``iptest3`` cli entrypoints do not exists anymore.
52 - ``iptest``/``iptest3`` cli entrypoints do not exists anymore.
53 - minimum officially support ``numpy`` version has been bumped, but this should
53 - minimum officially support ``numpy`` version has been bumped, but this should
54 not have much effect on packaging.
54 not have much effect on packaging.
55
55
56
56
57 Deprecation and removal
57 Deprecation and removal
58 -----------------------
58 -----------------------
59
59
60 We removed almost all features, arguments, functions, and modules that were
60 We removed almost all features, arguments, functions, and modules that were
61 marked as deprecated between IPython 1.0 and 5.0. As reminder 5.0 was released
61 marked as deprecated between IPython 1.0 and 5.0. As reminder 5.0 was released
62 in 2016, and 1.0 in 2013. Last release of the 5 branch was 5.10.0, in may 2020.
62 in 2016, and 1.0 in 2013. Last release of the 5 branch was 5.10.0, in may 2020.
63 The few remaining deprecated features we left have better deprecation warnings
63 The few remaining deprecated features we left have better deprecation warnings
64 or have been turned into explicit errors for better error messages.
64 or have been turned into explicit errors for better error messages.
65
65
66 I will use this occasion to add the following requests to anyone emitting a
66 I will use this occasion to add the following requests to anyone emitting a
67 deprecation warning:
67 deprecation warning:
68
68
69 - Please at at least ``stacklevel=2`` so that the warning is emitted into the
69 - Please at at least ``stacklevel=2`` so that the warning is emitted into the
70 caller context, and not the callee one.
70 caller context, and not the callee one.
71 - Please add **since which version** something is deprecated.
71 - Please add **since which version** something is deprecated.
72
72
73 As a side note it is much easier to deal with conditional comparing to versions
73 As a side note it is much easier to deal with conditional comparing to versions
74 numbers than ``try/except`` when a functionality change with version.
74 numbers than ``try/except`` when a functionality change with version.
75
75
76 I won't list all the removed features here, but modules like ``IPython.kernel``,
76 I won't list all the removed features here, but modules like ``IPython.kernel``,
77 which was just a shim module around ``ipykernel`` for the past 8 years have been
77 which was just a shim module around ``ipykernel`` for the past 8 years have been
78 remove, and so many other similar things that pre-date the name **Jupyter**
78 remove, and so many other similar things that pre-date the name **Jupyter**
79 itself.
79 itself.
80
80
81 We no longer need to add ``IPyhton.extensions`` to the PYTHONPATH because that is being
81 We no longer need to add ``IPyhton.extensions`` to the PYTHONPATH because that is being
82 handled by ``load_extension``.
82 handled by ``load_extension``.
83
83
84 We are also removing ``Cythonmagic``, ``sympyprinting`` and ``rmagic`` as they are now in
84 We are also removing ``Cythonmagic``, ``sympyprinting`` and ``rmagic`` as they are now in
85 other packages and no longer need to be inside IPython.
85 other packages and no longer need to be inside IPython.
86
86
87
87
88 Documentation
88 Documentation
89 -------------
89 -------------
90
90
91 Majority of our docstrings have now been reformatted and automatically fixed by
91 Majority of our docstrings have now been reformatted and automatically fixed by
92 the experimental `VΓ©lin <https://pypi.org/project/velin/>`_ project, to conform
92 the experimental `VΓ©lin <https://pypi.org/project/velin/>`_ project, to conform
93 to numpydoc.
93 to numpydoc.
94
94
95 Type annotations
96 ----------------
97
98 While IPython itself is highly dynamic and can't be completely typed, many of
99 the function now have type annotation, and part of the codebase and now checked
100 by mypy.
101
95
102
96 Featured changes
103 Featured changes
97 ----------------
104 ----------------
98
105
99 Here is a features list of changes in IPython 8.0. This is of course non-exhaustive.
106 Here is a features list of changes in IPython 8.0. This is of course non-exhaustive.
100 Please note as well that many features have been added in the 7.x branch as well
107 Please note as well that many features have been added in the 7.x branch as well
101 (and hence why you want to read the 7.x what's new notes), in particular
108 (and hence why you want to read the 7.x what's new notes), in particular
102 features contributed by QuantStack (with respect to debugger protocol, and Xeus
109 features contributed by QuantStack (with respect to debugger protocol, and Xeus
103 Python), as well as many debugger features that I was please to implement as
110 Python), as well as many debugger features that I was please to implement as
104 part of my work at QuanSight and Sponsored by DE Shaw.
111 part of my work at QuanSight and Sponsored by DE Shaw.
105
112
106 Better Tracebacks
113 Better Tracebacks
107 ~~~~~~~~~~~~~~~~~
114 ~~~~~~~~~~~~~~~~~
108
115
109 The first on is the integration of the ``stack_data`` package;
116 The first on is the integration of the ``stack_data`` package;
110 which provide smarter informations in traceback; in particular it will highlight
117 which provide smarter informations in traceback; in particular it will highlight
111 the AST node where an error occurs which can help to quickly narrow down errors.
118 the AST node where an error occurs which can help to quickly narrow down errors.
112
119
113 For example in the following snippet::
120 For example in the following snippet::
114
121
115 def foo(i):
122 def foo(i):
116 x = [[[0]]]
123 x = [[[0]]]
117 return x[0][i][0]
124 return x[0][i][0]
118
125
119
126
120 def bar():
127 def bar():
121 return foo(0) + foo(
128 return foo(0) + foo(
122 1
129 1
123 ) + foo(2)
130 ) + foo(2)
124
131
125
132
126 Calling ``bar()`` would raise an ``IndexError`` on the return line of ``foo``,
133 Calling ``bar()`` would raise an ``IndexError`` on the return line of ``foo``,
127 IPython 8.0 is capable of telling you, where the index error occurs::
134 IPython 8.0 is capable of telling you, where the index error occurs::
128
135
129 return x[0][i][0]
136 return x[0][i][0]
130 ^
137 ^
131 Autosuggestons
138 Autosuggestons
132 ~~~~~~~~~~~~~~
139 ~~~~~~~~~~~~~~
133
140
134 Autosuggestion is a very useful feature available in `fish <https://fishshell.com/>`__, `zsh <https://en.wikipedia.org/wiki/Z_shell>`__, and `prompt-toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html#auto-suggestion>`__.
141 Autosuggestion is a very useful feature available in `fish <https://fishshell.com/>`__, `zsh <https://en.wikipedia.org/wiki/Z_shell>`__, and `prompt-toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html#auto-suggestion>`__.
135
142
136 `Ptpython <https://github.com/prompt-toolkit/ptpython#ptpython>`__ allows users to enable this feature in
143 `Ptpython <https://github.com/prompt-toolkit/ptpython#ptpython>`__ allows users to enable this feature in
137 `ptpython/config.py <https://github.com/prompt-toolkit/ptpython/blob/master/examples/ptpython_config/config.py#L90>`__.
144 `ptpython/config.py <https://github.com/prompt-toolkit/ptpython/blob/master/examples/ptpython_config/config.py#L90>`__.
138
145
139 This feature allows users to accept autosuggestions with ctrl e, ctrl f,
146 This feature allows users to accept autosuggestions with ctrl e, ctrl f,
140 or right arrow as described below.
147 or right arrow as described below.
141
148
142 1. Start ipython
149 1. Start ipython
143
150
144 .. image:: ../_images/8.0/auto_suggest_prompt_no_text.png
151 .. image:: ../_images/8.0/auto_suggest_prompt_no_text.png
145
152
146 2. Run ``print("hello")``
153 2. Run ``print("hello")``
147
154
148 .. image:: ../_images/8.0/auto_suggest_print_hello_suggest.png
155 .. image:: ../_images/8.0/auto_suggest_print_hello_suggest.png
149
156
150 3. Press p to see the autosuggestion
157 3. Press p to see the autosuggestion
151
158
152 .. image:: ../_images/8.0/auto_suggest_print_hello_suggest.png
159 .. image:: ../_images/8.0/auto_suggest_print_hello_suggest.png
153
160
154 4. Press ctrl f, or ctrl e, or right arrow to accept the suggestion
161 4. Press ctrl f, or ctrl e, or right arrow to accept the suggestion
155
162
156 .. image:: ../_images/8.0/auto_suggest_print_hello.png
163 .. image:: ../_images/8.0/auto_suggest_print_hello.png
157
164
158 You can also complete word by word:
165 You can also complete word by word:
159
166
160 1. Run ``def say_hello(): print("hello")``
167 1. Run ``def say_hello(): print("hello")``
161
168
162 .. image:: ../_images/8.0/auto_suggest_second_prompt.png
169 .. image:: ../_images/8.0/auto_suggest_second_prompt.png
163
170
164 2. Press d to see the autosuggestion
171 2. Press d to see the autosuggestion
165
172
166 .. image:: ../_images/8.0/auto_suggest_d_phantom.png
173 .. image:: ../_images/8.0/auto_suggest_d_phantom.png
167
174
168 3. Press alt f to accept the first word of the suggestion
175 3. Press alt f to accept the first word of the suggestion
169
176
170 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
177 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
171
178
172 Importantly, this feature does not interfere with tab completion:
179 Importantly, this feature does not interfere with tab completion:
173
180
174 1. After running ``def say_hello(): print("hello")``, press d
181 1. After running ``def say_hello(): print("hello")``, press d
175
182
176 .. image:: ../_images/8.0/audo_suggest_d_phantom.png
183 .. image:: ../_images/8.0/audo_suggest_d_phantom.png
177
184
178 2. Press Tab to start tab completion
185 2. Press Tab to start tab completion
179
186
180 .. image:: ../_images/8.0/auto_suggest_d_completions.png
187 .. image:: ../_images/8.0/auto_suggest_d_completions.png
181
188
182 3A. Press Tab again to select the first option
189 3A. Press Tab again to select the first option
183
190
184 .. image:: ../_images/8.0/auto_suggest_def_completions.png
191 .. image:: ../_images/8.0/auto_suggest_def_completions.png
185
192
186 3B. Press alt f to accept to accept the first word of the suggestion
193 3B. Press alt f to accept to accept the first word of the suggestion
187
194
188 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
195 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
189
196
190 3C. Press ctrl f or ctrl e to accept the entire suggestion
197 3C. Press ctrl f or ctrl e to accept the entire suggestion
191
198
192 .. image:: ../_images/8.0/auto_suggest_match_parens.png
199 .. image:: ../_images/8.0/auto_suggest_match_parens.png
193
200
194 To install a version of ipython with autosuggestions enabled, run:
201 To install a version of ipython with autosuggestions enabled, run:
195
202
196 ``pip install git+https://github.com/mskar/ipython@auto_suggest``
203 ``pip install git+https://github.com/mskar/ipython@auto_suggest``
197
204
198 Currently, autosuggestions are only shown in the emacs or vi insert editing modes:
205 Currently, autosuggestions are only shown in the emacs or vi insert editing modes:
199
206
200 - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode.
207 - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode.
201 - To use these shortcuts in vi insert mode, you will have to create `custom keybindings in your config.py <https://github.com/mskar/setup/commit/2892fcee46f9f80ef7788f0749edc99daccc52f4/>`__.
208 - To use these shortcuts in vi insert mode, you will have to create `custom keybindings in your config.py <https://github.com/mskar/setup/commit/2892fcee46f9f80ef7788f0749edc99daccc52f4/>`__.
202
209
203
210
204 Show pinfo information in ipdb using "?" and "??"
211 Show pinfo information in ipdb using "?" and "??"
205 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
206
213
207 In IPDB, it is now possible to show the information about an object using "?"
214 In IPDB, it is now possible to show the information about an object using "?"
208 and "??", in much the same way it can be done when using the IPython prompt::
215 and "??", in much the same way it can be done when using the IPython prompt::
209
216
210 ipdb> partial?
217 ipdb> partial?
211 Init signature: partial(self, /, *args, **kwargs)
218 Init signature: partial(self, /, *args, **kwargs)
212 Docstring:
219 Docstring:
213 partial(func, *args, **keywords) - new function with partial application
220 partial(func, *args, **keywords) - new function with partial application
214 of the given arguments and keywords.
221 of the given arguments and keywords.
215 File: ~/.pyenv/versions/3.8.6/lib/python3.8/functools.py
222 File: ~/.pyenv/versions/3.8.6/lib/python3.8/functools.py
216 Type: type
223 Type: type
217 Subclasses:
224 Subclasses:
218
225
219 Previously, "pinfo" or "pinfo2" command had to be used for this purpose.
226 Previously, "pinfo" or "pinfo2" command had to be used for this purpose.
220
227
221
228
222 Autoreload 3 feature
229 Autoreload 3 feature
223 ~~~~~~~~~~~~~~~~~~~~
230 ~~~~~~~~~~~~~~~~~~~~
224
231
225 Example: When an IPython session is ran with the 'autoreload' extension loaded,
232 Example: When an IPython session is ran with the 'autoreload' extension loaded,
226 you will now have the option '3' to select which means the following:
233 you will now have the option '3' to select which means the following:
227
234
228 1. replicate all functionality from option 2
235 1. replicate all functionality from option 2
229 2. autoload all new funcs/classes/enums/globals from the module when they're added
236 2. autoload all new funcs/classes/enums/globals from the module when they're added
230 3. autoload all newly imported funcs/classes/enums/globals from external modules
237 3. autoload all newly imported funcs/classes/enums/globals from external modules
231
238
232 Try ``%autoreload 3`` in an IPython session after running ``%load_ext autoreload``
239 Try ``%autoreload 3`` in an IPython session after running ``%load_ext autoreload``
233
240
234 For more information please see unit test -
241 For more information please see unit test -
235 extensions/tests/test_autoreload.py : 'test_autoload_newly_added_objects'
242 extensions/tests/test_autoreload.py : 'test_autoload_newly_added_objects'
236
243
237
244
238
245
239
246
240 History Range Glob feature
247 History Range Glob feature
241 ~~~~~~~~~~~~~~~~~~~~~~~~~~
248 ~~~~~~~~~~~~~~~~~~~~~~~~~~
242
249
243 Previously, when using ``%history``, users could specify either
250 Previously, when using ``%history``, users could specify either
244 a range of sessions and lines, for example:
251 a range of sessions and lines, for example:
245
252
246 .. code-block:: python
253 .. code-block:: python
247
254
248 ~8/1-~6/5 # see history from the first line of 8 sessions ago,
255 ~8/1-~6/5 # see history from the first line of 8 sessions ago,
249 # to the fifth line of 6 sessions ago.``
256 # to the fifth line of 6 sessions ago.``
250
257
251 Or users could specify a glob pattern:
258 Or users could specify a glob pattern:
252
259
253 .. code-block:: python
260 .. code-block:: python
254
261
255 -g <pattern> # glob ALL history for the specified pattern.
262 -g <pattern> # glob ALL history for the specified pattern.
256
263
257 However users could *not* specify both.
264 However users could *not* specify both.
258
265
259 If a user *did* specify both a range and a glob pattern,
266 If a user *did* specify both a range and a glob pattern,
260 then the glob pattern would be used (globbing *all* history) *and the range would be ignored*.
267 then the glob pattern would be used (globbing *all* history) *and the range would be ignored*.
261
268
262 With this enhancement, if a user specifies both a range and a glob pattern, then the glob pattern will be applied to the specified range of history.
269 With this enhancement, if a user specifies both a range and a glob pattern, then the glob pattern will be applied to the specified range of history.
263
270
264 Don't start a multi line cell with sunken parenthesis
271 Don't start a multi line cell with sunken parenthesis
265 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
272 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
266
273
267 From now on IPython will not ask for the next line of input when given a single
274 From now on IPython will not ask for the next line of input when given a single
268 line with more closing than opening brackets. For example, this means that if
275 line with more closing than opening brackets. For example, this means that if
269 you (mis)type ']]' instead of '[]', a ``SyntaxError`` will show up, instead of
276 you (mis)type ']]' instead of '[]', a ``SyntaxError`` will show up, instead of
270 the ``...:`` prompt continuation.
277 the ``...:`` prompt continuation.
271
278
272 IPython shell for ipdb interact
279 IPython shell for ipdb interact
273 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
274
281
275 The ipdb ``interact`` starts an IPython shell instead of Python's built-in ``code.interact()``.
282 The ipdb ``interact`` starts an IPython shell instead of Python's built-in ``code.interact()``.
276
283
277 Automatic Vi prompt stripping
284 Automatic Vi prompt stripping
278 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
279
286
280 When pasting code into IPython, it will strip the leading prompt characters if
287 When pasting code into IPython, it will strip the leading prompt characters if
281 there are any. For example, you can paste the following code into the console -
288 there are any. For example, you can paste the following code into the console -
282 it will still work, even though each line is prefixed with prompts (`In`,
289 it will still work, even though each line is prefixed with prompts (`In`,
283 `Out`)::
290 `Out`)::
284
291
285 In [1]: 2 * 2 == 4
292 In [1]: 2 * 2 == 4
286 Out[1]: True
293 Out[1]: True
287
294
288 In [2]: print("This still works as pasted")
295 In [2]: print("This still works as pasted")
289
296
290
297
291 Previously, this was not the case for the Vi-mode prompts::
298 Previously, this was not the case for the Vi-mode prompts::
292
299
293 In [1]: [ins] In [13]: 2 * 2 == 4
300 In [1]: [ins] In [13]: 2 * 2 == 4
294 ...: Out[13]: True
301 ...: Out[13]: True
295 ...:
302 ...:
296 File "<ipython-input-1-727bb88eaf33>", line 1
303 File "<ipython-input-1-727bb88eaf33>", line 1
297 [ins] In [13]: 2 * 2 == 4
304 [ins] In [13]: 2 * 2 == 4
298 ^
305 ^
299 SyntaxError: invalid syntax
306 SyntaxError: invalid syntax
300
307
301 This is now fixed, and Vi prompt prefixes - ``[ins]`` and ``[nav]`` - are
308 This is now fixed, and Vi prompt prefixes - ``[ins]`` and ``[nav]`` - are
302 skipped just as the normal ``In`` would be.
309 skipped just as the normal ``In`` would be.
303
310
304 IPython shell can be started in the Vi mode using ``ipython
311 IPython shell can be started in the Vi mode using ``ipython
305 --TerminalInteractiveShell.editing_mode=vi``
312 --TerminalInteractiveShell.editing_mode=vi``
306
313
307 Empty History Ranges
314 Empty History Ranges
308 ~~~~~~~~~~~~~~~~~~~~
315 ~~~~~~~~~~~~~~~~~~~~
309
316
310 A number of magics that take history ranges can now be used with an empty
317 A number of magics that take history ranges can now be used with an empty
311 range. These magics are:
318 range. These magics are:
312
319
313 * ``%save``
320 * ``%save``
314 * ``%load``
321 * ``%load``
315 * ``%pastebin``
322 * ``%pastebin``
316 * ``%pycat``
323 * ``%pycat``
317
324
318 Using them this way will make them take the history of the current session up
325 Using them this way will make them take the history of the current session up
319 to the point of the magic call (such that the magic itself will not be
326 to the point of the magic call (such that the magic itself will not be
320 included).
327 included).
321
328
322 Therefore it is now possible to save the whole history to a file using simple
329 Therefore it is now possible to save the whole history to a file using simple
323 ``%save <filename>``, load and edit it using ``%load`` (makes for a nice usage
330 ``%save <filename>``, load and edit it using ``%load`` (makes for a nice usage
324 when followed with :kbd:`F2`), send it to dpaste.org using ``%pastebin``, or
331 when followed with :kbd:`F2`), send it to dpaste.org using ``%pastebin``, or
325 view the whole thing syntax-highlighted with a single ``%pycat``.
332 view the whole thing syntax-highlighted with a single ``%pycat``.
326
333
327 Traceback improvements
334 Traceback improvements
328 ~~~~~~~~~~~~~~~~~~~~~~
335 ~~~~~~~~~~~~~~~~~~~~~~
329
336
330
337
331 UPDATE THIS IN INPUT.
338 UPDATE THIS IN INPUT.
332
339
333 Previously, error tracebacks for errors happening in code cells were showing a hash, the one used for compiling the Python AST::
340 Previously, error tracebacks for errors happening in code cells were showing a hash, the one used for compiling the Python AST::
334
341
335 In [1]: def foo():
342 In [1]: def foo():
336 ...: return 3 / 0
343 ...: return 3 / 0
337 ...:
344 ...:
338
345
339 In [2]: foo()
346 In [2]: foo()
340 ---------------------------------------------------------------------------
347 ---------------------------------------------------------------------------
341 ZeroDivisionError Traceback (most recent call last)
348 ZeroDivisionError Traceback (most recent call last)
342 <ipython-input-2-c19b6d9633cf> in <module>
349 <ipython-input-2-c19b6d9633cf> in <module>
343 ----> 1 foo()
350 ----> 1 foo()
344
351
345 <ipython-input-1-1595a74c32d5> in foo()
352 <ipython-input-1-1595a74c32d5> in foo()
346 1 def foo():
353 1 def foo():
347 ----> 2 return 3 / 0
354 ----> 2 return 3 / 0
348 3
355 3
349
356
350 ZeroDivisionError: division by zero
357 ZeroDivisionError: division by zero
351
358
352 The error traceback is now correctly formatted, showing the cell number in which the error happened::
359 The error traceback is now correctly formatted, showing the cell number in which the error happened::
353
360
354 In [1]: def foo():
361 In [1]: def foo():
355 ...: return 3 / 0
362 ...: return 3 / 0
356 ...:
363 ...:
357
364
358 In [2]: foo()
365 Input In [2]: foo()
359 ---------------------------------------------------------------------------
366 ---------------------------------------------------------------------------
360 ZeroDivisionError Traceback (most recent call last)
367 ZeroDivisionError Traceback (most recent call last)
361 In [2], in <module>
368 input In [2], in <module>
362 ----> 1 foo()
369 ----> 1 foo()
363
370
364 In [1], in foo()
371 Input In [1], in foo()
365 1 def foo():
372 1 def foo():
366 ----> 2 return 3 / 0
373 ----> 2 return 3 / 0
367
374
368 ZeroDivisionError: division by zero
375 ZeroDivisionError: division by zero
369
376
370 Miscellaneous
377 Miscellaneous
371 ~~~~~~~~~~~~~
378 ~~~~~~~~~~~~~
372
379
373 - ``~`` is now expanded when part of a path in most magics :ghpull:`13385`
380 - ``~`` is now expanded when part of a path in most magics :ghpull:`13385`
374 - ``%/%%timeit`` magic now adds comma every thousands to make reading long number easier :ghpull:`13379`
381 - ``%/%%timeit`` magic now adds comma every thousands to make reading long number easier :ghpull:`13379`
375 - ``"info"`` messages can now be customised to hide some fields :ghpull:`13343`
382 - ``"info"`` messages can now be customised to hide some fields :ghpull:`13343`
376 - ``collections.UserList`` now pretty-prints :ghpull:`13320`
383 - ``collections.UserList`` now pretty-prints :ghpull:`13320`
377 - The debugger now have a persistent history, which should make it less
384 - The debugger now have a persistent history, which should make it less
378 annoying to retype commands :ghpull:`13246`
385 annoying to retype commands :ghpull:`13246`
379 - ``!pip`` ``!conda`` ``!cd`` or ``!ls`` are likely doing the wrong thing, we
386 - ``!pip`` ``!conda`` ``!cd`` or ``!ls`` are likely doing the wrong thing, we
380 now warn users if they use it. :ghpull:`12954`
387 now warn users if they use it. :ghpull:`12954`
381 - make ``%precision`` work for ``numpy.float64`` type :ghpull:`12902`
388 - make ``%precision`` work for ``numpy.float64`` type :ghpull:`12902`
382
389
383
390
384
391
385
392
386 Numfocus Small Developer Grant
393 Numfocus Small Developer Grant
387 ------------------------------
394 ------------------------------
388
395
389 To prepare for Python 3.10 we have also started working on removing reliance and
396 To prepare for Python 3.10 we have also started working on removing reliance and
390 any dependency that is not Python 3.10 compatible; that include migrating our
397 any dependency that is not Python 3.10 compatible; that include migrating our
391 test suite to pytest, and starting to remove nose. This also mean that the
398 test suite to pytest, and starting to remove nose. This also mean that the
392 ``iptest`` command is now gone, and all testing is via pytest.
399 ``iptest`` command is now gone, and all testing is via pytest.
393
400
394 This was in bog part thanks the NumFOCUS Small Developer grant, we were able to
401 This was in bog part thanks the NumFOCUS Small Developer grant, we were able to
395 allocate 4000 to hire `Nikita Kniazev @Kojoley <https://github.com/Kojoley>`__
402 allocate 4000 to hire `Nikita Kniazev @Kojoley <https://github.com/Kojoley>`__
396 who did a fantastic job at updating our code base, migrating to pytest, pushing
403 who did a fantastic job at updating our code base, migrating to pytest, pushing
397 our coverage, and fixing a large number of bugs. I highly recommend contacting
404 our coverage, and fixing a large number of bugs. I highly recommend contacting
398 them if you need help with C++ and Python projects
405 them if you need help with C++ and Python projects
399
406
400 You can find all relevant issues and PRs with the SDG 2021 tag:
407 You can find all relevant issues and PRs with the SDG 2021 tag:
401
408
402 https://github.com/ipython/ipython/issues?q=label%3A%22Numfocus+SDG+2021%22+
409 https://github.com/ipython/ipython/issues?q=label%3A%22Numfocus+SDG+2021%22+
403
410
404 Removing support for Older Python
411 Removing support for Older Python
405 ---------------------------------
412 ---------------------------------
406
413
407
414
408 We are also removing support for Python up to 3.7 allowing internal code to use more
415 We are also removing support for Python up to 3.7 allowing internal code to use more
409 efficient ``pathlib``, and make better use of type annotations.
416 efficient ``pathlib``, and make better use of type annotations.
410
417
411 .. image:: ../_images/8.0/pathlib_pathlib_everywhere.jpg
418 .. image:: ../_images/8.0/pathlib_pathlib_everywhere.jpg
412 :alt: "Meme image of Toy story with Woody and Buzz, with the text 'pathlib, pathlib everywhere'"
419 :alt: "Meme image of Toy story with Woody and Buzz, with the text 'pathlib, pathlib everywhere'"
413
420
414
421
415 IMAGE : Pathlib, pathlib everywhere.
422 IMAGE : Pathlib, pathlib everywhere.
416
423
417 We have about 34 PRs only to update some logic tu update some function from managing strings to
424 We have about 34 PRs only to update some logic tu update some function from managing strings to
418 using Pathlib.
425 using Pathlib.
419
426
420 The completer has also seen significant updates and make use of newer Jedi API
427 The completer has also seen significant updates and make use of newer Jedi API
421 offering faster and more reliable tab completion.
428 offering faster and more reliable tab completion.
422
429
423 For the terminal users this also enable the auto-suggestion feature, described
430 For the terminal users this also enable the auto-suggestion feature, described
424 below, which show "ghost text" ahead of your cursor you can accept without
431 below, which show "ghost text" ahead of your cursor you can accept without
425 having to press the tab key or ask the completer to suggest completions.
432 having to press the tab key or ask the completer to suggest completions.
426
433
427
434
428
435
429 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
436 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
430
437
431 As a reminder, IPython master has diverged from the 7.x branch, thus master may
438 As a reminder, IPython master has diverged from the 7.x branch, thus master may
432 have more feature and API changes.
439 have more feature and API changes.
433
440
434 Backwards incompatible changes
441 Backwards incompatible changes
435 ------------------------------
442 ------------------------------
436
443
437 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
444 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
General Comments 0
You need to be logged in to leave comments. Login now