##// END OF EJS Templates
Add support for chained exceptions....
Matthias Bussonnier -
Show More
@@ -1,997 +1,1107 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Pdb debugger class.
4 4
5 5
6 6 This is an extension to PDB which adds a number of new features.
7 7 Note that there is also the `IPython.terminal.debugger` class which provides UI
8 8 improvements.
9 9
10 10 We also strongly recommend to use this via the `ipdb` package, which provides
11 11 extra configuration options.
12 12
13 13 Among other things, this subclass of PDB:
14 14 - supports many IPython magics like pdef/psource
15 15 - hide frames in tracebacks based on `__tracebackhide__`
16 16 - allows to skip frames based on `__debuggerskip__`
17 17
18 18 The skipping and hiding frames are configurable via the `skip_predicates`
19 19 command.
20 20
21 21 By default, frames from readonly files will be hidden, frames containing
22 22 ``__tracebackhide__=True`` will be hidden.
23 23
24 24 Frames containing ``__debuggerskip__`` will be stepped over, frames who's parent
25 25 frames value of ``__debuggerskip__`` is ``True`` will be skipped.
26 26
27 27 >>> def helpers_helper():
28 28 ... pass
29 29 ...
30 30 ... def helper_1():
31 31 ... print("don't step in me")
32 32 ... helpers_helpers() # will be stepped over unless breakpoint set.
33 33 ...
34 34 ...
35 35 ... def helper_2():
36 36 ... print("in me neither")
37 37 ...
38 38
39 39 One can define a decorator that wraps a function between the two helpers:
40 40
41 41 >>> def pdb_skipped_decorator(function):
42 42 ...
43 43 ...
44 44 ... def wrapped_fn(*args, **kwargs):
45 45 ... __debuggerskip__ = True
46 46 ... helper_1()
47 47 ... __debuggerskip__ = False
48 48 ... result = function(*args, **kwargs)
49 49 ... __debuggerskip__ = True
50 50 ... helper_2()
51 51 ... # setting __debuggerskip__ to False again is not necessary
52 52 ... return result
53 53 ...
54 54 ... return wrapped_fn
55 55
56 56 When decorating a function, ipdb will directly step into ``bar()`` by
57 57 default:
58 58
59 59 >>> @foo_decorator
60 60 ... def bar(x, y):
61 61 ... return x * y
62 62
63 63
64 64 You can toggle the behavior with
65 65
66 66 ipdb> skip_predicates debuggerskip false
67 67
68 68 or configure it in your ``.pdbrc``
69 69
70 70
71 71
72 72 License
73 73 -------
74 74
75 75 Modified from the standard pdb.Pdb class to avoid including readline, so that
76 76 the command line completion of other programs which include this isn't
77 77 damaged.
78 78
79 79 In the future, this class will be expanded with improvements over the standard
80 80 pdb.
81 81
82 82 The original code in this file is mainly lifted out of cmd.py in Python 2.2,
83 83 with minor changes. Licensing should therefore be under the standard Python
84 84 terms. For details on the PSF (Python Software Foundation) standard license,
85 85 see:
86 86
87 87 https://docs.python.org/2/license.html
88 88
89 89
90 90 All the changes since then are under the same license as IPython.
91 91
92 92 """
93 93
94 94 #*****************************************************************************
95 95 #
96 96 # This file is licensed under the PSF license.
97 97 #
98 98 # Copyright (C) 2001 Python Software Foundation, www.python.org
99 99 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
100 100 #
101 101 #
102 102 #*****************************************************************************
103 103
104 104 import inspect
105 105 import linecache
106 106 import sys
107 107 import re
108 108 import os
109 109
110 110 from IPython import get_ipython
111 from contextlib import contextmanager
111 112 from IPython.utils import PyColorize
112 113 from IPython.utils import coloransi, py3compat
113 114 from IPython.core.excolors import exception_colors
114 115
115 116 # skip module docstests
116 117 __skip_doctest__ = True
117 118
118 119 prompt = 'ipdb> '
119 120
120 121 # We have to check this directly from sys.argv, config struct not yet available
121 122 from pdb import Pdb as OldPdb
122 123
123 124 # Allow the set_trace code to operate outside of an ipython instance, even if
124 125 # it does so with some limitations. The rest of this support is implemented in
125 126 # the Tracer constructor.
126 127
127 128 DEBUGGERSKIP = "__debuggerskip__"
128 129
129 130
131 # this has been implemented in Pdb in Python 3.13 (https://github.com/python/cpython/pull/106676
132 # on lower python versions, we backported the feature.
133 CHAIN_EXCEPTIONS = sys.version_info < (3, 13)
134
135
130 136 def make_arrow(pad):
131 137 """generate the leading arrow in front of traceback or debugger"""
132 138 if pad >= 2:
133 139 return '-'*(pad-2) + '> '
134 140 elif pad == 1:
135 141 return '>'
136 142 return ''
137 143
138 144
139 145 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
140 146 """Exception hook which handles `BdbQuit` exceptions.
141 147
142 148 All other exceptions are processed using the `excepthook`
143 149 parameter.
144 150 """
145 151 raise ValueError(
146 152 "`BdbQuit_excepthook` is deprecated since version 5.1",
147 153 )
148 154
149 155
150 156 def BdbQuit_IPython_excepthook(self, et, ev, tb, tb_offset=None):
151 157 raise ValueError(
152 158 "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
153 159 DeprecationWarning, stacklevel=2)
154 160
155 161
156 162 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
157 163
158 164
159 165 def strip_indentation(multiline_string):
160 166 return RGX_EXTRA_INDENT.sub('', multiline_string)
161 167
162 168
163 169 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
164 170 """Make new_fn have old_fn's doc string. This is particularly useful
165 171 for the ``do_...`` commands that hook into the help system.
166 172 Adapted from from a comp.lang.python posting
167 173 by Duncan Booth."""
168 174 def wrapper(*args, **kw):
169 175 return new_fn(*args, **kw)
170 176 if old_fn.__doc__:
171 177 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
172 178 return wrapper
173 179
174 180
175 181 class Pdb(OldPdb):
176 182 """Modified Pdb class, does not load readline.
177 183
178 184 for a standalone version that uses prompt_toolkit, see
179 185 `IPython.terminal.debugger.TerminalPdb` and
180 186 `IPython.terminal.debugger.set_trace()`
181 187
182 188
183 189 This debugger can hide and skip frames that are tagged according to some predicates.
184 190 See the `skip_predicates` commands.
185 191
186 192 """
187 193
194 if CHAIN_EXCEPTIONS:
195 MAX_CHAINED_EXCEPTION_DEPTH = 999
196
188 197 default_predicates = {
189 198 "tbhide": True,
190 199 "readonly": False,
191 200 "ipython_internal": True,
192 201 "debuggerskip": True,
193 202 }
194 203
195 204 def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs):
196 205 """Create a new IPython debugger.
197 206
198 207 Parameters
199 208 ----------
200 209 completekey : default None
201 210 Passed to pdb.Pdb.
202 211 stdin : default None
203 212 Passed to pdb.Pdb.
204 213 stdout : default None
205 214 Passed to pdb.Pdb.
206 215 context : int
207 216 Number of lines of source code context to show when
208 217 displaying stacktrace information.
209 218 **kwargs
210 219 Passed to pdb.Pdb.
211 220
212 221 Notes
213 222 -----
214 223 The possibilities are python version dependent, see the python
215 224 docs for more info.
216 225 """
217 226
218 227 # Parent constructor:
219 228 try:
220 229 self.context = int(context)
221 230 if self.context <= 0:
222 231 raise ValueError("Context must be a positive integer")
223 232 except (TypeError, ValueError) as e:
224 233 raise ValueError("Context must be a positive integer") from e
225 234
226 235 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
227 236 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
228 237
229 238 # IPython changes...
230 239 self.shell = get_ipython()
231 240
232 241 if self.shell is None:
233 242 save_main = sys.modules['__main__']
234 243 # No IPython instance running, we must create one
235 244 from IPython.terminal.interactiveshell import \
236 245 TerminalInteractiveShell
237 246 self.shell = TerminalInteractiveShell.instance()
238 247 # needed by any code which calls __import__("__main__") after
239 248 # the debugger was entered. See also #9941.
240 249 sys.modules["__main__"] = save_main
241 250
242 251
243 252 color_scheme = self.shell.colors
244 253
245 254 self.aliases = {}
246 255
247 256 # Create color table: we copy the default one from the traceback
248 257 # module and add a few attributes needed for debugging
249 258 self.color_scheme_table = exception_colors()
250 259
251 260 # shorthands
252 261 C = coloransi.TermColors
253 262 cst = self.color_scheme_table
254 263
255 264 cst['NoColor'].colors.prompt = C.NoColor
256 265 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
257 266 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
258 267
259 268 cst['Linux'].colors.prompt = C.Green
260 269 cst['Linux'].colors.breakpoint_enabled = C.LightRed
261 270 cst['Linux'].colors.breakpoint_disabled = C.Red
262 271
263 272 cst['LightBG'].colors.prompt = C.Blue
264 273 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
265 274 cst['LightBG'].colors.breakpoint_disabled = C.Red
266 275
267 276 cst['Neutral'].colors.prompt = C.Blue
268 277 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
269 278 cst['Neutral'].colors.breakpoint_disabled = C.Red
270 279
271 280 # Add a python parser so we can syntax highlight source while
272 281 # debugging.
273 282 self.parser = PyColorize.Parser(style=color_scheme)
274 283 self.set_colors(color_scheme)
275 284
276 285 # Set the prompt - the default prompt is '(Pdb)'
277 286 self.prompt = prompt
278 287 self.skip_hidden = True
279 288 self.report_skipped = True
280 289
281 290 # list of predicates we use to skip frames
282 291 self._predicates = self.default_predicates
283 292
293 if CHAIN_EXCEPTIONS:
294 self._chained_exceptions = tuple()
295 self._chained_exception_index = 0
296
284 297 #
285 298 def set_colors(self, scheme):
286 299 """Shorthand access to the color table scheme selector method."""
287 300 self.color_scheme_table.set_active_scheme(scheme)
288 301 self.parser.style = scheme
289 302
290 303 def set_trace(self, frame=None):
291 304 if frame is None:
292 305 frame = sys._getframe().f_back
293 306 self.initial_frame = frame
294 307 return super().set_trace(frame)
295 308
296 309 def _hidden_predicate(self, frame):
297 310 """
298 311 Given a frame return whether it it should be hidden or not by IPython.
299 312 """
300 313
301 314 if self._predicates["readonly"]:
302 315 fname = frame.f_code.co_filename
303 316 # we need to check for file existence and interactively define
304 317 # function would otherwise appear as RO.
305 318 if os.path.isfile(fname) and not os.access(fname, os.W_OK):
306 319 return True
307 320
308 321 if self._predicates["tbhide"]:
309 322 if frame in (self.curframe, getattr(self, "initial_frame", None)):
310 323 return False
311 324 frame_locals = self._get_frame_locals(frame)
312 325 if "__tracebackhide__" not in frame_locals:
313 326 return False
314 327 return frame_locals["__tracebackhide__"]
315 328 return False
316 329
317 330 def hidden_frames(self, stack):
318 331 """
319 332 Given an index in the stack return whether it should be skipped.
320 333
321 334 This is used in up/down and where to skip frames.
322 335 """
323 336 # The f_locals dictionary is updated from the actual frame
324 337 # locals whenever the .f_locals accessor is called, so we
325 338 # avoid calling it here to preserve self.curframe_locals.
326 339 # Furthermore, there is no good reason to hide the current frame.
327 340 ip_hide = [self._hidden_predicate(s[0]) for s in stack]
328 341 ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"]
329 342 if ip_start and self._predicates["ipython_internal"]:
330 343 ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)]
331 344 return ip_hide
332 345
333 def interaction(self, frame, traceback):
346 if CHAIN_EXCEPTIONS:
347
348 def _get_tb_and_exceptions(self, tb_or_exc):
349 """
350 Given a tracecack or an exception, return a tuple of chained exceptions
351 and current traceback to inspect.
352 This will deal with selecting the right ``__cause__`` or ``__context__``
353 as well as handling cycles, and return a flattened list of exceptions we
354 can jump to with do_exceptions.
355 """
356 _exceptions = []
357 if isinstance(tb_or_exc, BaseException):
358 traceback, current = tb_or_exc.__traceback__, tb_or_exc
359
360 while current is not None:
361 if current in _exceptions:
362 break
363 _exceptions.append(current)
364 if current.__cause__ is not None:
365 current = current.__cause__
366 elif (
367 current.__context__ is not None
368 and not current.__suppress_context__
369 ):
370 current = current.__context__
371
372 if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH:
373 self.message(
374 f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}"
375 " chained exceptions found, not all exceptions"
376 "will be browsable with `exceptions`."
377 )
378 break
379 else:
380 traceback = tb_or_exc
381 return tuple(reversed(_exceptions)), traceback
382
383 @contextmanager
384 def _hold_exceptions(self, exceptions):
385 """
386 Context manager to ensure proper cleaning of exceptions references
387 When given a chained exception instead of a traceback,
388 pdb may hold references to many objects which may leak memory.
389 We use this context manager to make sure everything is properly cleaned
390 """
391 try:
392 self._chained_exceptions = exceptions
393 self._chained_exception_index = len(exceptions) - 1
394 yield
395 finally:
396 # we can't put those in forget as otherwise they would
397 # be cleared on exception change
398 self._chained_exceptions = tuple()
399 self._chained_exception_index = 0
400
401 def do_exceptions(self, arg):
402 """exceptions [number]
403 List or change current exception in an exception chain.
404 Without arguments, list all the current exception in the exception
405 chain. Exceptions will be numbered, with the current exception indicated
406 with an arrow.
407 If given an integer as argument, switch to the exception at that index.
408 """
409 if not self._chained_exceptions:
410 self.message(
411 "Did not find chained exceptions. To move between"
412 " exceptions, pdb/post_mortem must be given an exception"
413 " object rather than a traceback."
414 )
415 return
416 if not arg:
417 for ix, exc in enumerate(self._chained_exceptions):
418 prompt = ">" if ix == self._chained_exception_index else " "
419 rep = repr(exc)
420 if len(rep) > 80:
421 rep = rep[:77] + "..."
422 self.message(f"{prompt} {ix:>3} {rep}")
423 else:
424 try:
425 number = int(arg)
426 except ValueError:
427 self.error("Argument must be an integer")
428 return
429 if 0 <= number < len(self._chained_exceptions):
430 self._chained_exception_index = number
431 self.setup(None, self._chained_exceptions[number].__traceback__)
432 self.print_stack_entry(self.stack[self.curindex])
433 else:
434 self.error("No exception with that number")
435
436 def interaction(self, frame, tb_or_exc):
334 437 try:
335 OldPdb.interaction(self, frame, traceback)
438 if CHAIN_EXCEPTIONS:
439 # this context manager is part of interaction in 3.13
440 _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc)
441 with self._hold_exceptions(_chained_exceptions):
442 OldPdb.interaction(self, frame, tb)
443 else:
444 OldPdb.interaction(self, frame, traceback)
445
336 446 except KeyboardInterrupt:
337 447 self.stdout.write("\n" + self.shell.get_exception_only())
338 448
339 449 def precmd(self, line):
340 450 """Perform useful escapes on the command before it is executed."""
341 451
342 452 if line.endswith("??"):
343 453 line = "pinfo2 " + line[:-2]
344 454 elif line.endswith("?"):
345 455 line = "pinfo " + line[:-1]
346 456
347 457 line = super().precmd(line)
348 458
349 459 return line
350 460
351 461 def new_do_frame(self, arg):
352 462 OldPdb.do_frame(self, arg)
353 463
354 464 def new_do_quit(self, arg):
355 465
356 466 if hasattr(self, 'old_all_completions'):
357 467 self.shell.Completer.all_completions = self.old_all_completions
358 468
359 469 return OldPdb.do_quit(self, arg)
360 470
361 471 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
362 472
363 473 def new_do_restart(self, arg):
364 474 """Restart command. In the context of ipython this is exactly the same
365 475 thing as 'quit'."""
366 476 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
367 477 return self.do_quit(arg)
368 478
369 479 def print_stack_trace(self, context=None):
370 480 Colors = self.color_scheme_table.active_colors
371 481 ColorsNormal = Colors.Normal
372 482 if context is None:
373 483 context = self.context
374 484 try:
375 485 context = int(context)
376 486 if context <= 0:
377 487 raise ValueError("Context must be a positive integer")
378 488 except (TypeError, ValueError) as e:
379 489 raise ValueError("Context must be a positive integer") from e
380 490 try:
381 491 skipped = 0
382 492 for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack):
383 493 if hidden and self.skip_hidden:
384 494 skipped += 1
385 495 continue
386 496 if skipped:
387 497 print(
388 498 f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
389 499 )
390 500 skipped = 0
391 501 self.print_stack_entry(frame_lineno, context=context)
392 502 if skipped:
393 503 print(
394 504 f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
395 505 )
396 506 except KeyboardInterrupt:
397 507 pass
398 508
399 509 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
400 510 context=None):
401 511 if context is None:
402 512 context = self.context
403 513 try:
404 514 context = int(context)
405 515 if context <= 0:
406 516 raise ValueError("Context must be a positive integer")
407 517 except (TypeError, ValueError) as e:
408 518 raise ValueError("Context must be a positive integer") from e
409 519 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
410 520
411 521 # vds: >>
412 522 frame, lineno = frame_lineno
413 523 filename = frame.f_code.co_filename
414 524 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
415 525 # vds: <<
416 526
417 527 def _get_frame_locals(self, frame):
418 528 """ "
419 529 Accessing f_local of current frame reset the namespace, so we want to avoid
420 530 that or the following can happen
421 531
422 532 ipdb> foo
423 533 "old"
424 534 ipdb> foo = "new"
425 535 ipdb> foo
426 536 "new"
427 537 ipdb> where
428 538 ipdb> foo
429 539 "old"
430 540
431 541 So if frame is self.current_frame we instead return self.curframe_locals
432 542
433 543 """
434 544 if frame is self.curframe:
435 545 return self.curframe_locals
436 546 else:
437 547 return frame.f_locals
438 548
439 549 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
440 550 if context is None:
441 551 context = self.context
442 552 try:
443 553 context = int(context)
444 554 if context <= 0:
445 555 print("Context must be a positive integer", file=self.stdout)
446 556 except (TypeError, ValueError):
447 557 print("Context must be a positive integer", file=self.stdout)
448 558
449 559 import reprlib
450 560
451 561 ret = []
452 562
453 563 Colors = self.color_scheme_table.active_colors
454 564 ColorsNormal = Colors.Normal
455 565 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
456 566 tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
457 567 tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
458 568 tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal)
459 569
460 570 frame, lineno = frame_lineno
461 571
462 572 return_value = ''
463 573 loc_frame = self._get_frame_locals(frame)
464 574 if "__return__" in loc_frame:
465 575 rv = loc_frame["__return__"]
466 576 # return_value += '->'
467 577 return_value += reprlib.repr(rv) + "\n"
468 578 ret.append(return_value)
469 579
470 580 #s = filename + '(' + `lineno` + ')'
471 581 filename = self.canonic(frame.f_code.co_filename)
472 582 link = tpl_link % py3compat.cast_unicode(filename)
473 583
474 584 if frame.f_code.co_name:
475 585 func = frame.f_code.co_name
476 586 else:
477 587 func = "<lambda>"
478 588
479 589 call = ""
480 590 if func != "?":
481 591 if "__args__" in loc_frame:
482 592 args = reprlib.repr(loc_frame["__args__"])
483 593 else:
484 594 args = '()'
485 595 call = tpl_call % (func, args)
486 596
487 597 # The level info should be generated in the same format pdb uses, to
488 598 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
489 599 if frame is self.curframe:
490 600 ret.append('> ')
491 601 else:
492 602 ret.append(" ")
493 603 ret.append("%s(%s)%s\n" % (link, lineno, call))
494 604
495 605 start = lineno - 1 - context//2
496 606 lines = linecache.getlines(filename)
497 607 start = min(start, len(lines) - context)
498 608 start = max(start, 0)
499 609 lines = lines[start : start + context]
500 610
501 611 for i, line in enumerate(lines):
502 612 show_arrow = start + 1 + i == lineno
503 613 linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line
504 614 ret.append(
505 615 self.__format_line(
506 616 linetpl, filename, start + 1 + i, line, arrow=show_arrow
507 617 )
508 618 )
509 619 return "".join(ret)
510 620
511 621 def __format_line(self, tpl_line, filename, lineno, line, arrow=False):
512 622 bp_mark = ""
513 623 bp_mark_color = ""
514 624
515 625 new_line, err = self.parser.format2(line, 'str')
516 626 if not err:
517 627 line = new_line
518 628
519 629 bp = None
520 630 if lineno in self.get_file_breaks(filename):
521 631 bps = self.get_breaks(filename, lineno)
522 632 bp = bps[-1]
523 633
524 634 if bp:
525 635 Colors = self.color_scheme_table.active_colors
526 636 bp_mark = str(bp.number)
527 637 bp_mark_color = Colors.breakpoint_enabled
528 638 if not bp.enabled:
529 639 bp_mark_color = Colors.breakpoint_disabled
530 640
531 641 numbers_width = 7
532 642 if arrow:
533 643 # This is the line with the error
534 644 pad = numbers_width - len(str(lineno)) - len(bp_mark)
535 645 num = '%s%s' % (make_arrow(pad), str(lineno))
536 646 else:
537 647 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
538 648
539 649 return tpl_line % (bp_mark_color + bp_mark, num, line)
540 650
541 651 def print_list_lines(self, filename, first, last):
542 652 """The printing (as opposed to the parsing part of a 'list'
543 653 command."""
544 654 try:
545 655 Colors = self.color_scheme_table.active_colors
546 656 ColorsNormal = Colors.Normal
547 657 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
548 658 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
549 659 src = []
550 660 if filename == "<string>" and hasattr(self, "_exec_filename"):
551 661 filename = self._exec_filename
552 662
553 663 for lineno in range(first, last+1):
554 664 line = linecache.getline(filename, lineno)
555 665 if not line:
556 666 break
557 667
558 668 if lineno == self.curframe.f_lineno:
559 669 line = self.__format_line(
560 670 tpl_line_em, filename, lineno, line, arrow=True
561 671 )
562 672 else:
563 673 line = self.__format_line(
564 674 tpl_line, filename, lineno, line, arrow=False
565 675 )
566 676
567 677 src.append(line)
568 678 self.lineno = lineno
569 679
570 680 print(''.join(src), file=self.stdout)
571 681
572 682 except KeyboardInterrupt:
573 683 pass
574 684
575 685 def do_skip_predicates(self, args):
576 686 """
577 687 Turn on/off individual predicates as to whether a frame should be hidden/skip.
578 688
579 689 The global option to skip (or not) hidden frames is set with skip_hidden
580 690
581 691 To change the value of a predicate
582 692
583 693 skip_predicates key [true|false]
584 694
585 695 Call without arguments to see the current values.
586 696
587 697 To permanently change the value of an option add the corresponding
588 698 command to your ``~/.pdbrc`` file. If you are programmatically using the
589 699 Pdb instance you can also change the ``default_predicates`` class
590 700 attribute.
591 701 """
592 702 if not args.strip():
593 703 print("current predicates:")
594 704 for p, v in self._predicates.items():
595 705 print(" ", p, ":", v)
596 706 return
597 707 type_value = args.strip().split(" ")
598 708 if len(type_value) != 2:
599 709 print(
600 710 f"Usage: skip_predicates <type> <value>, with <type> one of {set(self._predicates.keys())}"
601 711 )
602 712 return
603 713
604 714 type_, value = type_value
605 715 if type_ not in self._predicates:
606 716 print(f"{type_!r} not in {set(self._predicates.keys())}")
607 717 return
608 718 if value.lower() not in ("true", "yes", "1", "no", "false", "0"):
609 719 print(
610 720 f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')"
611 721 )
612 722 return
613 723
614 724 self._predicates[type_] = value.lower() in ("true", "yes", "1")
615 725 if not any(self._predicates.values()):
616 726 print(
617 727 "Warning, all predicates set to False, skip_hidden may not have any effects."
618 728 )
619 729
620 730 def do_skip_hidden(self, arg):
621 731 """
622 732 Change whether or not we should skip frames with the
623 733 __tracebackhide__ attribute.
624 734 """
625 735 if not arg.strip():
626 736 print(
627 737 f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change."
628 738 )
629 739 elif arg.strip().lower() in ("true", "yes"):
630 740 self.skip_hidden = True
631 741 elif arg.strip().lower() in ("false", "no"):
632 742 self.skip_hidden = False
633 743 if not any(self._predicates.values()):
634 744 print(
635 745 "Warning, all predicates set to False, skip_hidden may not have any effects."
636 746 )
637 747
638 748 def do_list(self, arg):
639 749 """Print lines of code from the current stack frame
640 750 """
641 751 self.lastcmd = 'list'
642 752 last = None
643 753 if arg and arg != ".":
644 754 try:
645 755 x = eval(arg, {}, {})
646 756 if type(x) == type(()):
647 757 first, last = x
648 758 first = int(first)
649 759 last = int(last)
650 760 if last < first:
651 761 # Assume it's a count
652 762 last = first + last
653 763 else:
654 764 first = max(1, int(x) - 5)
655 765 except:
656 766 print('*** Error in argument:', repr(arg), file=self.stdout)
657 767 return
658 768 elif self.lineno is None or arg == ".":
659 769 first = max(1, self.curframe.f_lineno - 5)
660 770 else:
661 771 first = self.lineno + 1
662 772 if last is None:
663 773 last = first + 10
664 774 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
665 775
666 776 # vds: >>
667 777 lineno = first
668 778 filename = self.curframe.f_code.co_filename
669 779 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
670 780 # vds: <<
671 781
672 782 do_l = do_list
673 783
674 784 def getsourcelines(self, obj):
675 785 lines, lineno = inspect.findsource(obj)
676 786 if inspect.isframe(obj) and obj.f_globals is self._get_frame_locals(obj):
677 787 # must be a module frame: do not try to cut a block out of it
678 788 return lines, 1
679 789 elif inspect.ismodule(obj):
680 790 return lines, 1
681 791 return inspect.getblock(lines[lineno:]), lineno+1
682 792
683 793 def do_longlist(self, arg):
684 794 """Print lines of code from the current stack frame.
685 795
686 796 Shows more lines than 'list' does.
687 797 """
688 798 self.lastcmd = 'longlist'
689 799 try:
690 800 lines, lineno = self.getsourcelines(self.curframe)
691 801 except OSError as err:
692 802 self.error(err)
693 803 return
694 804 last = lineno + len(lines)
695 805 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
696 806 do_ll = do_longlist
697 807
698 808 def do_debug(self, arg):
699 809 """debug code
700 810 Enter a recursive debugger that steps through the code
701 811 argument (which is an arbitrary expression or statement to be
702 812 executed in the current environment).
703 813 """
704 814 trace_function = sys.gettrace()
705 815 sys.settrace(None)
706 816 globals = self.curframe.f_globals
707 817 locals = self.curframe_locals
708 818 p = self.__class__(completekey=self.completekey,
709 819 stdin=self.stdin, stdout=self.stdout)
710 820 p.use_rawinput = self.use_rawinput
711 821 p.prompt = "(%s) " % self.prompt.strip()
712 822 self.message("ENTERING RECURSIVE DEBUGGER")
713 823 sys.call_tracing(p.run, (arg, globals, locals))
714 824 self.message("LEAVING RECURSIVE DEBUGGER")
715 825 sys.settrace(trace_function)
716 826 self.lastcmd = p.lastcmd
717 827
718 828 def do_pdef(self, arg):
719 829 """Print the call signature for any callable object.
720 830
721 831 The debugger interface to %pdef"""
722 832 namespaces = [
723 833 ("Locals", self.curframe_locals),
724 834 ("Globals", self.curframe.f_globals),
725 835 ]
726 836 self.shell.find_line_magic("pdef")(arg, namespaces=namespaces)
727 837
728 838 def do_pdoc(self, arg):
729 839 """Print the docstring for an object.
730 840
731 841 The debugger interface to %pdoc."""
732 842 namespaces = [
733 843 ("Locals", self.curframe_locals),
734 844 ("Globals", self.curframe.f_globals),
735 845 ]
736 846 self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces)
737 847
738 848 def do_pfile(self, arg):
739 849 """Print (or run through pager) the file where an object is defined.
740 850
741 851 The debugger interface to %pfile.
742 852 """
743 853 namespaces = [
744 854 ("Locals", self.curframe_locals),
745 855 ("Globals", self.curframe.f_globals),
746 856 ]
747 857 self.shell.find_line_magic("pfile")(arg, namespaces=namespaces)
748 858
749 859 def do_pinfo(self, arg):
750 860 """Provide detailed information about an object.
751 861
752 862 The debugger interface to %pinfo, i.e., obj?."""
753 863 namespaces = [
754 864 ("Locals", self.curframe_locals),
755 865 ("Globals", self.curframe.f_globals),
756 866 ]
757 867 self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces)
758 868
759 869 def do_pinfo2(self, arg):
760 870 """Provide extra detailed information about an object.
761 871
762 872 The debugger interface to %pinfo2, i.e., obj??."""
763 873 namespaces = [
764 874 ("Locals", self.curframe_locals),
765 875 ("Globals", self.curframe.f_globals),
766 876 ]
767 877 self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces)
768 878
769 879 def do_psource(self, arg):
770 880 """Print (or run through pager) the source code for an object."""
771 881 namespaces = [
772 882 ("Locals", self.curframe_locals),
773 883 ("Globals", self.curframe.f_globals),
774 884 ]
775 885 self.shell.find_line_magic("psource")(arg, namespaces=namespaces)
776 886
777 887 def do_where(self, arg):
778 888 """w(here)
779 889 Print a stack trace, with the most recent frame at the bottom.
780 890 An arrow indicates the "current frame", which determines the
781 891 context of most commands. 'bt' is an alias for this command.
782 892
783 893 Take a number as argument as an (optional) number of context line to
784 894 print"""
785 895 if arg:
786 896 try:
787 897 context = int(arg)
788 898 except ValueError as err:
789 899 self.error(err)
790 900 return
791 901 self.print_stack_trace(context)
792 902 else:
793 903 self.print_stack_trace()
794 904
795 905 do_w = do_where
796 906
797 907 def break_anywhere(self, frame):
798 908 """
799 909 _stop_in_decorator_internals is overly restrictive, as we may still want
800 910 to trace function calls, so we need to also update break_anywhere so
801 911 that is we don't `stop_here`, because of debugger skip, we may still
802 912 stop at any point inside the function
803 913
804 914 """
805 915
806 916 sup = super().break_anywhere(frame)
807 917 if sup:
808 918 return sup
809 919 if self._predicates["debuggerskip"]:
810 920 if DEBUGGERSKIP in frame.f_code.co_varnames:
811 921 return True
812 922 if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
813 923 return True
814 924 return False
815 925
816 926 def _is_in_decorator_internal_and_should_skip(self, frame):
817 927 """
818 928 Utility to tell us whether we are in a decorator internal and should stop.
819 929
820 930 """
821 931
822 932 # if we are disabled don't skip
823 933 if not self._predicates["debuggerskip"]:
824 934 return False
825 935
826 936 # if frame is tagged, skip by default.
827 937 if DEBUGGERSKIP in frame.f_code.co_varnames:
828 938 return True
829 939
830 940 # if one of the parent frame value set to True skip as well.
831 941
832 942 cframe = frame
833 943 while getattr(cframe, "f_back", None):
834 944 cframe = cframe.f_back
835 945 if self._get_frame_locals(cframe).get(DEBUGGERSKIP):
836 946 return True
837 947
838 948 return False
839 949
840 950 def stop_here(self, frame):
841 951 if self._is_in_decorator_internal_and_should_skip(frame) is True:
842 952 return False
843 953
844 954 hidden = False
845 955 if self.skip_hidden:
846 956 hidden = self._hidden_predicate(frame)
847 957 if hidden:
848 958 if self.report_skipped:
849 959 Colors = self.color_scheme_table.active_colors
850 960 ColorsNormal = Colors.Normal
851 961 print(
852 962 f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n"
853 963 )
854 964 return super().stop_here(frame)
855 965
856 966 def do_up(self, arg):
857 967 """u(p) [count]
858 968 Move the current frame count (default one) levels up in the
859 969 stack trace (to an older frame).
860 970
861 971 Will skip hidden frames.
862 972 """
863 973 # modified version of upstream that skips
864 974 # frames with __tracebackhide__
865 975 if self.curindex == 0:
866 976 self.error("Oldest frame")
867 977 return
868 978 try:
869 979 count = int(arg or 1)
870 980 except ValueError:
871 981 self.error("Invalid frame count (%s)" % arg)
872 982 return
873 983 skipped = 0
874 984 if count < 0:
875 985 _newframe = 0
876 986 else:
877 987 counter = 0
878 988 hidden_frames = self.hidden_frames(self.stack)
879 989 for i in range(self.curindex - 1, -1, -1):
880 990 if hidden_frames[i] and self.skip_hidden:
881 991 skipped += 1
882 992 continue
883 993 counter += 1
884 994 if counter >= count:
885 995 break
886 996 else:
887 997 # if no break occurred.
888 998 self.error(
889 999 "all frames above hidden, use `skip_hidden False` to get get into those."
890 1000 )
891 1001 return
892 1002
893 1003 Colors = self.color_scheme_table.active_colors
894 1004 ColorsNormal = Colors.Normal
895 1005 _newframe = i
896 1006 self._select_frame(_newframe)
897 1007 if skipped:
898 1008 print(
899 1009 f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
900 1010 )
901 1011
902 1012 def do_down(self, arg):
903 1013 """d(own) [count]
904 1014 Move the current frame count (default one) levels down in the
905 1015 stack trace (to a newer frame).
906 1016
907 1017 Will skip hidden frames.
908 1018 """
909 1019 if self.curindex + 1 == len(self.stack):
910 1020 self.error("Newest frame")
911 1021 return
912 1022 try:
913 1023 count = int(arg or 1)
914 1024 except ValueError:
915 1025 self.error("Invalid frame count (%s)" % arg)
916 1026 return
917 1027 if count < 0:
918 1028 _newframe = len(self.stack) - 1
919 1029 else:
920 1030 counter = 0
921 1031 skipped = 0
922 1032 hidden_frames = self.hidden_frames(self.stack)
923 1033 for i in range(self.curindex + 1, len(self.stack)):
924 1034 if hidden_frames[i] and self.skip_hidden:
925 1035 skipped += 1
926 1036 continue
927 1037 counter += 1
928 1038 if counter >= count:
929 1039 break
930 1040 else:
931 1041 self.error(
932 1042 "all frames below hidden, use `skip_hidden False` to get get into those."
933 1043 )
934 1044 return
935 1045
936 1046 Colors = self.color_scheme_table.active_colors
937 1047 ColorsNormal = Colors.Normal
938 1048 if skipped:
939 1049 print(
940 1050 f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
941 1051 )
942 1052 _newframe = i
943 1053
944 1054 self._select_frame(_newframe)
945 1055
946 1056 do_d = do_down
947 1057 do_u = do_up
948 1058
949 1059 def do_context(self, context):
950 1060 """context number_of_lines
951 1061 Set the number of lines of source code to show when displaying
952 1062 stacktrace information.
953 1063 """
954 1064 try:
955 1065 new_context = int(context)
956 1066 if new_context <= 0:
957 1067 raise ValueError()
958 1068 self.context = new_context
959 1069 except ValueError:
960 1070 self.error("The 'context' command requires a positive integer argument.")
961 1071
962 1072
963 1073 class InterruptiblePdb(Pdb):
964 1074 """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
965 1075
966 1076 def cmdloop(self, intro=None):
967 1077 """Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
968 1078 try:
969 1079 return OldPdb.cmdloop(self, intro=intro)
970 1080 except KeyboardInterrupt:
971 1081 self.stop_here = lambda frame: False
972 1082 self.do_quit("")
973 1083 sys.settrace(None)
974 1084 self.quitting = False
975 1085 raise
976 1086
977 1087 def _cmdloop(self):
978 1088 while True:
979 1089 try:
980 1090 # keyboard interrupts allow for an easy way to cancel
981 1091 # the current command, so allow them during interactive input
982 1092 self.allow_kbdint = True
983 1093 self.cmdloop()
984 1094 self.allow_kbdint = False
985 1095 break
986 1096 except KeyboardInterrupt:
987 1097 self.message('--KeyboardInterrupt--')
988 1098 raise
989 1099
990 1100
991 1101 def set_trace(frame=None):
992 1102 """
993 1103 Start debugging from `frame`.
994 1104
995 1105 If frame is not specified, debugging starts from caller's frame.
996 1106 """
997 1107 Pdb().set_trace(frame or sys._getframe().f_back)
@@ -1,1519 +1,1525 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Verbose and colourful traceback formatting.
4 4
5 5 **ColorTB**
6 6
7 7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 8 ColorTB class is a solution to that problem. It colors the different parts of a
9 9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 10 text editor.
11 11
12 12 Installation instructions for ColorTB::
13 13
14 14 import sys,ultratb
15 15 sys.excepthook = ultratb.ColorTB()
16 16
17 17 **VerboseTB**
18 18
19 19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 21 and intended it for CGI programmers, but why should they have all the fun? I
22 22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 23 but kind of neat, and maybe useful for long-running programs that you believe
24 24 are bug-free. If a crash *does* occur in that type of program you want details.
25 25 Give it a shot--you'll love it or you'll hate it.
26 26
27 27 .. note::
28 28
29 29 The Verbose mode prints the variables currently visible where the exception
30 30 happened (shortening their strings if too long). This can potentially be
31 31 very slow, if you happen to have a huge data structure whose string
32 32 representation is complex to compute. Your computer may appear to freeze for
33 33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 34 with Ctrl-C (maybe hitting it more than once).
35 35
36 36 If you encounter this kind of situation often, you may want to use the
37 37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 38 variables (but otherwise includes the information and context given by
39 39 Verbose).
40 40
41 41 .. note::
42 42
43 43 The verbose mode print all variables in the stack, which means it can
44 44 potentially leak sensitive information like access keys, or unencrypted
45 45 password.
46 46
47 47 Installation instructions for VerboseTB::
48 48
49 49 import sys,ultratb
50 50 sys.excepthook = ultratb.VerboseTB()
51 51
52 52 Note: Much of the code in this module was lifted verbatim from the standard
53 53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54 54
55 55 Color schemes
56 56 -------------
57 57
58 58 The colors are defined in the class TBTools through the use of the
59 59 ColorSchemeTable class. Currently the following exist:
60 60
61 61 - NoColor: allows all of this module to be used in any terminal (the color
62 62 escapes are just dummy blank strings).
63 63
64 64 - Linux: is meant to look good in a terminal like the Linux console (black
65 65 or very dark background).
66 66
67 67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 68 in light background terminals.
69 69
70 70 - Neutral: a neutral color scheme that should be readable on both light and
71 71 dark background
72 72
73 73 You can implement other color schemes easily, the syntax is fairly
74 74 self-explanatory. Please send back new schemes you develop to the author for
75 75 possible inclusion in future releases.
76 76
77 77 Inheritance diagram:
78 78
79 79 .. inheritance-diagram:: IPython.core.ultratb
80 80 :parts: 3
81 81 """
82 82
83 83 #*****************************************************************************
84 84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 86 #
87 87 # Distributed under the terms of the BSD License. The full license is in
88 88 # the file COPYING, distributed as part of this software.
89 89 #*****************************************************************************
90 90
91 91
92 92 from collections.abc import Sequence
93 93 import functools
94 94 import inspect
95 95 import linecache
96 96 import pydoc
97 97 import sys
98 98 import time
99 99 import traceback
100 100 import types
101 101 from types import TracebackType
102 102 from typing import Any, List, Optional, Tuple
103 103
104 104 import stack_data
105 105 from pygments.formatters.terminal256 import Terminal256Formatter
106 106 from pygments.styles import get_style_by_name
107 107
108 108 import IPython.utils.colorable as colorable
109 109 # IPython's own modules
110 110 from IPython import get_ipython
111 111 from IPython.core import debugger
112 112 from IPython.core.display_trap import DisplayTrap
113 113 from IPython.core.excolors import exception_colors
114 114 from IPython.utils import PyColorize
115 115 from IPython.utils import path as util_path
116 116 from IPython.utils import py3compat
117 117 from IPython.utils.terminal import get_terminal_size
118 118
119 119 # Globals
120 120 # amount of space to put line numbers before verbose tracebacks
121 121 INDENT_SIZE = 8
122 122
123 123 # Default color scheme. This is used, for example, by the traceback
124 124 # formatter. When running in an actual IPython instance, the user's rc.colors
125 125 # value is used, but having a module global makes this functionality available
126 126 # to users of ultratb who are NOT running inside ipython.
127 127 DEFAULT_SCHEME = 'NoColor'
128 128 FAST_THRESHOLD = 10_000
129 129
130 130 # ---------------------------------------------------------------------------
131 131 # Code begins
132 132
133 133 # Helper function -- largely belongs to VerboseTB, but we need the same
134 134 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
135 135 # can be recognized properly by ipython.el's py-traceback-line-re
136 136 # (SyntaxErrors have to be treated specially because they have no traceback)
137 137
138 138
139 139 @functools.lru_cache()
140 140 def count_lines_in_py_file(filename: str) -> int:
141 141 """
142 142 Given a filename, returns the number of lines in the file
143 143 if it ends with the extension ".py". Otherwise, returns 0.
144 144 """
145 145 if not filename.endswith(".py"):
146 146 return 0
147 147 else:
148 148 try:
149 149 with open(filename, "r") as file:
150 150 s = sum(1 for line in file)
151 151 except UnicodeError:
152 152 return 0
153 153 return s
154 154
155 155 """
156 156 Given a frame object, returns the total number of lines in the file
157 157 if the filename ends with the extension ".py". Otherwise, returns 0.
158 158 """
159 159
160 160
161 161 def get_line_number_of_frame(frame: types.FrameType) -> int:
162 162 """
163 163 Given a frame object, returns the total number of lines in the file
164 164 containing the frame's code object, or the number of lines in the
165 165 frame's source code if the file is not available.
166 166
167 167 Parameters
168 168 ----------
169 169 frame : FrameType
170 170 The frame object whose line number is to be determined.
171 171
172 172 Returns
173 173 -------
174 174 int
175 175 The total number of lines in the file containing the frame's
176 176 code object, or the number of lines in the frame's source code
177 177 if the file is not available.
178 178 """
179 179 filename = frame.f_code.co_filename
180 180 if filename is None:
181 181 print("No file....")
182 182 lines, first = inspect.getsourcelines(frame)
183 183 return first + len(lines)
184 184 return count_lines_in_py_file(filename)
185 185
186 186
187 187 def _safe_string(value, what, func=str):
188 188 # Copied from cpython/Lib/traceback.py
189 189 try:
190 190 return func(value)
191 191 except:
192 192 return f"<{what} {func.__name__}() failed>"
193 193
194 194
195 195 def _format_traceback_lines(lines, Colors, has_colors: bool, lvals):
196 196 """
197 197 Format tracebacks lines with pointing arrow, leading numbers...
198 198
199 199 Parameters
200 200 ----------
201 201 lines : list[Line]
202 202 Colors
203 203 ColorScheme used.
204 204 lvals : str
205 205 Values of local variables, already colored, to inject just after the error line.
206 206 """
207 207 numbers_width = INDENT_SIZE - 1
208 208 res = []
209 209
210 210 for stack_line in lines:
211 211 if stack_line is stack_data.LINE_GAP:
212 212 res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal))
213 213 continue
214 214
215 215 line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n'
216 216 lineno = stack_line.lineno
217 217 if stack_line.is_current:
218 218 # This is the line with the error
219 219 pad = numbers_width - len(str(lineno))
220 220 num = '%s%s' % (debugger.make_arrow(pad), str(lineno))
221 221 start_color = Colors.linenoEm
222 222 else:
223 223 num = '%*s' % (numbers_width, lineno)
224 224 start_color = Colors.lineno
225 225
226 226 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
227 227
228 228 res.append(line)
229 229 if lvals and stack_line.is_current:
230 230 res.append(lvals + '\n')
231 231 return res
232 232
233 233 def _simple_format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format):
234 234 """
235 235 Format tracebacks lines with pointing arrow, leading numbers...
236 236
237 237 Parameters
238 238 ==========
239 239
240 240 lnum: int
241 241 number of the target line of code.
242 242 index: int
243 243 which line in the list should be highlighted.
244 244 lines: list[string]
245 245 Colors:
246 246 ColorScheme used.
247 247 lvals: bytes
248 248 Values of local variables, already colored, to inject just after the error line.
249 249 _line_format: f (str) -> (str, bool)
250 250 return (colorized version of str, failure to do so)
251 251 """
252 252 numbers_width = INDENT_SIZE - 1
253 253 res = []
254 254 for i, line in enumerate(lines, lnum - index):
255 255 # assert isinstance(line, str)
256 256 line = py3compat.cast_unicode(line)
257 257
258 258 new_line, err = _line_format(line, "str")
259 259 if not err:
260 260 line = new_line
261 261
262 262 if i == lnum:
263 263 # This is the line with the error
264 264 pad = numbers_width - len(str(i))
265 265 num = "%s%s" % (debugger.make_arrow(pad), str(lnum))
266 266 line = "%s%s%s %s%s" % (
267 267 Colors.linenoEm,
268 268 num,
269 269 Colors.line,
270 270 line,
271 271 Colors.Normal,
272 272 )
273 273 else:
274 274 num = "%*s" % (numbers_width, i)
275 275 line = "%s%s%s %s" % (Colors.lineno, num, Colors.Normal, line)
276 276
277 277 res.append(line)
278 278 if lvals and i == lnum:
279 279 res.append(lvals + "\n")
280 280 return res
281 281
282 282
283 283 def _format_filename(file, ColorFilename, ColorNormal, *, lineno=None):
284 284 """
285 285 Format filename lines with custom formatting from caching compiler or `File *.py` by default
286 286
287 287 Parameters
288 288 ----------
289 289 file : str
290 290 ColorFilename
291 291 ColorScheme's filename coloring to be used.
292 292 ColorNormal
293 293 ColorScheme's normal coloring to be used.
294 294 """
295 295 ipinst = get_ipython()
296 296 if (
297 297 ipinst is not None
298 298 and (data := ipinst.compile.format_code_name(file)) is not None
299 299 ):
300 300 label, name = data
301 301 if lineno is None:
302 302 tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}"
303 303 else:
304 304 tpl_link = (
305 305 f"{{label}} {ColorFilename}{{name}}, line {{lineno}}{ColorNormal}"
306 306 )
307 307 else:
308 308 label = "File"
309 309 name = util_path.compress_user(
310 310 py3compat.cast_unicode(file, util_path.fs_encoding)
311 311 )
312 312 if lineno is None:
313 313 tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}"
314 314 else:
315 315 # can we make this the more friendly ", line {{lineno}}", or do we need to preserve the formatting with the colon?
316 316 tpl_link = f"{{label}} {ColorFilename}{{name}}:{{lineno}}{ColorNormal}"
317 317
318 318 return tpl_link.format(label=label, name=name, lineno=lineno)
319 319
320 320 #---------------------------------------------------------------------------
321 321 # Module classes
322 322 class TBTools(colorable.Colorable):
323 323 """Basic tools used by all traceback printer classes."""
324 324
325 325 # Number of frames to skip when reporting tracebacks
326 326 tb_offset = 0
327 327
328 328 def __init__(
329 329 self,
330 330 color_scheme="NoColor",
331 331 call_pdb=False,
332 332 ostream=None,
333 333 parent=None,
334 334 config=None,
335 335 *,
336 336 debugger_cls=None,
337 337 ):
338 338 # Whether to call the interactive pdb debugger after printing
339 339 # tracebacks or not
340 340 super(TBTools, self).__init__(parent=parent, config=config)
341 341 self.call_pdb = call_pdb
342 342
343 343 # Output stream to write to. Note that we store the original value in
344 344 # a private attribute and then make the public ostream a property, so
345 345 # that we can delay accessing sys.stdout until runtime. The way
346 346 # things are written now, the sys.stdout object is dynamically managed
347 347 # so a reference to it should NEVER be stored statically. This
348 348 # property approach confines this detail to a single location, and all
349 349 # subclasses can simply access self.ostream for writing.
350 350 self._ostream = ostream
351 351
352 352 # Create color table
353 353 self.color_scheme_table = exception_colors()
354 354
355 355 self.set_colors(color_scheme)
356 356 self.old_scheme = color_scheme # save initial value for toggles
357 357 self.debugger_cls = debugger_cls or debugger.Pdb
358 358
359 359 if call_pdb:
360 360 self.pdb = self.debugger_cls()
361 361 else:
362 362 self.pdb = None
363 363
364 364 def _get_ostream(self):
365 365 """Output stream that exceptions are written to.
366 366
367 367 Valid values are:
368 368
369 369 - None: the default, which means that IPython will dynamically resolve
370 370 to sys.stdout. This ensures compatibility with most tools, including
371 371 Windows (where plain stdout doesn't recognize ANSI escapes).
372 372
373 373 - Any object with 'write' and 'flush' attributes.
374 374 """
375 375 return sys.stdout if self._ostream is None else self._ostream
376 376
377 377 def _set_ostream(self, val):
378 378 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
379 379 self._ostream = val
380 380
381 381 ostream = property(_get_ostream, _set_ostream)
382 382
383 383 @staticmethod
384 384 def _get_chained_exception(exception_value):
385 385 cause = getattr(exception_value, "__cause__", None)
386 386 if cause:
387 387 return cause
388 388 if getattr(exception_value, "__suppress_context__", False):
389 389 return None
390 390 return getattr(exception_value, "__context__", None)
391 391
392 392 def get_parts_of_chained_exception(
393 393 self, evalue
394 394 ) -> Optional[Tuple[type, BaseException, TracebackType]]:
395 395 chained_evalue = self._get_chained_exception(evalue)
396 396
397 397 if chained_evalue:
398 398 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
399 399 return None
400 400
401 401 def prepare_chained_exception_message(self, cause) -> List[Any]:
402 402 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
403 403 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
404 404
405 405 if cause:
406 406 message = [[direct_cause]]
407 407 else:
408 408 message = [[exception_during_handling]]
409 409 return message
410 410
411 411 @property
412 412 def has_colors(self) -> bool:
413 413 return self.color_scheme_table.active_scheme_name.lower() != "nocolor"
414 414
415 415 def set_colors(self, *args, **kw):
416 416 """Shorthand access to the color table scheme selector method."""
417 417
418 418 # Set own color table
419 419 self.color_scheme_table.set_active_scheme(*args, **kw)
420 420 # for convenience, set Colors to the active scheme
421 421 self.Colors = self.color_scheme_table.active_colors
422 422 # Also set colors of debugger
423 423 if hasattr(self, 'pdb') and self.pdb is not None:
424 424 self.pdb.set_colors(*args, **kw)
425 425
426 426 def color_toggle(self):
427 427 """Toggle between the currently active color scheme and NoColor."""
428 428
429 429 if self.color_scheme_table.active_scheme_name == 'NoColor':
430 430 self.color_scheme_table.set_active_scheme(self.old_scheme)
431 431 self.Colors = self.color_scheme_table.active_colors
432 432 else:
433 433 self.old_scheme = self.color_scheme_table.active_scheme_name
434 434 self.color_scheme_table.set_active_scheme('NoColor')
435 435 self.Colors = self.color_scheme_table.active_colors
436 436
437 437 def stb2text(self, stb):
438 438 """Convert a structured traceback (a list) to a string."""
439 439 return '\n'.join(stb)
440 440
441 441 def text(self, etype, value, tb, tb_offset: Optional[int] = None, context=5):
442 442 """Return formatted traceback.
443 443
444 444 Subclasses may override this if they add extra arguments.
445 445 """
446 446 tb_list = self.structured_traceback(etype, value, tb,
447 447 tb_offset, context)
448 448 return self.stb2text(tb_list)
449 449
450 450 def structured_traceback(
451 451 self,
452 452 etype: type,
453 453 evalue: Optional[BaseException],
454 454 etb: Optional[TracebackType] = None,
455 455 tb_offset: Optional[int] = None,
456 456 number_of_lines_of_context: int = 5,
457 457 ):
458 458 """Return a list of traceback frames.
459 459
460 460 Must be implemented by each class.
461 461 """
462 462 raise NotImplementedError()
463 463
464 464
465 465 #---------------------------------------------------------------------------
466 466 class ListTB(TBTools):
467 467 """Print traceback information from a traceback list, with optional color.
468 468
469 469 Calling requires 3 arguments: (etype, evalue, elist)
470 470 as would be obtained by::
471 471
472 472 etype, evalue, tb = sys.exc_info()
473 473 if tb:
474 474 elist = traceback.extract_tb(tb)
475 475 else:
476 476 elist = None
477 477
478 478 It can thus be used by programs which need to process the traceback before
479 479 printing (such as console replacements based on the code module from the
480 480 standard library).
481 481
482 482 Because they are meant to be called without a full traceback (only a
483 483 list), instances of this class can't call the interactive pdb debugger."""
484 484
485 485
486 486 def __call__(self, etype, value, elist):
487 487 self.ostream.flush()
488 488 self.ostream.write(self.text(etype, value, elist))
489 489 self.ostream.write('\n')
490 490
491 491 def _extract_tb(self, tb):
492 492 if tb:
493 493 return traceback.extract_tb(tb)
494 494 else:
495 495 return None
496 496
497 497 def structured_traceback(
498 498 self,
499 499 etype: type,
500 500 evalue: Optional[BaseException],
501 501 etb: Optional[TracebackType] = None,
502 502 tb_offset: Optional[int] = None,
503 503 context=5,
504 504 ):
505 505 """Return a color formatted string with the traceback info.
506 506
507 507 Parameters
508 508 ----------
509 509 etype : exception type
510 510 Type of the exception raised.
511 511 evalue : object
512 512 Data stored in the exception
513 513 etb : list | TracebackType | None
514 514 If list: List of frames, see class docstring for details.
515 515 If Traceback: Traceback of the exception.
516 516 tb_offset : int, optional
517 517 Number of frames in the traceback to skip. If not given, the
518 518 instance evalue is used (set in constructor).
519 519 context : int, optional
520 520 Number of lines of context information to print.
521 521
522 522 Returns
523 523 -------
524 524 String with formatted exception.
525 525 """
526 526 # This is a workaround to get chained_exc_ids in recursive calls
527 527 # etb should not be a tuple if structured_traceback is not recursive
528 528 if isinstance(etb, tuple):
529 529 etb, chained_exc_ids = etb
530 530 else:
531 531 chained_exc_ids = set()
532 532
533 533 if isinstance(etb, list):
534 534 elist = etb
535 535 elif etb is not None:
536 536 elist = self._extract_tb(etb)
537 537 else:
538 538 elist = []
539 539 tb_offset = self.tb_offset if tb_offset is None else tb_offset
540 540 assert isinstance(tb_offset, int)
541 541 Colors = self.Colors
542 542 out_list = []
543 543 if elist:
544 544
545 545 if tb_offset and len(elist) > tb_offset:
546 546 elist = elist[tb_offset:]
547 547
548 548 out_list.append('Traceback %s(most recent call last)%s:' %
549 549 (Colors.normalEm, Colors.Normal) + '\n')
550 550 out_list.extend(self._format_list(elist))
551 551 # The exception info should be a single entry in the list.
552 552 lines = ''.join(self._format_exception_only(etype, evalue))
553 553 out_list.append(lines)
554 554
555 555 exception = self.get_parts_of_chained_exception(evalue)
556 556
557 557 if exception and (id(exception[1]) not in chained_exc_ids):
558 558 chained_exception_message = (
559 559 self.prepare_chained_exception_message(evalue.__cause__)[0]
560 560 if evalue is not None
561 561 else ""
562 562 )
563 563 etype, evalue, etb = exception
564 564 # Trace exception to avoid infinite 'cause' loop
565 565 chained_exc_ids.add(id(exception[1]))
566 566 chained_exceptions_tb_offset = 0
567 567 out_list = (
568 568 self.structured_traceback(
569 569 etype,
570 570 evalue,
571 571 (etb, chained_exc_ids), # type: ignore
572 572 chained_exceptions_tb_offset,
573 573 context,
574 574 )
575 575 + chained_exception_message
576 576 + out_list)
577 577
578 578 return out_list
579 579
580 580 def _format_list(self, extracted_list):
581 581 """Format a list of traceback entry tuples for printing.
582 582
583 583 Given a list of tuples as returned by extract_tb() or
584 584 extract_stack(), return a list of strings ready for printing.
585 585 Each string in the resulting list corresponds to the item with the
586 586 same index in the argument list. Each string ends in a newline;
587 587 the strings may contain internal newlines as well, for those items
588 588 whose source text line is not None.
589 589
590 590 Lifted almost verbatim from traceback.py
591 591 """
592 592
593 593 Colors = self.Colors
594 594 output_list = []
595 595 for ind, (filename, lineno, name, line) in enumerate(extracted_list):
596 596 normalCol, nameCol, fileCol, lineCol = (
597 597 # Emphasize the last entry
598 598 (Colors.normalEm, Colors.nameEm, Colors.filenameEm, Colors.line)
599 599 if ind == len(extracted_list) - 1
600 600 else (Colors.Normal, Colors.name, Colors.filename, "")
601 601 )
602 602
603 603 fns = _format_filename(filename, fileCol, normalCol, lineno=lineno)
604 604 item = f"{normalCol} {fns}"
605 605
606 606 if name != "<module>":
607 607 item += f" in {nameCol}{name}{normalCol}\n"
608 608 else:
609 609 item += "\n"
610 610 if line:
611 611 item += f"{lineCol} {line.strip()}{normalCol}\n"
612 612 output_list.append(item)
613 613
614 614 return output_list
615 615
616 616 def _format_exception_only(self, etype, value):
617 617 """Format the exception part of a traceback.
618 618
619 619 The arguments are the exception type and value such as given by
620 620 sys.exc_info()[:2]. The return value is a list of strings, each ending
621 621 in a newline. Normally, the list contains a single string; however,
622 622 for SyntaxError exceptions, it contains several lines that (when
623 623 printed) display detailed information about where the syntax error
624 624 occurred. The message indicating which exception occurred is the
625 625 always last string in the list.
626 626
627 627 Also lifted nearly verbatim from traceback.py
628 628 """
629 629 have_filedata = False
630 630 Colors = self.Colors
631 631 output_list = []
632 632 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
633 633 if value is None:
634 634 # Not sure if this can still happen in Python 2.6 and above
635 635 output_list.append(stype + "\n")
636 636 else:
637 637 if issubclass(etype, SyntaxError):
638 638 have_filedata = True
639 639 if not value.filename: value.filename = "<string>"
640 640 if value.lineno:
641 641 lineno = value.lineno
642 642 textline = linecache.getline(value.filename, value.lineno)
643 643 else:
644 644 lineno = "unknown"
645 645 textline = ""
646 646 output_list.append(
647 647 "%s %s%s\n"
648 648 % (
649 649 Colors.normalEm,
650 650 _format_filename(
651 651 value.filename,
652 652 Colors.filenameEm,
653 653 Colors.normalEm,
654 654 lineno=(None if lineno == "unknown" else lineno),
655 655 ),
656 656 Colors.Normal,
657 657 )
658 658 )
659 659 if textline == "":
660 660 textline = py3compat.cast_unicode(value.text, "utf-8")
661 661
662 662 if textline is not None:
663 663 i = 0
664 664 while i < len(textline) and textline[i].isspace():
665 665 i += 1
666 666 output_list.append(
667 667 "%s %s%s\n" % (Colors.line, textline.strip(), Colors.Normal)
668 668 )
669 669 if value.offset is not None:
670 670 s = ' '
671 671 for c in textline[i:value.offset - 1]:
672 672 if c.isspace():
673 673 s += c
674 674 else:
675 675 s += " "
676 676 output_list.append(
677 677 "%s%s^%s\n" % (Colors.caret, s, Colors.Normal)
678 678 )
679 679
680 680 try:
681 681 s = value.msg
682 682 except Exception:
683 683 s = self._some_str(value)
684 684 if s:
685 685 output_list.append(
686 686 "%s%s:%s %s\n" % (stype, Colors.excName, Colors.Normal, s)
687 687 )
688 688 else:
689 689 output_list.append("%s\n" % stype)
690 690
691 691 # PEP-678 notes
692 692 output_list.extend(f"{x}\n" for x in getattr(value, "__notes__", []))
693 693
694 694 # sync with user hooks
695 695 if have_filedata:
696 696 ipinst = get_ipython()
697 697 if ipinst is not None:
698 698 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
699 699
700 700 return output_list
701 701
702 702 def get_exception_only(self, etype, value):
703 703 """Only print the exception type and message, without a traceback.
704 704
705 705 Parameters
706 706 ----------
707 707 etype : exception type
708 708 value : exception value
709 709 """
710 710 return ListTB.structured_traceback(self, etype, value)
711 711
712 712 def show_exception_only(self, etype, evalue):
713 713 """Only print the exception type and message, without a traceback.
714 714
715 715 Parameters
716 716 ----------
717 717 etype : exception type
718 718 evalue : exception value
719 719 """
720 720 # This method needs to use __call__ from *this* class, not the one from
721 721 # a subclass whose signature or behavior may be different
722 722 ostream = self.ostream
723 723 ostream.flush()
724 724 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
725 725 ostream.flush()
726 726
727 727 def _some_str(self, value):
728 728 # Lifted from traceback.py
729 729 try:
730 730 return py3compat.cast_unicode(str(value))
731 731 except:
732 732 return u'<unprintable %s object>' % type(value).__name__
733 733
734 734
735 735 class FrameInfo:
736 736 """
737 737 Mirror of stack data's FrameInfo, but so that we can bypass highlighting on
738 738 really long frames.
739 739 """
740 740
741 741 description: Optional[str]
742 742 filename: Optional[str]
743 743 lineno: Tuple[int]
744 744 # number of context lines to use
745 745 context: Optional[int]
746 746
747 747 @classmethod
748 748 def _from_stack_data_FrameInfo(cls, frame_info):
749 749 return cls(
750 750 getattr(frame_info, "description", None),
751 751 getattr(frame_info, "filename", None), # type: ignore[arg-type]
752 752 getattr(frame_info, "lineno", None), # type: ignore[arg-type]
753 753 getattr(frame_info, "frame", None),
754 754 getattr(frame_info, "code", None),
755 755 sd=frame_info,
756 756 context=None,
757 757 )
758 758
759 759 def __init__(
760 760 self,
761 761 description: Optional[str],
762 762 filename: str,
763 763 lineno: Tuple[int],
764 764 frame,
765 765 code,
766 766 *,
767 767 sd=None,
768 768 context=None,
769 769 ):
770 770 self.description = description
771 771 self.filename = filename
772 772 self.lineno = lineno
773 773 self.frame = frame
774 774 self.code = code
775 775 self._sd = sd
776 776 self.context = context
777 777
778 778 # self.lines = []
779 779 if sd is None:
780 780 ix = inspect.getsourcelines(frame)
781 781 self.raw_lines = ix[0]
782 782
783 783 @property
784 784 def variables_in_executing_piece(self):
785 785 if self._sd:
786 786 return self._sd.variables_in_executing_piece
787 787 else:
788 788 return []
789 789
790 790 @property
791 791 def lines(self):
792 792 return self._sd.lines
793 793
794 794 @property
795 795 def executing(self):
796 796 if self._sd:
797 797 return self._sd.executing
798 798 else:
799 799 return None
800 800
801 801
802 802 # ----------------------------------------------------------------------------
803 803 class VerboseTB(TBTools):
804 804 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
805 805 of HTML. Requires inspect and pydoc. Crazy, man.
806 806
807 807 Modified version which optionally strips the topmost entries from the
808 808 traceback, to be used with alternate interpreters (because their own code
809 809 would appear in the traceback)."""
810 810
811 811 _tb_highlight = "bg:ansiyellow"
812 812 _tb_highlight_style = "default"
813 813
814 814 def __init__(
815 815 self,
816 816 color_scheme: str = "Linux",
817 817 call_pdb: bool = False,
818 818 ostream=None,
819 819 tb_offset: int = 0,
820 820 long_header: bool = False,
821 821 include_vars: bool = True,
822 822 check_cache=None,
823 823 debugger_cls=None,
824 824 parent=None,
825 825 config=None,
826 826 ):
827 827 """Specify traceback offset, headers and color scheme.
828 828
829 829 Define how many frames to drop from the tracebacks. Calling it with
830 830 tb_offset=1 allows use of this handler in interpreters which will have
831 831 their own code at the top of the traceback (VerboseTB will first
832 832 remove that frame before printing the traceback info)."""
833 833 TBTools.__init__(
834 834 self,
835 835 color_scheme=color_scheme,
836 836 call_pdb=call_pdb,
837 837 ostream=ostream,
838 838 parent=parent,
839 839 config=config,
840 840 debugger_cls=debugger_cls,
841 841 )
842 842 self.tb_offset = tb_offset
843 843 self.long_header = long_header
844 844 self.include_vars = include_vars
845 845 # By default we use linecache.checkcache, but the user can provide a
846 846 # different check_cache implementation. This was formerly used by the
847 847 # IPython kernel for interactive code, but is no longer necessary.
848 848 if check_cache is None:
849 849 check_cache = linecache.checkcache
850 850 self.check_cache = check_cache
851 851
852 852 self.skip_hidden = True
853 853
854 854 def format_record(self, frame_info: FrameInfo):
855 855 """Format a single stack frame"""
856 856 assert isinstance(frame_info, FrameInfo)
857 857 Colors = self.Colors # just a shorthand + quicker name lookup
858 858 ColorsNormal = Colors.Normal # used a lot
859 859
860 860 if isinstance(frame_info._sd, stack_data.RepeatedFrames):
861 861 return ' %s[... skipping similar frames: %s]%s\n' % (
862 862 Colors.excName, frame_info.description, ColorsNormal)
863 863
864 864 indent = " " * INDENT_SIZE
865 865 em_normal = "%s\n%s%s" % (Colors.valEm, indent, ColorsNormal)
866 866 tpl_call = f"in {Colors.vName}{{file}}{Colors.valEm}{{scope}}{ColorsNormal}"
867 867 tpl_call_fail = "in %s%%s%s(***failed resolving arguments***)%s" % (
868 868 Colors.vName,
869 869 Colors.valEm,
870 870 ColorsNormal,
871 871 )
872 872 tpl_name_val = "%%s %s= %%s%s" % (Colors.valEm, ColorsNormal)
873 873
874 874 link = _format_filename(
875 875 frame_info.filename,
876 876 Colors.filenameEm,
877 877 ColorsNormal,
878 878 lineno=frame_info.lineno,
879 879 )
880 880 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
881 881 if frame_info.executing is not None:
882 882 func = frame_info.executing.code_qualname()
883 883 else:
884 884 func = "?"
885 885 if func == "<module>":
886 886 call = ""
887 887 else:
888 888 # Decide whether to include variable details or not
889 889 var_repr = eqrepr if self.include_vars else nullrepr
890 890 try:
891 891 scope = inspect.formatargvalues(
892 892 args, varargs, varkw, locals_, formatvalue=var_repr
893 893 )
894 894 call = tpl_call.format(file=func, scope=scope)
895 895 except KeyError:
896 896 # This happens in situations like errors inside generator
897 897 # expressions, where local variables are listed in the
898 898 # line, but can't be extracted from the frame. I'm not
899 899 # 100% sure this isn't actually a bug in inspect itself,
900 900 # but since there's no info for us to compute with, the
901 901 # best we can do is report the failure and move on. Here
902 902 # we must *not* call any traceback construction again,
903 903 # because that would mess up use of %debug later on. So we
904 904 # simply report the failure and move on. The only
905 905 # limitation will be that this frame won't have locals
906 906 # listed in the call signature. Quite subtle problem...
907 907 # I can't think of a good way to validate this in a unit
908 908 # test, but running a script consisting of:
909 909 # dict( (k,v.strip()) for (k,v) in range(10) )
910 910 # will illustrate the error, if this exception catch is
911 911 # disabled.
912 912 call = tpl_call_fail % func
913 913
914 914 lvals = ''
915 915 lvals_list = []
916 916 if self.include_vars:
917 917 try:
918 918 # we likely want to fix stackdata at some point, but
919 919 # still need a workaround.
920 920 fibp = frame_info.variables_in_executing_piece
921 921 for var in fibp:
922 922 lvals_list.append(tpl_name_val % (var.name, repr(var.value)))
923 923 except Exception:
924 924 lvals_list.append(
925 925 "Exception trying to inspect frame. No more locals available."
926 926 )
927 927 if lvals_list:
928 928 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
929 929
930 930 result = f'{link}{", " if call else ""}{call}\n'
931 931 if frame_info._sd is None:
932 932 # fast fallback if file is too long
933 933 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
934 934 link = tpl_link % util_path.compress_user(frame_info.filename)
935 935 level = "%s %s\n" % (link, call)
936 936 _line_format = PyColorize.Parser(
937 937 style=self.color_scheme_table.active_scheme_name, parent=self
938 938 ).format2
939 939 first_line = frame_info.code.co_firstlineno
940 940 current_line = frame_info.lineno[0]
941 941 raw_lines = frame_info.raw_lines
942 942 index = current_line - first_line
943 943
944 944 if index >= frame_info.context:
945 945 start = max(index - frame_info.context, 0)
946 946 stop = index + frame_info.context
947 947 index = frame_info.context
948 948 else:
949 949 start = 0
950 950 stop = index + frame_info.context
951 951 raw_lines = raw_lines[start:stop]
952 952
953 953 return "%s%s" % (
954 954 level,
955 955 "".join(
956 956 _simple_format_traceback_lines(
957 957 current_line,
958 958 index,
959 959 raw_lines,
960 960 Colors,
961 961 lvals,
962 962 _line_format,
963 963 )
964 964 ),
965 965 )
966 966 # result += "\n".join(frame_info.raw_lines)
967 967 else:
968 968 result += "".join(
969 969 _format_traceback_lines(
970 970 frame_info.lines, Colors, self.has_colors, lvals
971 971 )
972 972 )
973 973 return result
974 974
975 975 def prepare_header(self, etype: str, long_version: bool = False):
976 976 colors = self.Colors # just a shorthand + quicker name lookup
977 977 colorsnormal = colors.Normal # used a lot
978 978 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
979 979 width = min(75, get_terminal_size()[0])
980 980 if long_version:
981 981 # Header with the exception type, python version, and date
982 982 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
983 983 date = time.ctime(time.time())
984 984
985 985 head = "%s%s%s\n%s%s%s\n%s" % (
986 986 colors.topline,
987 987 "-" * width,
988 988 colorsnormal,
989 989 exc,
990 990 " " * (width - len(etype) - len(pyver)),
991 991 pyver,
992 992 date.rjust(width),
993 993 )
994 994 head += (
995 995 "\nA problem occurred executing Python code. Here is the sequence of function"
996 996 "\ncalls leading up to the error, with the most recent (innermost) call last."
997 997 )
998 998 else:
999 999 # Simplified header
1000 1000 head = "%s%s" % (
1001 1001 exc,
1002 1002 "Traceback (most recent call last)".rjust(width - len(etype)),
1003 1003 )
1004 1004
1005 1005 return head
1006 1006
1007 1007 def format_exception(self, etype, evalue):
1008 1008 colors = self.Colors # just a shorthand + quicker name lookup
1009 1009 colorsnormal = colors.Normal # used a lot
1010 1010 # Get (safely) a string form of the exception info
1011 1011 try:
1012 1012 etype_str, evalue_str = map(str, (etype, evalue))
1013 1013 except:
1014 1014 # User exception is improperly defined.
1015 1015 etype, evalue = str, sys.exc_info()[:2]
1016 1016 etype_str, evalue_str = map(str, (etype, evalue))
1017 1017
1018 1018 # PEP-678 notes
1019 1019 notes = getattr(evalue, "__notes__", [])
1020 1020 if not isinstance(notes, Sequence) or isinstance(notes, (str, bytes)):
1021 1021 notes = [_safe_string(notes, "__notes__", func=repr)]
1022 1022
1023 1023 # ... and format it
1024 1024 return [
1025 1025 "{}{}{}: {}".format(
1026 1026 colors.excName,
1027 1027 etype_str,
1028 1028 colorsnormal,
1029 1029 py3compat.cast_unicode(evalue_str),
1030 1030 ),
1031 1031 *(
1032 1032 "{}{}".format(
1033 1033 colorsnormal, _safe_string(py3compat.cast_unicode(n), "note")
1034 1034 )
1035 1035 for n in notes
1036 1036 ),
1037 1037 ]
1038 1038
1039 1039 def format_exception_as_a_whole(
1040 1040 self,
1041 1041 etype: type,
1042 1042 evalue: Optional[BaseException],
1043 1043 etb: Optional[TracebackType],
1044 1044 number_of_lines_of_context,
1045 1045 tb_offset: Optional[int],
1046 1046 ):
1047 1047 """Formats the header, traceback and exception message for a single exception.
1048 1048
1049 1049 This may be called multiple times by Python 3 exception chaining
1050 1050 (PEP 3134).
1051 1051 """
1052 1052 # some locals
1053 1053 orig_etype = etype
1054 1054 try:
1055 1055 etype = etype.__name__ # type: ignore
1056 1056 except AttributeError:
1057 1057 pass
1058 1058
1059 1059 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1060 1060 assert isinstance(tb_offset, int)
1061 1061 head = self.prepare_header(str(etype), self.long_header)
1062 1062 records = (
1063 1063 self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []
1064 1064 )
1065 1065
1066 1066 frames = []
1067 1067 skipped = 0
1068 1068 lastrecord = len(records) - 1
1069 1069 for i, record in enumerate(records):
1070 1070 if (
1071 1071 not isinstance(record._sd, stack_data.RepeatedFrames)
1072 1072 and self.skip_hidden
1073 1073 ):
1074 1074 if (
1075 1075 record.frame.f_locals.get("__tracebackhide__", 0)
1076 1076 and i != lastrecord
1077 1077 ):
1078 1078 skipped += 1
1079 1079 continue
1080 1080 if skipped:
1081 1081 Colors = self.Colors # just a shorthand + quicker name lookup
1082 1082 ColorsNormal = Colors.Normal # used a lot
1083 1083 frames.append(
1084 1084 " %s[... skipping hidden %s frame]%s\n"
1085 1085 % (Colors.excName, skipped, ColorsNormal)
1086 1086 )
1087 1087 skipped = 0
1088 1088 frames.append(self.format_record(record))
1089 1089 if skipped:
1090 1090 Colors = self.Colors # just a shorthand + quicker name lookup
1091 1091 ColorsNormal = Colors.Normal # used a lot
1092 1092 frames.append(
1093 1093 " %s[... skipping hidden %s frame]%s\n"
1094 1094 % (Colors.excName, skipped, ColorsNormal)
1095 1095 )
1096 1096
1097 1097 formatted_exception = self.format_exception(etype, evalue)
1098 1098 if records:
1099 1099 frame_info = records[-1]
1100 1100 ipinst = get_ipython()
1101 1101 if ipinst is not None:
1102 1102 ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0)
1103 1103
1104 1104 return [[head] + frames + formatted_exception]
1105 1105
1106 1106 def get_records(
1107 1107 self, etb: TracebackType, number_of_lines_of_context: int, tb_offset: int
1108 1108 ):
1109 1109 assert etb is not None
1110 1110 context = number_of_lines_of_context - 1
1111 1111 after = context // 2
1112 1112 before = context - after
1113 1113 if self.has_colors:
1114 1114 style = get_style_by_name(self._tb_highlight_style)
1115 1115 style = stack_data.style_with_executing_node(style, self._tb_highlight)
1116 1116 formatter = Terminal256Formatter(style=style)
1117 1117 else:
1118 1118 formatter = None
1119 1119 options = stack_data.Options(
1120 1120 before=before,
1121 1121 after=after,
1122 1122 pygments_formatter=formatter,
1123 1123 )
1124 1124
1125 1125 # Let's estimate the amount of code we will have to parse/highlight.
1126 1126 cf: Optional[TracebackType] = etb
1127 1127 max_len = 0
1128 1128 tbs = []
1129 1129 while cf is not None:
1130 1130 try:
1131 1131 mod = inspect.getmodule(cf.tb_frame)
1132 1132 if mod is not None:
1133 1133 mod_name = mod.__name__
1134 1134 root_name, *_ = mod_name.split(".")
1135 1135 if root_name == "IPython":
1136 1136 cf = cf.tb_next
1137 1137 continue
1138 1138 max_len = get_line_number_of_frame(cf.tb_frame)
1139 1139
1140 1140 except OSError:
1141 1141 max_len = 0
1142 1142 max_len = max(max_len, max_len)
1143 1143 tbs.append(cf)
1144 1144 cf = getattr(cf, "tb_next", None)
1145 1145
1146 1146 if max_len > FAST_THRESHOLD:
1147 1147 FIs = []
1148 1148 for tb in tbs:
1149 1149 frame = tb.tb_frame # type: ignore
1150 1150 lineno = (frame.f_lineno,)
1151 1151 code = frame.f_code
1152 1152 filename = code.co_filename
1153 1153 # TODO: Here we need to use before/after/
1154 1154 FIs.append(
1155 1155 FrameInfo(
1156 1156 "Raw frame", filename, lineno, frame, code, context=context
1157 1157 )
1158 1158 )
1159 1159 return FIs
1160 1160 res = list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
1161 1161 res = [FrameInfo._from_stack_data_FrameInfo(r) for r in res]
1162 1162 return res
1163 1163
1164 1164 def structured_traceback(
1165 1165 self,
1166 1166 etype: type,
1167 1167 evalue: Optional[BaseException],
1168 1168 etb: Optional[TracebackType] = None,
1169 1169 tb_offset: Optional[int] = None,
1170 1170 number_of_lines_of_context: int = 5,
1171 1171 ):
1172 1172 """Return a nice text document describing the traceback."""
1173 1173 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1174 1174 tb_offset)
1175 1175
1176 1176 colors = self.Colors # just a shorthand + quicker name lookup
1177 1177 colorsnormal = colors.Normal # used a lot
1178 1178 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1179 1179 structured_traceback_parts = [head]
1180 1180 chained_exceptions_tb_offset = 0
1181 1181 lines_of_context = 3
1182 1182 formatted_exceptions = formatted_exception
1183 1183 exception = self.get_parts_of_chained_exception(evalue)
1184 1184 if exception:
1185 1185 assert evalue is not None
1186 1186 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1187 1187 etype, evalue, etb = exception
1188 1188 else:
1189 1189 evalue = None
1190 1190 chained_exc_ids = set()
1191 1191 while evalue:
1192 1192 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1193 1193 chained_exceptions_tb_offset)
1194 1194 exception = self.get_parts_of_chained_exception(evalue)
1195 1195
1196 1196 if exception and not id(exception[1]) in chained_exc_ids:
1197 1197 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1198 1198 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1199 1199 etype, evalue, etb = exception
1200 1200 else:
1201 1201 evalue = None
1202 1202
1203 1203 # we want to see exceptions in a reversed order:
1204 1204 # the first exception should be on top
1205 1205 for formatted_exception in reversed(formatted_exceptions):
1206 1206 structured_traceback_parts += formatted_exception
1207 1207
1208 1208 return structured_traceback_parts
1209 1209
1210 1210 def debugger(self, force: bool = False):
1211 1211 """Call up the pdb debugger if desired, always clean up the tb
1212 1212 reference.
1213 1213
1214 1214 Keywords:
1215 1215
1216 1216 - force(False): by default, this routine checks the instance call_pdb
1217 1217 flag and does not actually invoke the debugger if the flag is false.
1218 1218 The 'force' option forces the debugger to activate even if the flag
1219 1219 is false.
1220 1220
1221 1221 If the call_pdb flag is set, the pdb interactive debugger is
1222 1222 invoked. In all cases, the self.tb reference to the current traceback
1223 1223 is deleted to prevent lingering references which hamper memory
1224 1224 management.
1225 1225
1226 1226 Note that each call to pdb() does an 'import readline', so if your app
1227 1227 requires a special setup for the readline completers, you'll have to
1228 1228 fix that by hand after invoking the exception handler."""
1229 1229
1230 1230 if force or self.call_pdb:
1231 1231 if self.pdb is None:
1232 1232 self.pdb = self.debugger_cls()
1233 1233 # the system displayhook may have changed, restore the original
1234 1234 # for pdb
1235 1235 display_trap = DisplayTrap(hook=sys.__displayhook__)
1236 1236 with display_trap:
1237 1237 self.pdb.reset()
1238 1238 # Find the right frame so we don't pop up inside ipython itself
1239 1239 if hasattr(self, "tb") and self.tb is not None: # type: ignore[has-type]
1240 1240 etb = self.tb # type: ignore[has-type]
1241 1241 else:
1242 1242 etb = self.tb = sys.last_traceback
1243 1243 while self.tb is not None and self.tb.tb_next is not None:
1244 1244 assert self.tb.tb_next is not None
1245 1245 self.tb = self.tb.tb_next
1246 1246 if etb and etb.tb_next:
1247 1247 etb = etb.tb_next
1248 1248 self.pdb.botframe = etb.tb_frame
1249 self.pdb.interaction(None, etb)
1249 # last_value should be deprecated, but last-exc sometimme not set
1250 # please check why later and remove the getattr.
1251 exc = sys.last_value if sys.version_info < (3, 12) else getattr(sys, "last_exc", sys.last_value) # type: ignore[attr-defined]
1252 if exc:
1253 self.pdb.interaction(None, exc)
1254 else:
1255 self.pdb.interaction(None, etb)
1250 1256
1251 1257 if hasattr(self, 'tb'):
1252 1258 del self.tb
1253 1259
1254 1260 def handler(self, info=None):
1255 1261 (etype, evalue, etb) = info or sys.exc_info()
1256 1262 self.tb = etb
1257 1263 ostream = self.ostream
1258 1264 ostream.flush()
1259 1265 ostream.write(self.text(etype, evalue, etb))
1260 1266 ostream.write('\n')
1261 1267 ostream.flush()
1262 1268
1263 1269 # Changed so an instance can just be called as VerboseTB_inst() and print
1264 1270 # out the right info on its own.
1265 1271 def __call__(self, etype=None, evalue=None, etb=None):
1266 1272 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1267 1273 if etb is None:
1268 1274 self.handler()
1269 1275 else:
1270 1276 self.handler((etype, evalue, etb))
1271 1277 try:
1272 1278 self.debugger()
1273 1279 except KeyboardInterrupt:
1274 1280 print("\nKeyboardInterrupt")
1275 1281
1276 1282
1277 1283 #----------------------------------------------------------------------------
1278 1284 class FormattedTB(VerboseTB, ListTB):
1279 1285 """Subclass ListTB but allow calling with a traceback.
1280 1286
1281 1287 It can thus be used as a sys.excepthook for Python > 2.1.
1282 1288
1283 1289 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1284 1290
1285 1291 Allows a tb_offset to be specified. This is useful for situations where
1286 1292 one needs to remove a number of topmost frames from the traceback (such as
1287 1293 occurs with python programs that themselves execute other python code,
1288 1294 like Python shells). """
1289 1295
1290 1296 mode: str
1291 1297
1292 1298 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1293 1299 ostream=None,
1294 1300 tb_offset=0, long_header=False, include_vars=False,
1295 1301 check_cache=None, debugger_cls=None,
1296 1302 parent=None, config=None):
1297 1303
1298 1304 # NEVER change the order of this list. Put new modes at the end:
1299 1305 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
1300 1306 self.verbose_modes = self.valid_modes[1:3]
1301 1307
1302 1308 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1303 1309 ostream=ostream, tb_offset=tb_offset,
1304 1310 long_header=long_header, include_vars=include_vars,
1305 1311 check_cache=check_cache, debugger_cls=debugger_cls,
1306 1312 parent=parent, config=config)
1307 1313
1308 1314 # Different types of tracebacks are joined with different separators to
1309 1315 # form a single string. They are taken from this dict
1310 1316 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
1311 1317 Minimal='')
1312 1318 # set_mode also sets the tb_join_char attribute
1313 1319 self.set_mode(mode)
1314 1320
1315 1321 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1316 1322 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1317 1323 mode = self.mode
1318 1324 if mode in self.verbose_modes:
1319 1325 # Verbose modes need a full traceback
1320 1326 return VerboseTB.structured_traceback(
1321 1327 self, etype, value, tb, tb_offset, number_of_lines_of_context
1322 1328 )
1323 1329 elif mode == 'Minimal':
1324 1330 return ListTB.get_exception_only(self, etype, value)
1325 1331 else:
1326 1332 # We must check the source cache because otherwise we can print
1327 1333 # out-of-date source code.
1328 1334 self.check_cache()
1329 1335 # Now we can extract and format the exception
1330 1336 return ListTB.structured_traceback(
1331 1337 self, etype, value, tb, tb_offset, number_of_lines_of_context
1332 1338 )
1333 1339
1334 1340 def stb2text(self, stb):
1335 1341 """Convert a structured traceback (a list) to a string."""
1336 1342 return self.tb_join_char.join(stb)
1337 1343
1338 1344 def set_mode(self, mode: Optional[str] = None):
1339 1345 """Switch to the desired mode.
1340 1346
1341 1347 If mode is not specified, cycles through the available modes."""
1342 1348
1343 1349 if not mode:
1344 1350 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1345 1351 len(self.valid_modes)
1346 1352 self.mode = self.valid_modes[new_idx]
1347 1353 elif mode not in self.valid_modes:
1348 1354 raise ValueError(
1349 1355 "Unrecognized mode in FormattedTB: <" + mode + ">\n"
1350 1356 "Valid modes: " + str(self.valid_modes)
1351 1357 )
1352 1358 else:
1353 1359 assert isinstance(mode, str)
1354 1360 self.mode = mode
1355 1361 # include variable details only in 'Verbose' mode
1356 1362 self.include_vars = (self.mode == self.valid_modes[2])
1357 1363 # Set the join character for generating text tracebacks
1358 1364 self.tb_join_char = self._join_chars[self.mode]
1359 1365
1360 1366 # some convenient shortcuts
1361 1367 def plain(self):
1362 1368 self.set_mode(self.valid_modes[0])
1363 1369
1364 1370 def context(self):
1365 1371 self.set_mode(self.valid_modes[1])
1366 1372
1367 1373 def verbose(self):
1368 1374 self.set_mode(self.valid_modes[2])
1369 1375
1370 1376 def minimal(self):
1371 1377 self.set_mode(self.valid_modes[3])
1372 1378
1373 1379
1374 1380 #----------------------------------------------------------------------------
1375 1381 class AutoFormattedTB(FormattedTB):
1376 1382 """A traceback printer which can be called on the fly.
1377 1383
1378 1384 It will find out about exceptions by itself.
1379 1385
1380 1386 A brief example::
1381 1387
1382 1388 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1383 1389 try:
1384 1390 ...
1385 1391 except:
1386 1392 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1387 1393 """
1388 1394
1389 1395 def __call__(self, etype=None, evalue=None, etb=None,
1390 1396 out=None, tb_offset=None):
1391 1397 """Print out a formatted exception traceback.
1392 1398
1393 1399 Optional arguments:
1394 1400 - out: an open file-like object to direct output to.
1395 1401
1396 1402 - tb_offset: the number of frames to skip over in the stack, on a
1397 1403 per-call basis (this overrides temporarily the instance's tb_offset
1398 1404 given at initialization time."""
1399 1405
1400 1406 if out is None:
1401 1407 out = self.ostream
1402 1408 out.flush()
1403 1409 out.write(self.text(etype, evalue, etb, tb_offset))
1404 1410 out.write('\n')
1405 1411 out.flush()
1406 1412 # FIXME: we should remove the auto pdb behavior from here and leave
1407 1413 # that to the clients.
1408 1414 try:
1409 1415 self.debugger()
1410 1416 except KeyboardInterrupt:
1411 1417 print("\nKeyboardInterrupt")
1412 1418
1413 1419 def structured_traceback(
1414 1420 self,
1415 1421 etype: type,
1416 1422 evalue: Optional[BaseException],
1417 1423 etb: Optional[TracebackType] = None,
1418 1424 tb_offset: Optional[int] = None,
1419 1425 number_of_lines_of_context: int = 5,
1420 1426 ):
1421 1427 # tb: TracebackType or tupleof tb types ?
1422 1428 if etype is None:
1423 1429 etype, evalue, etb = sys.exc_info()
1424 1430 if isinstance(etb, tuple):
1425 1431 # tb is a tuple if this is a chained exception.
1426 1432 self.tb = etb[0]
1427 1433 else:
1428 1434 self.tb = etb
1429 1435 return FormattedTB.structured_traceback(
1430 1436 self, etype, evalue, etb, tb_offset, number_of_lines_of_context
1431 1437 )
1432 1438
1433 1439
1434 1440 #---------------------------------------------------------------------------
1435 1441
1436 1442 # A simple class to preserve Nathan's original functionality.
1437 1443 class ColorTB(FormattedTB):
1438 1444 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1439 1445
1440 1446 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1441 1447 FormattedTB.__init__(self, color_scheme=color_scheme,
1442 1448 call_pdb=call_pdb, **kwargs)
1443 1449
1444 1450
1445 1451 class SyntaxTB(ListTB):
1446 1452 """Extension which holds some state: the last exception value"""
1447 1453
1448 1454 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1449 1455 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1450 1456 self.last_syntax_error = None
1451 1457
1452 1458 def __call__(self, etype, value, elist):
1453 1459 self.last_syntax_error = value
1454 1460
1455 1461 ListTB.__call__(self, etype, value, elist)
1456 1462
1457 1463 def structured_traceback(self, etype, value, elist, tb_offset=None,
1458 1464 context=5):
1459 1465 # If the source file has been edited, the line in the syntax error can
1460 1466 # be wrong (retrieved from an outdated cache). This replaces it with
1461 1467 # the current value.
1462 1468 if isinstance(value, SyntaxError) \
1463 1469 and isinstance(value.filename, str) \
1464 1470 and isinstance(value.lineno, int):
1465 1471 linecache.checkcache(value.filename)
1466 1472 newtext = linecache.getline(value.filename, value.lineno)
1467 1473 if newtext:
1468 1474 value.text = newtext
1469 1475 self.last_syntax_error = value
1470 1476 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1471 1477 tb_offset=tb_offset, context=context)
1472 1478
1473 1479 def clear_err_state(self):
1474 1480 """Return the current error state and clear it"""
1475 1481 e = self.last_syntax_error
1476 1482 self.last_syntax_error = None
1477 1483 return e
1478 1484
1479 1485 def stb2text(self, stb):
1480 1486 """Convert a structured traceback (a list) to a string."""
1481 1487 return ''.join(stb)
1482 1488
1483 1489
1484 1490 # some internal-use functions
1485 1491 def text_repr(value):
1486 1492 """Hopefully pretty robust repr equivalent."""
1487 1493 # this is pretty horrible but should always return *something*
1488 1494 try:
1489 1495 return pydoc.text.repr(value) # type: ignore[call-arg]
1490 1496 except KeyboardInterrupt:
1491 1497 raise
1492 1498 except:
1493 1499 try:
1494 1500 return repr(value)
1495 1501 except KeyboardInterrupt:
1496 1502 raise
1497 1503 except:
1498 1504 try:
1499 1505 # all still in an except block so we catch
1500 1506 # getattr raising
1501 1507 name = getattr(value, '__name__', None)
1502 1508 if name:
1503 1509 # ick, recursion
1504 1510 return text_repr(name)
1505 1511 klass = getattr(value, '__class__', None)
1506 1512 if klass:
1507 1513 return '%s instance' % text_repr(klass)
1508 1514 except KeyboardInterrupt:
1509 1515 raise
1510 1516 except:
1511 1517 return 'UNRECOVERABLE REPR FAILURE'
1512 1518
1513 1519
1514 1520 def eqrepr(value, repr=text_repr):
1515 1521 return '=%s' % repr(value)
1516 1522
1517 1523
1518 1524 def nullrepr(value, repr=text_repr):
1519 1525 return ''
@@ -1,80 +1,82 b''
1 1 """Test embedding of IPython"""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2013 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 import os
15 15 import sys
16 16 from IPython.testing.decorators import skip_win32
17 17 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Tests
21 21 #-----------------------------------------------------------------------------
22 22
23 23 @skip_win32
24 24 def test_debug_magic_passes_through_generators():
25 25 """
26 26 This test that we can correctly pass through frames of a generator post-mortem.
27 27 """
28 28 import pexpect
29 29 import re
30 30 in_prompt = re.compile(br'In ?\[\d+\]:')
31 31 ipdb_prompt = 'ipdb>'
32 32 env = os.environ.copy()
33 33 child = pexpect.spawn(sys.executable, ['-m', 'IPython', '--colors=nocolor', '--simple-prompt'],
34 34 env=env)
35 35 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
36 36
37 37 child.expect(in_prompt)
38 38
39 39 child.timeout = 2 * IPYTHON_TESTING_TIMEOUT_SCALE
40 40
41 41 child.sendline("def f(x):")
42 42 child.sendline(" raise Exception")
43 43 child.sendline("")
44 44
45 45 child.expect(in_prompt)
46 46 child.sendline("gen = (f(x) for x in [0])")
47 47 child.sendline("")
48 48
49 49 child.expect(in_prompt)
50 50 child.sendline("for x in gen:")
51 51 child.sendline(" pass")
52 52 child.sendline("")
53 53
54 54 child.timeout = 10 * IPYTHON_TESTING_TIMEOUT_SCALE
55 55
56 56 child.expect('Exception:')
57 57
58 58 child.expect(in_prompt)
59 59 child.sendline(r'%debug')
60 60 child.expect('----> 2 raise Exception')
61 61
62 62 child.expect(ipdb_prompt)
63 63 child.sendline('u')
64 64 child.expect_exact(r'----> 1 gen = (f(x) for x in [0])')
65 65
66 66 child.expect(ipdb_prompt)
67 67 child.sendline('u')
68 68 child.expect_exact('----> 1 for x in gen:')
69 69
70 70 child.expect(ipdb_prompt)
71 child.sendline('u')
72 child.expect_exact('*** Oldest frame')
71 child.sendline("u")
72 child.expect_exact(
73 "*** all frames above hidden, use `skip_hidden False` to get get into those."
74 )
73 75
74 76 child.expect(ipdb_prompt)
75 77 child.sendline('exit')
76 78
77 79 child.expect(in_prompt)
78 80 child.sendline('exit')
79 81
80 82 child.close()
@@ -1,1746 +1,1763 b''
1 1 ============
2 2 8.x Series
3 3 ============
4
5 .. _version 8.15:
6
7 IPython 8.15
8 ------------
9
10 Medium release of IPython after a couple of month hiatus, and a bit off-schedule.
11
12 The main change is the addition of the ability to move between chained
13 exceptions when using IPdb, this feature was also contributed to upstream Pdb
14 and is thus native to CPython in Python 3.13+ Though ipdb should support this
15 feature in older version of Python. I invite you to look at the `CPython changes
16 and docs <https://github.com/python/cpython/pull/106676>`_ for more details.
17
18 I also want o thanks the `D.E. Shaw group <https://www.deshaw.com/>`_ for
19 suggesting and funding this feature.
20
4 21 .. _version 8.14:
5 22
6 23 IPython 8.14
7 24 ------------
8 25
9 26 Small release of IPython.
10 27
11 28 - :ghpull:`14080` fixes some shortcuts issues.
12 29 - :ghpull:`14056` Add option to ``%autoreload`` to hide errors when reloading code. This will be the default for spyder
13 30 user is my understanding.
14 31 - :ghpull:`14039` (and :ghpull:`14040`) to show exception notes in tracebacks.
15 32
16 33 - :ghpull:`14076` Add option to EventManager to prevent printing
17 34
18 35
19 36 SPEC 0 and SPEC 4
20 37 ~~~~~~~~~~~~~~~~~
21 38
22 39 You've heard about the NEPs, (NumPy enhancement Proposal), having a NEP for something non-numpy specific was sometime confusing.
23 40 Long live the `SPECs <https://scientific-python.org/specs/>`_.
24 41
25 42 We are now trying to follow SPEC 0 (aka old NEP 29) for of support of upstream libraries.
26 43
27 44 We also now try to follow SPEC 4 (test and publish nightly on a centralized nightly repository).
28 45 We encourage you to do so as well in order to report breakage, and contribute to the SPEC process !
29 46
30 47
31 48 Python 3.12 compatibility ?
32 49 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 50
34 51 Python 3.12 changed its tokenizer to have better support for f-strings and allow arbitrary expression.
35 52 This is a great new feature and performance improvement in python 3.12.
36 53
37 54 Unfortunately this means the new tokenizer does not support incomplete or invalid Python which will
38 55 break many features of IPython. Thus compatibility of IPython with Python 3.12 is not guarantied.
39 56 It is unclear to which extent IPython is affected, and whether we can/should try to still support magics, shell
40 57 escape (``! ....``), ..., as well as how to do it if we can.
41 58
42 59 In addition even if we there is technical feasibility to do so, it is no clear we have the resources to do it.
43 60 We are thus looking for your help if you can _test_ on Python 3.12 to see to which extent this affects users and which
44 61 features are critical.
45 62
46 63 We are not going to pin IPython to Python ``<3.12`` as otherwise on install pip would downgrade/resolve to IPython 8.13,
47 64 so if you plan to update to Python 3.12 after its release, we encourage for extra care.
48 65
49 66
50 67 .. _version 8.13.1:
51 68 .. _version 8.13.2:
52 69 .. _version 8.12.3:
53 70
54 71 IPython 8.13.1, 8.13.2 and 8.12.2
55 72 ---------------------------------
56 73
57 74 3 quick in succession patch release of IPython in addition to IPython 8.13.0
58 75 having been yanked.
59 76
60 77 IPython 8.13.0 was improperly tagged as still compatible with Python 3.8, and
61 78 still had some mention of compatibility with 3.8. IPython 8.13.1 is identical to
62 79 8.13 but with the exception of being correctly tagged. This release and yank was
63 80 mostly done to fix CI.
64 81
65 82 IPython 8.12.2 and 8.13.2 contain UI fixes, with respect to right arrow not
66 83 working in some case in the terminal, and 8.12.2 contain also a requested
67 84 backport of :ghpull:`14029` (Allow safe access to the ``__getattribute__``
68 85 method of modules) for tab completion.
69 86
70 87 .. _version 8.13:
71 88
72 89 IPython 8.13
73 90 ------------
74 91
75 92 As usual for the end of the month, minor release of IPython. This release is
76 93 significant in that it not only has a number of bugfixes, but also drop support
77 94 for Python 3.8 as per NEP 29 (:ghpull:`14023`).
78 95
79 96 All the critical bugfixes have been backported onto the 8.12.1 release (see
80 97 below). In addition to that went into 8.12.1 you'll find:
81 98
82 99 - Pretty reprensentation for ``Counter`` has been fixed to match the Python one
83 100 and be in decreasing order. :ghpull:`14032`
84 101 - Module completion is better when jedi is disabled :ghpull:`14029`.
85 102 - Improvment of ``%%bash`` magic that would get stuck :ghpull:`14019`
86 103
87 104
88 105 We hope you enjoy this release an will maybe see you at JupyterCon in less than
89 106 two weeks.
90 107
91 108 As usual you can find the full list of PRs on GitHub under `the 8.13 milestone
92 109 <https://github.com/ipython/ipython/milestone/115?closed=1>`__.
93 110
94 111 Thanks to the D.E. Shaw group for the request and sponsoring the work.
95 112
96 113
97 114 .. _version 8.12.1:
98 115
99 116 IPython 8.12.1
100 117 --------------
101 118
102 119 This is the twin release of IPython 8.13 that contain only critical UI and bug
103 120 fixes. The next minor version of IPython has dropped support for Python 3.8 – as
104 121 per Nep 29 and this IPython 8.12.x will now only receive bugfixes.
105 122
106 123
107 124 - :ghpull:`14004` Fix a bug introduced in IPython 8.12 that crash when
108 125 inspecting some docstrings.
109 126 - :ghpull:`14010` Fix fast traceback code that was not working in some case.
110 127 - :ghpull:`14014` Fix ``%page`` magic broken in some case.
111 128 - :ghpull:`14026`, :ghpull:`14027` Tweak default shortcut with respect to
112 129 autosuggestions.
113 130 - :ghpull:`14033` add back the ability to use ``.get()`` on OInfo object for
114 131 backward compatibility with h5py (this will be re-deprecated later, and h5py
115 132 will also get a fix).
116 133
117 134 As usual you can find the full list of PRs on GitHub under `the 8.12.1 milestone
118 135 <https://github.com/ipython/ipython/milestone/116?closed=1>`__.
119 136
120 137 Thanks to the D.E. Shaw group for the request and sponsoring the work.
121 138
122 139 .. _version 8.12.0:
123 140
124 141 IPython 8.12
125 142 ------------
126 143
127 144 Hopefully slightly early release for IPython 8.12. Last Thursday of the month,
128 145 even if I guess it's likely already Friday somewhere in the pacific ocean.
129 146
130 147 A number of PRs and bug fixes this month with close to 20 PRs merged !
131 148
132 149
133 150 The IPython repo reached :ghpull:`14000` !! Actually the PR that create those exact release
134 151 note is :ghpull:`14000`. Ok, more issues and PR is not always better, and I'd
135 152 love to have more time to close issues and Pull Requests.
136 153
137 154 Let's note that in less than 2 month JupyterCon is back, in Paris please visit
138 155 `jupytercon.com <https://jupytercon.com>`__, and looking forward to see you
139 156 there.
140 157
141 158 Packagers should take note that ``typing_extension`` is now a mandatory dependency
142 159 for Python versions ``<3.10``.
143 160
144 161
145 162
146 163 Let's note also that according to `NEP29
147 164 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`__, It is soon time to
148 165 stop support for Python 3.8 that will be release more than 3 and 1/2 years ago::
149 166
150 167 On Apr 14, 2023 drop support for Python 3.8 (initially released on Oct 14, 2019)
151 168
152 169 Thus I am likely to stop advertising support for Python 3.8 in the next
153 170 release at the end of April.
154 171
155 172
156 173 Here are some miscellaneous updates of interest:
157 174
158 175 - :ghpull:`13957` brings updates to the Qt integration, particularly for Qt6.
159 176 - :ghpull:`13960` fixes the %debug magic command to give access to the local
160 177 scope.
161 178 - :ghpull:`13964` fixes some crashes with the new fast traceback code. Note that
162 179 there are still some issues with the fast traceback code, and I a, likely
163 180 to fix and tweak behavior.
164 181 - :ghpull:`13973` We are slowly migrating IPython internals to use proper type
165 182 objects/dataclasses instead of dictionaries to allow static typing checks.
166 183 These are technically public API and could lead to breakage, so please let us
167 184 know if that's the case and I'll mitigate.
168 185 - :ghpull:`13990`, :ghpull:`13991`, :ghpull:`13994` all improve keybinding and
169 186 shortcut configurability.
170 187
171 188 As usual you can find the full list of PRs on GitHub under `the 8.12 milestone
172 189 <https://github.com/ipython/ipython/milestone/114?closed=1>`__.
173 190
174 191 We want to thank the D.E. Shaw group for requesting and sponsoring the work on
175 192 the following big feature. We had productive discussions on how to best expose
176 193 this feature
177 194
178 195 Dynamic documentation dispatch
179 196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180 197
181 198 We are experimenting with dynamic documentation dispatch for object attribute.
182 199 See :ghissue:`13860`. The goal is to allow object to define documentation for
183 200 their attributes, properties, even when those are dynamically defined with
184 201 `__getattr__`.
185 202
186 203 In particular when those objects are base types it can be useful to show the
187 204 documentation
188 205
189 206
190 207 .. code-block:: ipython
191 208
192 209
193 210 In [1]: class User:
194 211 ...:
195 212 ...: __custom_documentations__ = {
196 213 ...: "first": "The first name of the user.",
197 214 ...: "last": "The last name of the user.",
198 215 ...: }
199 216 ...:
200 217 ...: first:str
201 218 ...: last:str
202 219 ...:
203 220 ...: def __init__(self, first, last):
204 221 ...: self.first = first
205 222 ...: self.last = last
206 223 ...:
207 224 ...: @property
208 225 ...: def full(self):
209 226 ...: """`self.first` and `self.last` joined by a space."""
210 227 ...: return self.first + " " + self.last
211 228 ...:
212 229 ...:
213 230 ...: user = Person('Jane', 'Doe')
214 231
215 232 In [2]: user.first?
216 233 Type: str
217 234 String form: Jane
218 235 Length: 4
219 236 Docstring: the first name of a the person object, a str
220 237 Class docstring:
221 238 ....
222 239
223 240 In [3]: user.last?
224 241 Type: str
225 242 String form: Doe
226 243 Length: 3
227 244 Docstring: the last name, also a str
228 245 ...
229 246
230 247
231 248 We can see here the symmetry with IPython looking for the docstring on the
232 249 properties:
233 250
234 251 .. code-block:: ipython
235 252
236 253
237 254 In [4]: user.full?
238 255 HERE
239 256 Type: property
240 257 String form: <property object at 0x102bb15d0>
241 258 Docstring: first and last join by a space
242 259
243 260
244 261 Note that while in the above example we use a static dictionary, libraries may
245 262 decide to use a custom object that define ``__getitem__``, we caution against
246 263 using objects that would trigger computation to show documentation, but it is
247 264 sometime preferable for highly dynamic code that for example export ans API as
248 265 object.
249 266
250 267
251 268
252 269 .. _version 8.11.0:
253 270
254 271 IPython 8.11
255 272 ------------
256 273
257 274 Back on almost regular monthly schedule for IPython with end-of-month
258 275 really-late-Friday release to make sure some bugs are properly fixed.
259 276 Small addition of with a few new features, bugfix and UX improvements.
260 277
261 278 This is a non-exhaustive list, but among other you will find:
262 279
263 280 Faster Traceback Highlighting
264 281 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265 282
266 283 Resurrection of pre-IPython-8 traceback highlighting code.
267 284
268 285 Really long and complicated files were slow to highlight in traceback with
269 286 IPython 8 despite upstream improvement that make many case better. Therefore
270 287 starting with IPython 8.11 when one of the highlighted file is more than 10 000
271 288 line long by default, we'll fallback to a faster path that does not have all the
272 289 features of highlighting failing AST nodes.
273 290
274 291 This can be configures by setting the value of
275 292 ``IPython.code.ultratb.FAST_THRESHOLD`` to an arbitrary low or large value.
276 293
277 294
278 295 Autoreload verbosity
279 296 ~~~~~~~~~~~~~~~~~~~~
280 297
281 298 We introduce more descriptive names for the ``%autoreload`` parameter:
282 299
283 300 - ``%autoreload now`` (also ``%autoreload``) - perform autoreload immediately.
284 301 - ``%autoreload off`` (also ``%autoreload 0``) - turn off autoreload.
285 302 - ``%autoreload explicit`` (also ``%autoreload 1``) - turn on autoreload only for modules
286 303 whitelisted by ``%aimport`` statements.
287 304 - ``%autoreload all`` (also ``%autoreload 2``) - turn on autoreload for all modules except those
288 305 blacklisted by ``%aimport`` statements.
289 306 - ``%autoreload complete`` (also ``%autoreload 3``) - all the fatures of ``all`` but also adding new
290 307 objects from the imported modules (see
291 308 IPython/extensions/tests/test_autoreload.py::test_autoload_newly_added_objects).
292 309
293 310 The original designations (e.g. "2") still work, and these new ones are case-insensitive.
294 311
295 312 Additionally, the option ``--print`` or ``-p`` can be added to the line to print the names of
296 313 modules being reloaded. Similarly, ``--log`` or ``-l`` will output the names to the logger at INFO
297 314 level. Both can be used simultaneously.
298 315
299 316 The parsing logic for ``%aimport`` is now improved such that modules can be whitelisted and
300 317 blacklisted in the same line, e.g. it's now possible to call ``%aimport os, -math`` to include
301 318 ``os`` for ``%autoreload explicit`` and exclude ``math`` for modes ``all`` and ``complete``.
302 319
303 320 Terminal shortcuts customization
304 321 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
305 322
306 323 Previously modifying shortcuts was only possible by hooking into startup files
307 324 and practically limited to adding new shortcuts or removing all shortcuts bound
308 325 to a specific key. This release enables users to override existing terminal
309 326 shortcuts, disable them or add new keybindings.
310 327
311 328 For example, to set the :kbd:`right` to accept a single character of auto-suggestion
312 329 you could use::
313 330
314 331 my_shortcuts = [
315 332 {
316 333 "command": "IPython:auto_suggest.accept_character",
317 334 "new_keys": ["right"]
318 335 }
319 336 ]
320 337 %config TerminalInteractiveShell.shortcuts = my_shortcuts
321 338
322 339 You can learn more in :std:configtrait:`TerminalInteractiveShell.shortcuts`
323 340 configuration reference.
324 341
325 342 Miscellaneous
326 343 ~~~~~~~~~~~~~
327 344
328 345 - ``%gui`` should now support PySide6. :ghpull:`13864`
329 346 - Cli shortcuts can now be configured :ghpull:`13928`, see above.
330 347 (note that there might be an issue with prompt_toolkit 3.0.37 and shortcut configuration).
331 348
332 349 - Capture output should now respect ``;`` semicolon to suppress output.
333 350 :ghpull:`13940`
334 351 - Base64 encoded images (in jupyter frontend), will not have trailing newlines.
335 352 :ghpull:`13941`
336 353
337 354 As usual you can find the full list of PRs on GitHub under `the 8.11 milestone
338 355 <https://github.com/ipython/ipython/milestone/113?closed=1>`__.
339 356
340 357 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
341 358 work on IPython and related libraries.
342 359
343 360 .. _version 8.10.0:
344 361
345 362 IPython 8.10
346 363 ------------
347 364
348 365 Out of schedule release of IPython with minor fixes to patch a potential CVE-2023-24816.
349 366 This is a really low severity CVE that you most likely are not affected by unless:
350 367
351 368 - You are on windows.
352 369 - You have a custom build of Python without ``_ctypes``
353 370 - You cd or start IPython or Jupyter in untrusted directory which names may be
354 371 valid shell commands.
355 372
356 373 You can read more on `the advisory
357 374 <https://github.com/ipython/ipython/security/advisories/GHSA-29gw-9793-fvw7>`__.
358 375
359 376 In addition to fixing this CVE we also fix a couple of outstanding bugs and issues.
360 377
361 378 As usual you can find the full list of PRs on GitHub under `the 8.10 milestone
362 379 <https://github.com/ipython/ipython/milestone/112?closed=1>`__.
363 380
364 381 In Particular:
365 382
366 383 - bump minimum numpy to `>=1.21` version following NEP29. :ghpull:`13930`
367 384 - fix for compatibility with MyPy 1.0. :ghpull:`13933`
368 385 - fix nbgrader stalling when IPython's ``showtraceback`` function is
369 386 monkeypatched. :ghpull:`13934`
370 387
371 388
372 389
373 390 As this release also contains those minimal changes in addition to fixing the
374 391 CVE I decided to bump the minor version anyway.
375 392
376 393 This will not affect the normal release schedule, so IPython 8.11 is due in
377 394 about 2 weeks.
378 395
379 396 .. _version 8.9.0:
380 397
381 398 IPython 8.9.0
382 399 -------------
383 400
384 401 Second release of IPython in 2023, last Friday of the month, we are back on
385 402 track. This is a small release with a few bug-fixes, and improvements, mostly
386 403 with respect to terminal shortcuts.
387 404
388 405
389 406 The biggest improvement for 8.9 is a drastic amelioration of the
390 407 auto-suggestions sponsored by D.E. Shaw and implemented by the more and more
391 408 active contributor `@krassowski <https://github.com/krassowski>`.
392 409
393 410 - ``right`` accepts a single character from suggestion
394 411 - ``ctrl+right`` accepts a semantic token (macos default shortcuts take
395 412 precedence and need to be disabled to make this work)
396 413 - ``backspace`` deletes a character and resumes hinting autosuggestions
397 414 - ``ctrl-left`` accepts suggestion and moves cursor left one character.
398 415 - ``backspace`` deletes a character and resumes hinting autosuggestions
399 416 - ``down`` moves to suggestion to later in history when no lines are present below the cursors.
400 417 - ``up`` moves to suggestion from earlier in history when no lines are present above the cursor.
401 418
402 419 This is best described by the Gif posted by `@krassowski
403 420 <https://github.com/krassowski>`, and in the PR itself :ghpull:`13888`.
404 421
405 422 .. image:: ../_images/autosuggest.gif
406 423
407 424 Please report any feedback in order for us to improve the user experience.
408 425 In particular we are also working on making the shortcuts configurable.
409 426
410 427 If you are interested in better terminal shortcuts, I also invite you to
411 428 participate in issue `13879
412 429 <https://github.com/ipython/ipython/issues/13879>`__.
413 430
414 431
415 432 As we follow `NEP29
416 433 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`__, next version of
417 434 IPython will officially stop supporting numpy 1.20, and will stop supporting
418 435 Python 3.8 after April release.
419 436
420 437 As usual you can find the full list of PRs on GitHub under `the 8.9 milestone
421 438 <https://github.com/ipython/ipython/milestone/111?closed=1>`__.
422 439
423 440
424 441 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
425 442 work on IPython and related libraries.
426 443
427 444 .. _version 8.8.0:
428 445
429 446 IPython 8.8.0
430 447 -------------
431 448
432 449 First release of IPython in 2023 as there was no release at the end of
433 450 December.
434 451
435 452 This is an unusually big release (relatively speaking) with more than 15 Pull
436 453 Requests merged.
437 454
438 455 Of particular interest are:
439 456
440 457 - :ghpull:`13852` that replaces the greedy completer and improves
441 458 completion, in particular for dictionary keys.
442 459 - :ghpull:`13858` that adds ``py.typed`` to ``setup.cfg`` to make sure it is
443 460 bundled in wheels.
444 461 - :ghpull:`13869` that implements tab completions for IPython options in the
445 462 shell when using `argcomplete <https://github.com/kislyuk/argcomplete>`. I
446 463 believe this also needs a recent version of Traitlets.
447 464 - :ghpull:`13865` makes the ``inspector`` class of `InteractiveShell`
448 465 configurable.
449 466 - :ghpull:`13880` that removes minor-version entrypoints as the minor version
450 467 entry points that would be included in the wheel would be the one of the
451 468 Python version that was used to build the ``whl`` file.
452 469
453 470 In no particular order, the rest of the changes update the test suite to be
454 471 compatible with Pygments 2.14, various docfixes, testing on more recent python
455 472 versions and various updates.
456 473
457 474 As usual you can find the full list of PRs on GitHub under `the 8.8 milestone
458 475 <https://github.com/ipython/ipython/milestone/110>`__.
459 476
460 477 Many thanks to @krassowski for the many PRs and @jasongrout for reviewing and
461 478 merging contributions.
462 479
463 480 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
464 481 work on IPython and related libraries.
465 482
466 483 .. _version 8.7.0:
467 484
468 485 IPython 8.7.0
469 486 -------------
470 487
471 488
472 489 Small release of IPython with a couple of bug fixes and new features for this
473 490 month. Next month is the end of year, it is unclear if there will be a release
474 491 close to the new year's eve, or if the next release will be at the end of January.
475 492
476 493 Here are a few of the relevant fixes,
477 494 as usual you can find the full list of PRs on GitHub under `the 8.7 milestone
478 495 <https://github.com/ipython/ipython/pulls?q=milestone%3A8.7>`__.
479 496
480 497
481 498 - :ghpull:`13834` bump the minimum prompt toolkit to 3.0.11.
482 499 - IPython shipped with the ``py.typed`` marker now, and we are progressively
483 500 adding more types. :ghpull:`13831`
484 501 - :ghpull:`13817` add configuration of code blacks formatting.
485 502
486 503
487 504 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
488 505 work on IPython and related libraries.
489 506
490 507
491 508 .. _version 8.6.0:
492 509
493 510 IPython 8.6.0
494 511 -------------
495 512
496 513 Back to a more regular release schedule (at least I try), as Friday is
497 514 already over by more than 24h hours. This is a slightly bigger release with a
498 515 few new features that contain no less than 25 PRs.
499 516
500 517 We'll notably found a couple of non negligible changes:
501 518
502 519 The ``install_ext`` and related functions have been removed after being
503 520 deprecated for years. You can use pip to install extensions. ``pip`` did not
504 521 exist when ``install_ext`` was introduced. You can still load local extensions
505 522 without installing them. Just set your ``sys.path`` for example. :ghpull:`13744`
506 523
507 524 IPython now has extra entry points that use the major *and minor* version of
508 525 python. For some of you this means that you can do a quick ``ipython3.10`` to
509 526 launch IPython from the Python 3.10 interpreter, while still using Python 3.11
510 527 as your main Python. :ghpull:`13743`
511 528
512 529 The completer matcher API has been improved. See :ghpull:`13745`. This should
513 530 improve the type inference and improve dict keys completions in many use case.
514 531 Thanks ``@krassowski`` for all the work, and the D.E. Shaw group for sponsoring
515 532 it.
516 533
517 534 The color of error nodes in tracebacks can now be customized. See
518 535 :ghpull:`13756`. This is a private attribute until someone finds the time to
519 536 properly add a configuration option. Note that with Python 3.11 that also shows
520 537 the relevant nodes in traceback, it would be good to leverage this information
521 538 (plus the "did you mean" info added on attribute errors). But that's likely work
522 539 I won't have time to do before long, so contributions welcome.
523 540
524 541 As we follow NEP 29, we removed support for numpy 1.19 :ghpull:`13760`.
525 542
526 543
527 544 The ``open()`` function present in the user namespace by default will now refuse
528 545 to open the file descriptors 0,1,2 (stdin, out, err), to avoid crashing IPython.
529 546 This mostly occurs in teaching context when incorrect values get passed around.
530 547
531 548
532 549 The ``?``, ``??``, and corresponding ``pinfo``, ``pinfo2`` magics can now find
533 550 objects inside arrays. That is to say, the following now works::
534 551
535 552
536 553 >>> def my_func(*arg, **kwargs):pass
537 554 >>> container = [my_func]
538 555 >>> container[0]?
539 556
540 557
541 558 If ``container`` define a custom ``getitem``, this __will__ trigger the custom
542 559 method. So don't put side effects in your ``getitems``. Thanks to the D.E. Shaw
543 560 group for the request and sponsoring the work.
544 561
545 562
546 563 As usual you can find the full list of PRs on GitHub under `the 8.6 milestone
547 564 <https://github.com/ipython/ipython/pulls?q=milestone%3A8.6>`__.
548 565
549 566 Thanks to all hacktoberfest contributors, please contribute to
550 567 `closember.org <https://closember.org/>`__.
551 568
552 569 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
553 570 work on IPython and related libraries.
554 571
555 572 .. _version 8.5.0:
556 573
557 574 IPython 8.5.0
558 575 -------------
559 576
560 577 First release since a couple of month due to various reasons and timing preventing
561 578 me for sticking to the usual monthly release the last Friday of each month. This
562 579 is of non negligible size as it has more than two dozen PRs with various fixes
563 580 an bug fixes.
564 581
565 582 Many thanks to everybody who contributed PRs for your patience in review and
566 583 merges.
567 584
568 585 Here is a non-exhaustive list of changes that have been implemented for IPython
569 586 8.5.0. As usual you can find the full list of issues and PRs tagged with `the
570 587 8.5 milestone
571 588 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A8.5+>`__.
572 589
573 590 - Added a shortcut for accepting auto suggestion. The End key shortcut for
574 591 accepting auto-suggestion This binding works in Vi mode too, provided
575 592 ``TerminalInteractiveShell.emacs_bindings_in_vi_insert_mode`` is set to be
576 593 ``True`` :ghpull:`13566`.
577 594
578 595 - No popup in window for latex generation when generating latex (e.g. via
579 596 `_latex_repr_`) no popup window is shows under Windows. :ghpull:`13679`
580 597
581 598 - Fixed error raised when attempting to tab-complete an input string with
582 599 consecutive periods or forward slashes (such as "file:///var/log/...").
583 600 :ghpull:`13675`
584 601
585 602 - Relative filenames in Latex rendering :
586 603 The `latex_to_png_dvipng` command internally generates input and output file
587 604 arguments to `latex` and `dvipis`. These arguments are now generated as
588 605 relative files to the current working directory instead of absolute file
589 606 paths. This solves a problem where the current working directory contains
590 607 characters that are not handled properly by `latex` and `dvips`. There are
591 608 no changes to the user API. :ghpull:`13680`
592 609
593 610 - Stripping decorators bug: Fixed bug which meant that ipython code blocks in
594 611 restructured text documents executed with the ipython-sphinx extension
595 612 skipped any lines of code containing python decorators. :ghpull:`13612`
596 613
597 614 - Allow some modules with frozen dataclasses to be reloaded. :ghpull:`13732`
598 615 - Fix paste magic on wayland. :ghpull:`13671`
599 616 - show maxlen in deque's repr. :ghpull:`13648`
600 617
601 618 Restore line numbers for Input
602 619 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
603 620
604 621 Line number information in tracebacks from input are restored.
605 622 Line numbers from input were removed during the transition to v8 enhanced traceback reporting.
606 623
607 624 So, instead of::
608 625
609 626 ---------------------------------------------------------------------------
610 627 ZeroDivisionError Traceback (most recent call last)
611 628 Input In [3], in <cell line: 1>()
612 629 ----> 1 myfunc(2)
613 630
614 631 Input In [2], in myfunc(z)
615 632 1 def myfunc(z):
616 633 ----> 2 foo.boo(z-1)
617 634
618 635 File ~/code/python/ipython/foo.py:3, in boo(x)
619 636 2 def boo(x):
620 637 ----> 3 return 1/(1-x)
621 638
622 639 ZeroDivisionError: division by zero
623 640
624 641 The error traceback now looks like::
625 642
626 643 ---------------------------------------------------------------------------
627 644 ZeroDivisionError Traceback (most recent call last)
628 645 Cell In [3], line 1
629 646 ----> 1 myfunc(2)
630 647
631 648 Cell In [2], line 2, in myfunc(z)
632 649 1 def myfunc(z):
633 650 ----> 2 foo.boo(z-1)
634 651
635 652 File ~/code/python/ipython/foo.py:3, in boo(x)
636 653 2 def boo(x):
637 654 ----> 3 return 1/(1-x)
638 655
639 656 ZeroDivisionError: division by zero
640 657
641 658 or, with xmode=Plain::
642 659
643 660 Traceback (most recent call last):
644 661 Cell In [12], line 1
645 662 myfunc(2)
646 663 Cell In [6], line 2 in myfunc
647 664 foo.boo(z-1)
648 665 File ~/code/python/ipython/foo.py:3 in boo
649 666 return 1/(1-x)
650 667 ZeroDivisionError: division by zero
651 668
652 669 :ghpull:`13560`
653 670
654 671 New setting to silence warning if working inside a virtual environment
655 672 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
656 673
657 674 Previously, when starting IPython in a virtual environment without IPython installed (so IPython from the global environment is used), the following warning was printed:
658 675
659 676 Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
660 677
661 678 This warning can be permanently silenced by setting ``c.InteractiveShell.warn_venv`` to ``False`` (the default is ``True``).
662 679
663 680 :ghpull:`13706`
664 681
665 682 -------
666 683
667 684 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
668 685 work on IPython and related libraries.
669 686
670 687
671 688 .. _version 8.4.0:
672 689
673 690 IPython 8.4.0
674 691 -------------
675 692
676 693 As for 7.34, this version contains a single fix: fix uncaught BdbQuit exceptions on ipdb
677 694 exit :ghpull:`13668`, and a single typo fix in documentation: :ghpull:`13682`
678 695
679 696 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
680 697 work on IPython and related libraries.
681 698
682 699
683 700 .. _version 8.3.0:
684 701
685 702 IPython 8.3.0
686 703 -------------
687 704
688 705 - :ghpull:`13625`, using ``?``, ``??``, ``*?`` will not call
689 706 ``set_next_input`` as most frontend allow proper multiline editing and it was
690 707 causing issues for many users of multi-cell frontends. This has been backported to 7.33
691 708
692 709
693 710 - :ghpull:`13600`, ``pre_run_*``-hooks will now have a ``cell_id`` attribute on
694 711 the info object when frontend provides it. This has been backported to 7.33
695 712
696 713 - :ghpull:`13624`, fixed :kbd:`End` key being broken after accepting an
697 714 auto-suggestion.
698 715
699 716 - :ghpull:`13657` fixed an issue where history from different sessions would be mixed.
700 717
701 718 .. _version 8.2.0:
702 719
703 720 IPython 8.2.0
704 721 -------------
705 722
706 723 IPython 8.2 mostly bring bugfixes to IPython.
707 724
708 725 - Auto-suggestion can now be elected with the ``end`` key. :ghpull:`13566`
709 726 - Some traceback issues with ``assert etb is not None`` have been fixed. :ghpull:`13588`
710 727 - History is now pulled from the sqitel database and not from in-memory.
711 728 In particular when using the ``%paste`` magic, the content of the pasted text will
712 729 be part of the history and not the verbatim text ``%paste`` anymore. :ghpull:`13592`
713 730 - Fix ``Ctrl-\\`` exit cleanup :ghpull:`13603`
714 731 - Fixes to ``ultratb`` ipdb support when used outside of IPython. :ghpull:`13498`
715 732
716 733
717 734 I am still trying to fix and investigate :ghissue:`13598`, which seems to be
718 735 random, and would appreciate help if you find a reproducible minimal case. I've
719 736 tried to make various changes to the codebase to mitigate it, but a proper fix
720 737 will be difficult without understanding the cause.
721 738
722 739
723 740 All the issues on pull-requests for this release can be found in the `8.2
724 741 milestone. <https://github.com/ipython/ipython/milestone/100>`__ . And some
725 742 documentation only PR can be found as part of the `7.33 milestone
726 743 <https://github.com/ipython/ipython/milestone/101>`__ (currently not released).
727 744
728 745 Thanks to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
729 746 work on IPython and related libraries.
730 747
731 748 .. _version 8.1.1:
732 749
733 750 IPython 8.1.1
734 751 -------------
735 752
736 753 Fix an issue with virtualenv and Python 3.8 introduced in 8.1
737 754
738 755 Revert :ghpull:`13537` (fix an issue with symlinks in virtualenv) that raises an
739 756 error in Python 3.8, and fixed in a different way in :ghpull:`13559`.
740 757
741 758 .. _version 8.1:
742 759
743 760 IPython 8.1.0
744 761 -------------
745 762
746 763 IPython 8.1 is the first minor release after 8.0 and fixes a number of bugs and
747 764 updates a few behaviors that were problematic with the 8.0 as with many new major
748 765 release.
749 766
750 767 Note that beyond the changes listed here, IPython 8.1.0 also contains all the
751 768 features listed in :ref:`version 7.32`.
752 769
753 770 - Misc and multiple fixes around quotation auto-closing. It is now disabled by
754 771 default. Run with ``TerminalInteractiveShell.auto_match=True`` to re-enabled
755 772 - Require pygments>=2.4.0 :ghpull:`13459`, this was implicit in the code, but
756 773 is now explicit in ``setup.cfg``/``setup.py``
757 774 - Docs improvement of ``core.magic_arguments`` examples. :ghpull:`13433`
758 775 - Multi-line edit executes too early with await. :ghpull:`13424`
759 776
760 777 - ``black`` is back as an optional dependency, and autoformatting disabled by
761 778 default until some fixes are implemented (black improperly reformat magics).
762 779 :ghpull:`13471` Additionally the ability to use ``yapf`` as a code
763 780 reformatter has been added :ghpull:`13528` . You can use
764 781 ``TerminalInteractiveShell.autoformatter="black"``,
765 782 ``TerminalInteractiveShell.autoformatter="yapf"`` to re-enable auto formating
766 783 with black, or switch to yapf.
767 784
768 785 - Fix and issue where ``display`` was not defined.
769 786
770 787 - Auto suggestions are now configurable. Currently only
771 788 ``AutoSuggestFromHistory`` (default) and ``None``. new provider contribution
772 789 welcomed. :ghpull:`13475`
773 790
774 791 - multiple packaging/testing improvement to simplify downstream packaging
775 792 (xfail with reasons, try to not access network...).
776 793
777 794 - Update deprecation. ``InteractiveShell.magic`` internal method has been
778 795 deprecated for many years but did not emit a warning until now.
779 796
780 797 - internal ``appended_to_syspath`` context manager has been deprecated.
781 798
782 799 - fix an issue with symlinks in virtualenv :ghpull:`13537` (Reverted in 8.1.1)
783 800
784 801 - Fix an issue with vim mode, where cursor would not be reset on exit :ghpull:`13472`
785 802
786 803 - ipython directive now remove only known pseudo-decorators :ghpull:`13532`
787 804
788 805 - ``IPython/lib/security`` which used to be used for jupyter notebook has been
789 806 removed.
790 807
791 808 - Fix an issue where ``async with`` would execute on new lines. :ghpull:`13436`
792 809
793 810
794 811 We want to remind users that IPython is part of the Jupyter organisations, and
795 812 thus governed by a Code of Conduct. Some of the behavior we have seen on GitHub is not acceptable.
796 813 Abuse and non-respectful comments on discussion will not be tolerated.
797 814
798 815 Many thanks to all the contributors to this release, many of the above fixed issues and
799 816 new features were done by first time contributors, showing there is still
800 817 plenty of easy contribution possible in IPython
801 818 . You can find all individual contributions
802 819 to this milestone `on github <https://github.com/ipython/ipython/milestone/91>`__.
803 820
804 821 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
805 822 work on IPython and related libraries. In particular the Lazy autoloading of
806 823 magics that you will find described in the 7.32 release notes.
807 824
808 825
809 826 .. _version 8.0.1:
810 827
811 828 IPython 8.0.1 (CVE-2022-21699)
812 829 ------------------------------
813 830
814 831 IPython 8.0.1, 7.31.1 and 5.11 are security releases that change some default
815 832 values in order to prevent potential Execution with Unnecessary Privileges.
816 833
817 834 Almost all version of IPython looks for configuration and profiles in current
818 835 working directory. Since IPython was developed before pip and environments
819 836 existed it was used a convenient way to load code/packages in a project
820 837 dependant way.
821 838
822 839 In 2022, it is not necessary anymore, and can lead to confusing behavior where
823 840 for example cloning a repository and starting IPython or loading a notebook from
824 841 any Jupyter-Compatible interface that has ipython set as a kernel can lead to
825 842 code execution.
826 843
827 844
828 845 I did not find any standard way for packaged to advertise CVEs they fix, I'm
829 846 thus trying to add a ``__patched_cves__`` attribute to the IPython module that
830 847 list the CVEs that should have been fixed. This attribute is informational only
831 848 as if a executable has a flaw, this value can always be changed by an attacker.
832 849
833 850 .. code::
834 851
835 852 In [1]: import IPython
836 853
837 854 In [2]: IPython.__patched_cves__
838 855 Out[2]: {'CVE-2022-21699'}
839 856
840 857 In [3]: 'CVE-2022-21699' in IPython.__patched_cves__
841 858 Out[3]: True
842 859
843 860 Thus starting with this version:
844 861
845 862 - The current working directory is not searched anymore for profiles or
846 863 configurations files.
847 864 - Added a ``__patched_cves__`` attribute (set of strings) to IPython module that contain
848 865 the list of fixed CVE. This is informational only.
849 866
850 867 Further details can be read on the `GitHub Advisory <https://github.com/ipython/ipython/security/advisories/GHSA-pq7m-3gw7-gq5x>`__
851 868
852 869
853 870 .. _version 8.0:
854 871
855 872 IPython 8.0
856 873 -----------
857 874
858 875 IPython 8.0 is bringing a large number of new features and improvements to both the
859 876 user of the terminal and of the kernel via Jupyter. The removal of compatibility
860 877 with an older version of Python is also the opportunity to do a couple of
861 878 performance improvements in particular with respect to startup time.
862 879 The 8.x branch started diverging from its predecessor around IPython 7.12
863 880 (January 2020).
864 881
865 882 This release contains 250+ pull requests, in addition to many of the features
866 883 and backports that have made it to the 7.x branch. Please see the
867 884 `8.0 milestone <https://github.com/ipython/ipython/milestone/73?closed=1>`__ for the full list of pull requests.
868 885
869 886 Please feel free to send pull requests to update those notes after release,
870 887 I have likely forgotten a few things reviewing 250+ PRs.
871 888
872 889 Dependencies changes/downstream packaging
873 890 -----------------------------------------
874 891
875 892 Most of our building steps have been changed to be (mostly) declarative
876 893 and follow PEP 517. We are trying to completely remove ``setup.py`` (:ghpull:`13238`) and are
877 894 looking for help to do so.
878 895
879 896 - minimum supported ``traitlets`` version is now 5+
880 897 - we now require ``stack_data``
881 898 - minimal Python is now 3.8
882 899 - ``nose`` is not a testing requirement anymore
883 900 - ``pytest`` replaces nose.
884 901 - ``iptest``/``iptest3`` cli entrypoints do not exist anymore.
885 902 - the minimum officially ​supported ``numpy`` version has been bumped, but this should
886 903 not have much effect on packaging.
887 904
888 905
889 906 Deprecation and removal
890 907 -----------------------
891 908
892 909 We removed almost all features, arguments, functions, and modules that were
893 910 marked as deprecated between IPython 1.0 and 5.0. As a reminder, 5.0 was released
894 911 in 2016, and 1.0 in 2013. Last release of the 5 branch was 5.10.0, in May 2020.
895 912 The few remaining deprecated features we left have better deprecation warnings
896 913 or have been turned into explicit errors for better error messages.
897 914
898 915 I will use this occasion to add the following requests to anyone emitting a
899 916 deprecation warning:
900 917
901 918 - Please add at least ``stacklevel=2`` so that the warning is emitted into the
902 919 caller context, and not the callee one.
903 920 - Please add **since which version** something is deprecated.
904 921
905 922 As a side note, it is much easier to conditionally compare version
906 923 numbers rather than using ``try/except`` when functionality changes with a version.
907 924
908 925 I won't list all the removed features here, but modules like ``IPython.kernel``,
909 926 which was just a shim module around ``ipykernel`` for the past 8 years, have been
910 927 removed, and so many other similar things that pre-date the name **Jupyter**
911 928 itself.
912 929
913 930 We no longer need to add ``IPython.extensions`` to the PYTHONPATH because that is being
914 931 handled by ``load_extension``.
915 932
916 933 We are also removing ``Cythonmagic``, ``sympyprinting`` and ``rmagic`` as they are now in
917 934 other packages and no longer need to be inside IPython.
918 935
919 936
920 937 Documentation
921 938 -------------
922 939
923 940 The majority of our docstrings have now been reformatted and automatically fixed by
924 941 the experimental `Vélin <https://pypi.org/project/velin/>`_ project to conform
925 942 to numpydoc.
926 943
927 944 Type annotations
928 945 ----------------
929 946
930 947 While IPython itself is highly dynamic and can't be completely typed, many of
931 948 the functions now have type annotations, and part of the codebase is now checked
932 949 by mypy.
933 950
934 951
935 952 Featured changes
936 953 ----------------
937 954
938 955 Here is a features list of changes in IPython 8.0. This is of course non-exhaustive.
939 956 Please note as well that many features have been added in the 7.x branch as well
940 957 (and hence why you want to read the 7.x what's new notes), in particular
941 958 features contributed by QuantStack (with respect to debugger protocol and Xeus
942 959 Python), as well as many debugger features that I was pleased to implement as
943 960 part of my work at QuanSight and sponsored by DE Shaw.
944 961
945 962 Traceback improvements
946 963 ~~~~~~~~~~~~~~~~~~~~~~
947 964
948 965 Previously, error tracebacks for errors happening in code cells were showing a
949 966 hash, the one used for compiling the Python AST::
950 967
951 968 In [1]: def foo():
952 969 ...: return 3 / 0
953 970 ...:
954 971
955 972 In [2]: foo()
956 973 ---------------------------------------------------------------------------
957 974 ZeroDivisionError Traceback (most recent call last)
958 975 <ipython-input-2-c19b6d9633cf> in <module>
959 976 ----> 1 foo()
960 977
961 978 <ipython-input-1-1595a74c32d5> in foo()
962 979 1 def foo():
963 980 ----> 2 return 3 / 0
964 981 3
965 982
966 983 ZeroDivisionError: division by zero
967 984
968 985 The error traceback is now correctly formatted, showing the cell number in which the error happened::
969 986
970 987 In [1]: def foo():
971 988 ...: return 3 / 0
972 989 ...:
973 990
974 991 Input In [2]: foo()
975 992 ---------------------------------------------------------------------------
976 993 ZeroDivisionError Traceback (most recent call last)
977 994 input In [2], in <module>
978 995 ----> 1 foo()
979 996
980 997 Input In [1], in foo()
981 998 1 def foo():
982 999 ----> 2 return 3 / 0
983 1000
984 1001 ZeroDivisionError: division by zero
985 1002
986 1003 The ``stack_data`` package has been integrated, which provides smarter information in the traceback;
987 1004 in particular it will highlight the AST node where an error occurs which can help to quickly narrow down errors.
988 1005
989 1006 For example in the following snippet::
990 1007
991 1008 def foo(i):
992 1009 x = [[[0]]]
993 1010 return x[0][i][0]
994 1011
995 1012
996 1013 def bar():
997 1014 return foo(0) + foo(
998 1015 1
999 1016 ) + foo(2)
1000 1017
1001 1018
1002 1019 calling ``bar()`` would raise an ``IndexError`` on the return line of ``foo``,
1003 1020 and IPython 8.0 is capable of telling you where the index error occurs::
1004 1021
1005 1022
1006 1023 IndexError
1007 1024 Input In [2], in <module>
1008 1025 ----> 1 bar()
1009 1026 ^^^^^
1010 1027
1011 1028 Input In [1], in bar()
1012 1029 6 def bar():
1013 1030 ----> 7 return foo(0) + foo(
1014 1031 ^^^^
1015 1032 8 1
1016 1033 ^^^^^^^^
1017 1034 9 ) + foo(2)
1018 1035 ^^^^
1019 1036
1020 1037 Input In [1], in foo(i)
1021 1038 1 def foo(i):
1022 1039 2 x = [[[0]]]
1023 1040 ----> 3 return x[0][i][0]
1024 1041 ^^^^^^^
1025 1042
1026 1043 The corresponding locations marked here with ``^`` will show up highlighted in
1027 1044 the terminal and notebooks.
1028 1045
1029 1046 Finally, a colon ``::`` and line number is appended after a filename in
1030 1047 traceback::
1031 1048
1032 1049
1033 1050 ZeroDivisionError Traceback (most recent call last)
1034 1051 File ~/error.py:4, in <module>
1035 1052 1 def f():
1036 1053 2 1/0
1037 1054 ----> 4 f()
1038 1055
1039 1056 File ~/error.py:2, in f()
1040 1057 1 def f():
1041 1058 ----> 2 1/0
1042 1059
1043 1060 Many terminals and editors have integrations enabling you to directly jump to the
1044 1061 relevant file/line when this syntax is used, so this small addition may have a high
1045 1062 impact on productivity.
1046 1063
1047 1064
1048 1065 Autosuggestions
1049 1066 ~~~~~~~~~~~~~~~
1050 1067
1051 1068 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>`__.
1052 1069
1053 1070 `Ptpython <https://github.com/prompt-toolkit/ptpython#ptpython>`__ allows users to enable this feature in
1054 1071 `ptpython/config.py <https://github.com/prompt-toolkit/ptpython/blob/master/examples/ptpython_config/config.py#L90>`__.
1055 1072
1056 1073 This feature allows users to accept autosuggestions with ctrl e, ctrl f,
1057 1074 or right arrow as described below.
1058 1075
1059 1076 1. Start ipython
1060 1077
1061 1078 .. image:: ../_images/8.0/auto_suggest_1_prompt_no_text.png
1062 1079
1063 1080 2. Run ``print("hello")``
1064 1081
1065 1082 .. image:: ../_images/8.0/auto_suggest_2_print_hello_suggest.png
1066 1083
1067 1084 3. start typing ``print`` again to see the autosuggestion
1068 1085
1069 1086 .. image:: ../_images/8.0/auto_suggest_3_print_hello_suggest.png
1070 1087
1071 1088 4. Press ``ctrl-f``, or ``ctrl-e``, or ``right-arrow`` to accept the suggestion
1072 1089
1073 1090 .. image:: ../_images/8.0/auto_suggest_4_print_hello.png
1074 1091
1075 1092 You can also complete word by word:
1076 1093
1077 1094 1. Run ``def say_hello(): print("hello")``
1078 1095
1079 1096 .. image:: ../_images/8.0/auto_suggest_second_prompt.png
1080 1097
1081 1098 2. Start typing the first letter if ``def`` to see the autosuggestion
1082 1099
1083 1100 .. image:: ../_images/8.0/auto_suggest_d_phantom.png
1084 1101
1085 1102 3. Press ``alt-f`` (or ``escape`` followed by ``f``), to accept the first word of the suggestion
1086 1103
1087 1104 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
1088 1105
1089 1106 Importantly, this feature does not interfere with tab completion:
1090 1107
1091 1108 1. After running ``def say_hello(): print("hello")``, press d
1092 1109
1093 1110 .. image:: ../_images/8.0/auto_suggest_d_phantom.png
1094 1111
1095 1112 2. Press Tab to start tab completion
1096 1113
1097 1114 .. image:: ../_images/8.0/auto_suggest_d_completions.png
1098 1115
1099 1116 3A. Press Tab again to select the first option
1100 1117
1101 1118 .. image:: ../_images/8.0/auto_suggest_def_completions.png
1102 1119
1103 1120 3B. Press ``alt f`` (``escape``, ``f``) to accept to accept the first word of the suggestion
1104 1121
1105 1122 .. image:: ../_images/8.0/auto_suggest_def_phantom.png
1106 1123
1107 1124 3C. Press ``ctrl-f`` or ``ctrl-e`` to accept the entire suggestion
1108 1125
1109 1126 .. image:: ../_images/8.0/auto_suggest_match_parens.png
1110 1127
1111 1128
1112 1129 Currently, autosuggestions are only shown in the emacs or vi insert editing modes:
1113 1130
1114 1131 - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode.
1115 1132 - 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/>`__.
1116 1133
1117 1134
1118 1135 Show pinfo information in ipdb using "?" and "??"
1119 1136 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1120 1137
1121 1138 In IPDB, it is now possible to show the information about an object using "?"
1122 1139 and "??", in much the same way that it can be done when using the IPython prompt::
1123 1140
1124 1141 ipdb> partial?
1125 1142 Init signature: partial(self, /, *args, **kwargs)
1126 1143 Docstring:
1127 1144 partial(func, *args, **keywords) - new function with partial application
1128 1145 of the given arguments and keywords.
1129 1146 File: ~/.pyenv/versions/3.8.6/lib/python3.8/functools.py
1130 1147 Type: type
1131 1148 Subclasses:
1132 1149
1133 1150 Previously, ``pinfo`` or ``pinfo2`` command had to be used for this purpose.
1134 1151
1135 1152
1136 1153 Autoreload 3 feature
1137 1154 ~~~~~~~~~~~~~~~~~~~~
1138 1155
1139 1156 Example: When an IPython session is run with the 'autoreload' extension loaded,
1140 1157 you will now have the option '3' to select, which means the following:
1141 1158
1142 1159 1. replicate all functionality from option 2
1143 1160 2. autoload all new funcs/classes/enums/globals from the module when they are added
1144 1161 3. autoload all newly imported funcs/classes/enums/globals from external modules
1145 1162
1146 1163 Try ``%autoreload 3`` in an IPython session after running ``%load_ext autoreload``.
1147 1164
1148 1165 For more information please see the following unit test : ``extensions/tests/test_autoreload.py:test_autoload_newly_added_objects``
1149 1166
1150 1167 Auto formatting with black in the CLI
1151 1168 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1152 1169
1153 1170 This feature was present in 7.x, but disabled by default.
1154 1171
1155 1172 In 8.0, input was automatically reformatted with Black when black was installed.
1156 1173 This feature has been reverted for the time being.
1157 1174 You can re-enable it by setting ``TerminalInteractiveShell.autoformatter`` to ``"black"``
1158 1175
1159 1176 History Range Glob feature
1160 1177 ~~~~~~~~~~~~~~~~~~~~~~~~~~
1161 1178
1162 1179 Previously, when using ``%history``, users could specify either
1163 1180 a range of sessions and lines, for example:
1164 1181
1165 1182 .. code-block:: python
1166 1183
1167 1184 ~8/1-~6/5 # see history from the first line of 8 sessions ago,
1168 1185 # to the fifth line of 6 sessions ago.``
1169 1186
1170 1187 Or users could specify a glob pattern:
1171 1188
1172 1189 .. code-block:: python
1173 1190
1174 1191 -g <pattern> # glob ALL history for the specified pattern.
1175 1192
1176 1193 However users could *not* specify both.
1177 1194
1178 1195 If a user *did* specify both a range and a glob pattern,
1179 1196 then the glob pattern would be used (globbing *all* history) *and the range would be ignored*.
1180 1197
1181 1198 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.
1182 1199
1183 1200 Don't start a multi-line cell with sunken parenthesis
1184 1201 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1185 1202
1186 1203 From now on, IPython will not ask for the next line of input when given a single
1187 1204 line with more closing than opening brackets. For example, this means that if
1188 1205 you (mis)type ``]]`` instead of ``[]``, a ``SyntaxError`` will show up, instead of
1189 1206 the ``...:`` prompt continuation.
1190 1207
1191 1208 IPython shell for ipdb interact
1192 1209 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1193 1210
1194 1211 The ipdb ``interact`` starts an IPython shell instead of Python's built-in ``code.interact()``.
1195 1212
1196 1213 Automatic Vi prompt stripping
1197 1214 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1198 1215
1199 1216 When pasting code into IPython, it will strip the leading prompt characters if
1200 1217 there are any. For example, you can paste the following code into the console -
1201 1218 it will still work, even though each line is prefixed with prompts (``In``,
1202 1219 ``Out``)::
1203 1220
1204 1221 In [1]: 2 * 2 == 4
1205 1222 Out[1]: True
1206 1223
1207 1224 In [2]: print("This still works as pasted")
1208 1225
1209 1226
1210 1227 Previously, this was not the case for the Vi-mode prompts::
1211 1228
1212 1229 In [1]: [ins] In [13]: 2 * 2 == 4
1213 1230 ...: Out[13]: True
1214 1231 ...:
1215 1232 File "<ipython-input-1-727bb88eaf33>", line 1
1216 1233 [ins] In [13]: 2 * 2 == 4
1217 1234 ^
1218 1235 SyntaxError: invalid syntax
1219 1236
1220 1237 This is now fixed, and Vi prompt prefixes - ``[ins]`` and ``[nav]`` - are
1221 1238 skipped just as the normal ``In`` would be.
1222 1239
1223 1240 IPython shell can be started in the Vi mode using ``ipython --TerminalInteractiveShell.editing_mode=vi``,
1224 1241 You should be able to change mode dynamically with ``%config TerminalInteractiveShell.editing_mode='vi'``
1225 1242
1226 1243 Empty History Ranges
1227 1244 ~~~~~~~~~~~~~~~~~~~~
1228 1245
1229 1246 A number of magics that take history ranges can now be used with an empty
1230 1247 range. These magics are:
1231 1248
1232 1249 * ``%save``
1233 1250 * ``%load``
1234 1251 * ``%pastebin``
1235 1252 * ``%pycat``
1236 1253
1237 1254 Using them this way will make them take the history of the current session up
1238 1255 to the point of the magic call (such that the magic itself will not be
1239 1256 included).
1240 1257
1241 1258 Therefore it is now possible to save the whole history to a file using
1242 1259 ``%save <filename>``, load and edit it using ``%load`` (makes for a nice usage
1243 1260 when followed with :kbd:`F2`), send it to `dpaste.org <http://dpast.org>`_ using
1244 1261 ``%pastebin``, or view the whole thing syntax-highlighted with a single
1245 1262 ``%pycat``.
1246 1263
1247 1264
1248 1265 Windows timing implementation: Switch to process_time
1249 1266 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1250 1267 Timing on Windows, for example with ``%%time``, was changed from being based on ``time.perf_counter``
1251 1268 (which counted time even when the process was sleeping) to being based on ``time.process_time`` instead
1252 1269 (which only counts CPU time). This brings it closer to the behavior on Linux. See :ghpull:`12984`.
1253 1270
1254 1271 Miscellaneous
1255 1272 ~~~~~~~~~~~~~
1256 1273 - Non-text formatters are not disabled in the terminal, which should simplify
1257 1274 writing extensions displaying images or other mimetypes in supporting terminals.
1258 1275 :ghpull:`12315`
1259 1276 - It is now possible to automatically insert matching brackets in Terminal IPython using the
1260 1277 ``TerminalInteractiveShell.auto_match=True`` option. :ghpull:`12586`
1261 1278 - We are thinking of deprecating the current ``%%javascript`` magic in favor of a better replacement. See :ghpull:`13376`.
1262 1279 - ``~`` is now expanded when part of a path in most magics :ghpull:`13385`
1263 1280 - ``%/%%timeit`` magic now adds a comma every thousands to make reading a long number easier :ghpull:`13379`
1264 1281 - ``"info"`` messages can now be customised to hide some fields :ghpull:`13343`
1265 1282 - ``collections.UserList`` now pretty-prints :ghpull:`13320`
1266 1283 - The debugger now has a persistent history, which should make it less
1267 1284 annoying to retype commands :ghpull:`13246`
1268 1285 - ``!pip`` ``!conda`` ``!cd`` or ``!ls`` are likely doing the wrong thing. We
1269 1286 now warn users if they use one of those commands. :ghpull:`12954`
1270 1287 - Make ``%precision`` work for ``numpy.float64`` type :ghpull:`12902`
1271 1288
1272 1289 Re-added support for XDG config directories
1273 1290 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1274 1291
1275 1292 XDG support through the years comes and goes. There is a tension between having
1276 1293 an identical location for configuration in all platforms versus having simple instructions.
1277 1294 After initial failures a couple of years ago, IPython was modified to automatically migrate XDG
1278 1295 config files back into ``~/.ipython``. That migration code has now been removed.
1279 1296 IPython now checks the XDG locations, so if you _manually_ move your config
1280 1297 files to your preferred location, IPython will not move them back.
1281 1298
1282 1299
1283 1300 Preparing for Python 3.10
1284 1301 -------------------------
1285 1302
1286 1303 To prepare for Python 3.10, we have started working on removing reliance and
1287 1304 any dependency that is not compatible with Python 3.10. This includes migrating our
1288 1305 test suite to pytest and starting to remove nose. This also means that the
1289 1306 ``iptest`` command is now gone and all testing is via pytest.
1290 1307
1291 1308 This was in large part thanks to the NumFOCUS Small Developer grant, which enabled us to
1292 1309 allocate \$4000 to hire `Nikita Kniazev (@Kojoley) <https://github.com/Kojoley>`_,
1293 1310 who did a fantastic job at updating our code base, migrating to pytest, pushing
1294 1311 our coverage, and fixing a large number of bugs. I highly recommend contacting
1295 1312 them if you need help with C++ and Python projects.
1296 1313
1297 1314 You can find all relevant issues and PRs with `the SDG 2021 tag <https://github.com/ipython/ipython/issues?q=label%3A%22Numfocus+SDG+2021%22+>`__
1298 1315
1299 1316 Removing support for older Python versions
1300 1317 ------------------------------------------
1301 1318
1302 1319
1303 1320 We are removing support for Python up through 3.7, allowing internal code to use the more
1304 1321 efficient ``pathlib`` and to make better use of type annotations.
1305 1322
1306 1323 .. image:: ../_images/8.0/pathlib_pathlib_everywhere.jpg
1307 1324 :alt: "Meme image of Toy Story with Woody and Buzz, with the text 'pathlib, pathlib everywhere'"
1308 1325
1309 1326
1310 1327 We had about 34 PRs only to update some logic to update some functions from managing strings to
1311 1328 using Pathlib.
1312 1329
1313 1330 The completer has also seen significant updates and now makes use of newer Jedi APIs,
1314 1331 offering faster and more reliable tab completion.
1315 1332
1316 1333 Misc Statistics
1317 1334 ---------------
1318 1335
1319 1336 Here are some numbers::
1320 1337
1321 1338 7.x: 296 files, 12561 blank lines, 20282 comments, 35142 line of code.
1322 1339 8.0: 252 files, 12053 blank lines, 19232 comments, 34505 line of code.
1323 1340
1324 1341 $ git diff --stat 7.x...master | tail -1
1325 1342 340 files changed, 13399 insertions(+), 12421 deletions(-)
1326 1343
1327 1344 We have commits from 162 authors, who contributed 1916 commits in 23 month, excluding merges (to not bias toward
1328 1345 maintainers pushing buttons).::
1329 1346
1330 1347 $ git shortlog -s --no-merges 7.x...master | sort -nr
1331 1348 535 Matthias Bussonnier
1332 1349 86 Nikita Kniazev
1333 1350 69 Blazej Michalik
1334 1351 49 Samuel Gaist
1335 1352 27 Itamar Turner-Trauring
1336 1353 18 Spas Kalaydzhisyki
1337 1354 17 Thomas Kluyver
1338 1355 17 Quentin Peter
1339 1356 17 James Morris
1340 1357 17 Artur Svistunov
1341 1358 15 Bart Skowron
1342 1359 14 Alex Hall
1343 1360 13 rushabh-v
1344 1361 13 Terry Davis
1345 1362 13 Benjamin Ragan-Kelley
1346 1363 8 martinRenou
1347 1364 8 farisachugthai
1348 1365 7 dswij
1349 1366 7 Gal B
1350 1367 7 Corentin Cadiou
1351 1368 6 yuji96
1352 1369 6 Martin Skarzynski
1353 1370 6 Justin Palmer
1354 1371 6 Daniel Goldfarb
1355 1372 6 Ben Greiner
1356 1373 5 Sammy Al Hashemi
1357 1374 5 Paul Ivanov
1358 1375 5 Inception95
1359 1376 5 Eyenpi
1360 1377 5 Douglas Blank
1361 1378 5 Coco Mishra
1362 1379 5 Bibo Hao
1363 1380 5 André A. Gomes
1364 1381 5 Ahmed Fasih
1365 1382 4 takuya fujiwara
1366 1383 4 palewire
1367 1384 4 Thomas A Caswell
1368 1385 4 Talley Lambert
1369 1386 4 Scott Sanderson
1370 1387 4 Ram Rachum
1371 1388 4 Nick Muoh
1372 1389 4 Nathan Goldbaum
1373 1390 4 Mithil Poojary
1374 1391 4 Michael T
1375 1392 4 Jakub Klus
1376 1393 4 Ian Castleden
1377 1394 4 Eli Rykoff
1378 1395 4 Ashwin Vishnu
1379 1396 3 谭九鼎
1380 1397 3 sleeping
1381 1398 3 Sylvain Corlay
1382 1399 3 Peter Corke
1383 1400 3 Paul Bissex
1384 1401 3 Matthew Feickert
1385 1402 3 Fernando Perez
1386 1403 3 Eric Wieser
1387 1404 3 Daniel Mietchen
1388 1405 3 Aditya Sathe
1389 1406 3 007vedant
1390 1407 2 rchiodo
1391 1408 2 nicolaslazo
1392 1409 2 luttik
1393 1410 2 gorogoroumaru
1394 1411 2 foobarbyte
1395 1412 2 bar-hen
1396 1413 2 Theo Ouzhinski
1397 1414 2 Strawkage
1398 1415 2 Samreen Zarroug
1399 1416 2 Pete Blois
1400 1417 2 Meysam Azad
1401 1418 2 Matthieu Ancellin
1402 1419 2 Mark Schmitz
1403 1420 2 Maor Kleinberger
1404 1421 2 MRCWirtz
1405 1422 2 Lumir Balhar
1406 1423 2 Julien Rabinow
1407 1424 2 Juan Luis Cano Rodríguez
1408 1425 2 Joyce Er
1409 1426 2 Jakub
1410 1427 2 Faris A Chugthai
1411 1428 2 Ethan Madden
1412 1429 2 Dimitri Papadopoulos
1413 1430 2 Diego Fernandez
1414 1431 2 Daniel Shimon
1415 1432 2 Coco Bennett
1416 1433 2 Carlos Cordoba
1417 1434 2 Boyuan Liu
1418 1435 2 BaoGiang HoangVu
1419 1436 2 Augusto
1420 1437 2 Arthur Svistunov
1421 1438 2 Arthur Moreira
1422 1439 2 Ali Nabipour
1423 1440 2 Adam Hackbarth
1424 1441 1 richard
1425 1442 1 linar-jether
1426 1443 1 lbennett
1427 1444 1 juacrumar
1428 1445 1 gpotter2
1429 1446 1 digitalvirtuoso
1430 1447 1 dalthviz
1431 1448 1 Yonatan Goldschmidt
1432 1449 1 Tomasz Kłoczko
1433 1450 1 Tobias Bengfort
1434 1451 1 Timur Kushukov
1435 1452 1 Thomas
1436 1453 1 Snir Broshi
1437 1454 1 Shao Yang Hong
1438 1455 1 Sanjana-03
1439 1456 1 Romulo Filho
1440 1457 1 Rodolfo Carvalho
1441 1458 1 Richard Shadrach
1442 1459 1 Reilly Tucker Siemens
1443 1460 1 Rakessh Roshan
1444 1461 1 Piers Titus van der Torren
1445 1462 1 PhanatosZou
1446 1463 1 Pavel Safronov
1447 1464 1 Paulo S. Costa
1448 1465 1 Paul McCarthy
1449 1466 1 NotWearingPants
1450 1467 1 Naelson Douglas
1451 1468 1 Michael Tiemann
1452 1469 1 Matt Wozniski
1453 1470 1 Markus Wageringel
1454 1471 1 Marcus Wirtz
1455 1472 1 Marcio Mazza
1456 1473 1 Lumír 'Frenzy' Balhar
1457 1474 1 Lightyagami1
1458 1475 1 Leon Anavi
1459 1476 1 LeafyLi
1460 1477 1 L0uisJ0shua
1461 1478 1 Kyle Cutler
1462 1479 1 Krzysztof Cybulski
1463 1480 1 Kevin Kirsche
1464 1481 1 KIU Shueng Chuan
1465 1482 1 Jonathan Slenders
1466 1483 1 Jay Qi
1467 1484 1 Jake VanderPlas
1468 1485 1 Iwan Briquemont
1469 1486 1 Hussaina Begum Nandyala
1470 1487 1 Gordon Ball
1471 1488 1 Gabriel Simonetto
1472 1489 1 Frank Tobia
1473 1490 1 Erik
1474 1491 1 Elliott Sales de Andrade
1475 1492 1 Daniel Hahler
1476 1493 1 Dan Green-Leipciger
1477 1494 1 Dan Green
1478 1495 1 Damian Yurzola
1479 1496 1 Coon, Ethan T
1480 1497 1 Carol Willing
1481 1498 1 Brian Lee
1482 1499 1 Brendan Gerrity
1483 1500 1 Blake Griffin
1484 1501 1 Bastian Ebeling
1485 1502 1 Bartosz Telenczuk
1486 1503 1 Ankitsingh6299
1487 1504 1 Andrew Port
1488 1505 1 Andrew J. Hesford
1489 1506 1 Albert Zhang
1490 1507 1 Adam Johnson
1491 1508
1492 1509 This does not, of course, represent non-code contributions, for which we are also grateful.
1493 1510
1494 1511
1495 1512 API Changes using Frappuccino
1496 1513 -----------------------------
1497 1514
1498 1515 This is an experimental exhaustive API difference using `Frappuccino <https://pypi.org/project/frappuccino/>`_
1499 1516
1500 1517
1501 1518 The following items are new in IPython 8.0 ::
1502 1519
1503 1520 + IPython.core.async_helpers.get_asyncio_loop()
1504 1521 + IPython.core.completer.Dict
1505 1522 + IPython.core.completer.Pattern
1506 1523 + IPython.core.completer.Sequence
1507 1524 + IPython.core.completer.__skip_doctest__
1508 1525 + IPython.core.debugger.Pdb.precmd(self, line)
1509 1526 + IPython.core.debugger.__skip_doctest__
1510 1527 + IPython.core.display.__getattr__(name)
1511 1528 + IPython.core.display.warn
1512 1529 + IPython.core.display_functions
1513 1530 + IPython.core.display_functions.DisplayHandle
1514 1531 + IPython.core.display_functions.DisplayHandle.display(self, obj, **kwargs)
1515 1532 + IPython.core.display_functions.DisplayHandle.update(self, obj, **kwargs)
1516 1533 + IPython.core.display_functions.__all__
1517 1534 + IPython.core.display_functions.__builtins__
1518 1535 + IPython.core.display_functions.__cached__
1519 1536 + IPython.core.display_functions.__doc__
1520 1537 + IPython.core.display_functions.__file__
1521 1538 + IPython.core.display_functions.__loader__
1522 1539 + IPython.core.display_functions.__name__
1523 1540 + IPython.core.display_functions.__package__
1524 1541 + IPython.core.display_functions.__spec__
1525 1542 + IPython.core.display_functions.b2a_hex
1526 1543 + IPython.core.display_functions.clear_output(wait=False)
1527 1544 + IPython.core.display_functions.display(*objs, include='None', exclude='None', metadata='None', transient='None', display_id='None', raw=False, clear=False, **kwargs)
1528 1545 + IPython.core.display_functions.publish_display_data(data, metadata='None', source='<deprecated>', *, transient='None', **kwargs)
1529 1546 + IPython.core.display_functions.update_display(obj, *, display_id, **kwargs)
1530 1547 + IPython.core.extensions.BUILTINS_EXTS
1531 1548 + IPython.core.inputtransformer2.has_sunken_brackets(tokens)
1532 1549 + IPython.core.interactiveshell.Callable
1533 1550 + IPython.core.interactiveshell.__annotations__
1534 1551 + IPython.core.ultratb.List
1535 1552 + IPython.core.ultratb.Tuple
1536 1553 + IPython.lib.pretty.CallExpression
1537 1554 + IPython.lib.pretty.CallExpression.factory(name)
1538 1555 + IPython.lib.pretty.RawStringLiteral
1539 1556 + IPython.lib.pretty.RawText
1540 1557 + IPython.terminal.debugger.TerminalPdb.do_interact(self, arg)
1541 1558 + IPython.terminal.embed.Set
1542 1559
1543 1560 The following items have been removed (or moved to superclass)::
1544 1561
1545 1562 - IPython.core.application.BaseIPythonApplication.initialize_subcommand
1546 1563 - IPython.core.completer.Sentinel
1547 1564 - IPython.core.completer.skip_doctest
1548 1565 - IPython.core.debugger.Tracer
1549 1566 - IPython.core.display.DisplayHandle
1550 1567 - IPython.core.display.DisplayHandle.display
1551 1568 - IPython.core.display.DisplayHandle.update
1552 1569 - IPython.core.display.b2a_hex
1553 1570 - IPython.core.display.clear_output
1554 1571 - IPython.core.display.display
1555 1572 - IPython.core.display.publish_display_data
1556 1573 - IPython.core.display.update_display
1557 1574 - IPython.core.excolors.Deprec
1558 1575 - IPython.core.excolors.ExceptionColors
1559 1576 - IPython.core.history.warn
1560 1577 - IPython.core.hooks.late_startup_hook
1561 1578 - IPython.core.hooks.pre_run_code_hook
1562 1579 - IPython.core.hooks.shutdown_hook
1563 1580 - IPython.core.interactiveshell.InteractiveShell.init_deprecation_warnings
1564 1581 - IPython.core.interactiveshell.InteractiveShell.init_readline
1565 1582 - IPython.core.interactiveshell.InteractiveShell.write
1566 1583 - IPython.core.interactiveshell.InteractiveShell.write_err
1567 1584 - IPython.core.interactiveshell.get_default_colors
1568 1585 - IPython.core.interactiveshell.removed_co_newlocals
1569 1586 - IPython.core.magics.execution.ExecutionMagics.profile_missing_notice
1570 1587 - IPython.core.magics.script.PIPE
1571 1588 - IPython.core.prefilter.PrefilterManager.init_transformers
1572 1589 - IPython.core.release.classifiers
1573 1590 - IPython.core.release.description
1574 1591 - IPython.core.release.keywords
1575 1592 - IPython.core.release.long_description
1576 1593 - IPython.core.release.name
1577 1594 - IPython.core.release.platforms
1578 1595 - IPython.core.release.url
1579 1596 - IPython.core.ultratb.VerboseTB.format_records
1580 1597 - IPython.core.ultratb.find_recursion
1581 1598 - IPython.core.ultratb.findsource
1582 1599 - IPython.core.ultratb.fix_frame_records_filenames
1583 1600 - IPython.core.ultratb.inspect_error
1584 1601 - IPython.core.ultratb.is_recursion_error
1585 1602 - IPython.core.ultratb.with_patch_inspect
1586 1603 - IPython.external.__all__
1587 1604 - IPython.external.__builtins__
1588 1605 - IPython.external.__cached__
1589 1606 - IPython.external.__doc__
1590 1607 - IPython.external.__file__
1591 1608 - IPython.external.__loader__
1592 1609 - IPython.external.__name__
1593 1610 - IPython.external.__package__
1594 1611 - IPython.external.__path__
1595 1612 - IPython.external.__spec__
1596 1613 - IPython.kernel.KernelConnectionInfo
1597 1614 - IPython.kernel.__builtins__
1598 1615 - IPython.kernel.__cached__
1599 1616 - IPython.kernel.__warningregistry__
1600 1617 - IPython.kernel.pkg
1601 1618 - IPython.kernel.protocol_version
1602 1619 - IPython.kernel.protocol_version_info
1603 1620 - IPython.kernel.src
1604 1621 - IPython.kernel.version_info
1605 1622 - IPython.kernel.warn
1606 1623 - IPython.lib.backgroundjobs
1607 1624 - IPython.lib.backgroundjobs.BackgroundJobBase
1608 1625 - IPython.lib.backgroundjobs.BackgroundJobBase.run
1609 1626 - IPython.lib.backgroundjobs.BackgroundJobBase.traceback
1610 1627 - IPython.lib.backgroundjobs.BackgroundJobExpr
1611 1628 - IPython.lib.backgroundjobs.BackgroundJobExpr.call
1612 1629 - IPython.lib.backgroundjobs.BackgroundJobFunc
1613 1630 - IPython.lib.backgroundjobs.BackgroundJobFunc.call
1614 1631 - IPython.lib.backgroundjobs.BackgroundJobManager
1615 1632 - IPython.lib.backgroundjobs.BackgroundJobManager.flush
1616 1633 - IPython.lib.backgroundjobs.BackgroundJobManager.new
1617 1634 - IPython.lib.backgroundjobs.BackgroundJobManager.remove
1618 1635 - IPython.lib.backgroundjobs.BackgroundJobManager.result
1619 1636 - IPython.lib.backgroundjobs.BackgroundJobManager.status
1620 1637 - IPython.lib.backgroundjobs.BackgroundJobManager.traceback
1621 1638 - IPython.lib.backgroundjobs.__builtins__
1622 1639 - IPython.lib.backgroundjobs.__cached__
1623 1640 - IPython.lib.backgroundjobs.__doc__
1624 1641 - IPython.lib.backgroundjobs.__file__
1625 1642 - IPython.lib.backgroundjobs.__loader__
1626 1643 - IPython.lib.backgroundjobs.__name__
1627 1644 - IPython.lib.backgroundjobs.__package__
1628 1645 - IPython.lib.backgroundjobs.__spec__
1629 1646 - IPython.lib.kernel.__builtins__
1630 1647 - IPython.lib.kernel.__cached__
1631 1648 - IPython.lib.kernel.__doc__
1632 1649 - IPython.lib.kernel.__file__
1633 1650 - IPython.lib.kernel.__loader__
1634 1651 - IPython.lib.kernel.__name__
1635 1652 - IPython.lib.kernel.__package__
1636 1653 - IPython.lib.kernel.__spec__
1637 1654 - IPython.lib.kernel.__warningregistry__
1638 1655 - IPython.paths.fs_encoding
1639 1656 - IPython.terminal.debugger.DEFAULT_BUFFER
1640 1657 - IPython.terminal.debugger.cursor_in_leading_ws
1641 1658 - IPython.terminal.debugger.emacs_insert_mode
1642 1659 - IPython.terminal.debugger.has_selection
1643 1660 - IPython.terminal.debugger.vi_insert_mode
1644 1661 - IPython.terminal.interactiveshell.DISPLAY_BANNER_DEPRECATED
1645 1662 - IPython.terminal.ipapp.TerminalIPythonApp.parse_command_line
1646 1663 - IPython.testing.test
1647 1664 - IPython.utils.contexts.NoOpContext
1648 1665 - IPython.utils.io.IOStream
1649 1666 - IPython.utils.io.IOStream.close
1650 1667 - IPython.utils.io.IOStream.write
1651 1668 - IPython.utils.io.IOStream.writelines
1652 1669 - IPython.utils.io.__warningregistry__
1653 1670 - IPython.utils.io.atomic_writing
1654 1671 - IPython.utils.io.stderr
1655 1672 - IPython.utils.io.stdin
1656 1673 - IPython.utils.io.stdout
1657 1674 - IPython.utils.io.unicode_std_stream
1658 1675 - IPython.utils.path.get_ipython_cache_dir
1659 1676 - IPython.utils.path.get_ipython_dir
1660 1677 - IPython.utils.path.get_ipython_module_path
1661 1678 - IPython.utils.path.get_ipython_package_dir
1662 1679 - IPython.utils.path.locate_profile
1663 1680 - IPython.utils.path.unquote_filename
1664 1681 - IPython.utils.py3compat.PY2
1665 1682 - IPython.utils.py3compat.PY3
1666 1683 - IPython.utils.py3compat.buffer_to_bytes
1667 1684 - IPython.utils.py3compat.builtin_mod_name
1668 1685 - IPython.utils.py3compat.cast_bytes
1669 1686 - IPython.utils.py3compat.getcwd
1670 1687 - IPython.utils.py3compat.isidentifier
1671 1688 - IPython.utils.py3compat.u_format
1672 1689
1673 1690 The following signatures differ between 7.x and 8.0::
1674 1691
1675 1692 - IPython.core.completer.IPCompleter.unicode_name_matches(self, text)
1676 1693 + IPython.core.completer.IPCompleter.unicode_name_matches(text)
1677 1694
1678 1695 - IPython.core.completer.match_dict_keys(keys, prefix, delims)
1679 1696 + IPython.core.completer.match_dict_keys(keys, prefix, delims, extra_prefix='None')
1680 1697
1681 1698 - IPython.core.interactiveshell.InteractiveShell.object_inspect_mime(self, oname, detail_level=0)
1682 1699 + IPython.core.interactiveshell.InteractiveShell.object_inspect_mime(self, oname, detail_level=0, omit_sections='()')
1683 1700
1684 1701 - IPython.core.interactiveshell.InteractiveShell.set_hook(self, name, hook, priority=50, str_key='None', re_key='None', _warn_deprecated=True)
1685 1702 + IPython.core.interactiveshell.InteractiveShell.set_hook(self, name, hook, priority=50, str_key='None', re_key='None')
1686 1703
1687 1704 - IPython.core.oinspect.Inspector.info(self, obj, oname='', formatter='None', info='None', detail_level=0)
1688 1705 + IPython.core.oinspect.Inspector.info(self, obj, oname='', info='None', detail_level=0)
1689 1706
1690 1707 - IPython.core.oinspect.Inspector.pinfo(self, obj, oname='', formatter='None', info='None', detail_level=0, enable_html_pager=True)
1691 1708 + IPython.core.oinspect.Inspector.pinfo(self, obj, oname='', formatter='None', info='None', detail_level=0, enable_html_pager=True, omit_sections='()')
1692 1709
1693 1710 - IPython.core.profiledir.ProfileDir.copy_config_file(self, config_file, path='None', overwrite=False)
1694 1711 + IPython.core.profiledir.ProfileDir.copy_config_file(self, config_file, path, overwrite=False)
1695 1712
1696 1713 - IPython.core.ultratb.VerboseTB.format_record(self, frame, file, lnum, func, lines, index)
1697 1714 + IPython.core.ultratb.VerboseTB.format_record(self, frame_info)
1698 1715
1699 1716 - IPython.terminal.embed.InteractiveShellEmbed.mainloop(self, local_ns='None', module='None', stack_depth=0, display_banner='None', global_ns='None', compile_flags='None')
1700 1717 + IPython.terminal.embed.InteractiveShellEmbed.mainloop(self, local_ns='None', module='None', stack_depth=0, compile_flags='None')
1701 1718
1702 1719 - IPython.terminal.embed.embed(**kwargs)
1703 1720 + IPython.terminal.embed.embed(*, header='', compile_flags='None', **kwargs)
1704 1721
1705 1722 - IPython.terminal.interactiveshell.TerminalInteractiveShell.interact(self, display_banner='<object object at 0xffffff>')
1706 1723 + IPython.terminal.interactiveshell.TerminalInteractiveShell.interact(self)
1707 1724
1708 1725 - IPython.terminal.interactiveshell.TerminalInteractiveShell.mainloop(self, display_banner='<object object at 0xffffff>')
1709 1726 + IPython.terminal.interactiveshell.TerminalInteractiveShell.mainloop(self)
1710 1727
1711 1728 - IPython.utils.path.get_py_filename(name, force_win32='None')
1712 1729 + IPython.utils.path.get_py_filename(name)
1713 1730
1714 1731 The following are new attributes (that might be inherited)::
1715 1732
1716 1733 + IPython.core.completer.IPCompleter.unicode_names
1717 1734 + IPython.core.debugger.InterruptiblePdb.precmd
1718 1735 + IPython.core.debugger.Pdb.precmd
1719 1736 + IPython.core.ultratb.AutoFormattedTB.has_colors
1720 1737 + IPython.core.ultratb.ColorTB.has_colors
1721 1738 + IPython.core.ultratb.FormattedTB.has_colors
1722 1739 + IPython.core.ultratb.ListTB.has_colors
1723 1740 + IPython.core.ultratb.SyntaxTB.has_colors
1724 1741 + IPython.core.ultratb.TBTools.has_colors
1725 1742 + IPython.core.ultratb.VerboseTB.has_colors
1726 1743 + IPython.terminal.debugger.TerminalPdb.do_interact
1727 1744 + IPython.terminal.debugger.TerminalPdb.precmd
1728 1745
1729 1746 The following attribute/methods have been removed::
1730 1747
1731 1748 - IPython.core.application.BaseIPythonApplication.deprecated_subcommands
1732 1749 - IPython.core.ultratb.AutoFormattedTB.format_records
1733 1750 - IPython.core.ultratb.ColorTB.format_records
1734 1751 - IPython.core.ultratb.FormattedTB.format_records
1735 1752 - IPython.terminal.embed.InteractiveShellEmbed.init_deprecation_warnings
1736 1753 - IPython.terminal.embed.InteractiveShellEmbed.init_readline
1737 1754 - IPython.terminal.embed.InteractiveShellEmbed.write
1738 1755 - IPython.terminal.embed.InteractiveShellEmbed.write_err
1739 1756 - IPython.terminal.interactiveshell.TerminalInteractiveShell.init_deprecation_warnings
1740 1757 - IPython.terminal.interactiveshell.TerminalInteractiveShell.init_readline
1741 1758 - IPython.terminal.interactiveshell.TerminalInteractiveShell.write
1742 1759 - IPython.terminal.interactiveshell.TerminalInteractiveShell.write_err
1743 1760 - IPython.terminal.ipapp.LocateIPythonApp.deprecated_subcommands
1744 1761 - IPython.terminal.ipapp.LocateIPythonApp.initialize_subcommand
1745 1762 - IPython.terminal.ipapp.TerminalIPythonApp.deprecated_subcommands
1746 1763 - IPython.terminal.ipapp.TerminalIPythonApp.initialize_subcommand
General Comments 0
You need to be logged in to leave comments. Login now