##// END OF EJS Templates
Improve error tracebacks so that it shows the cell prompts
martinRenou -
Show More
@@ -0,0 +1,39 b''
1 Traceback improvements
2 ======================
3
4 Previously, error tracebacks for errors happening in code cells were showing a hash, the one used for compiling the Python AST.
5
6 In [1]: def foo():
7 ...: return 3 / 0
8 ...:
9
10 In [2]: foo()
11 ---------------------------------------------------------------------------
12 ZeroDivisionError Traceback (most recent call last)
13 <ipython-input-2-c19b6d9633cf> in <module>
14 ----> 1 foo()
15
16 <ipython-input-1-1595a74c32d5> in foo()
17 1 def foo():
18 ----> 2 return 3 / 0
19 3
20
21 ZeroDivisionError: division by zero
22
23 The error traceback is now correctly formatted, showing the cell number in which the error happened:
24
25 In [1]: def foo():
26 ...: return 3 / 0
27 ...:
28
29 In [2]: foo()
30 ---------------------------------------------------------------------------
31 ZeroDivisionError Traceback (most recent call last)
32 In [2], in <module>
33 ----> 1 foo()
34
35 In [1], in foo()
36 1 def foo():
37 ----> 2 return 3 / 0
38
39 ZeroDivisionError: division by zero
@@ -92,6 +92,10 b' class CachingCompiler(codeop.Compile):'
92 # (otherwise we'd lose our tracebacks).
92 # (otherwise we'd lose our tracebacks).
93 linecache.checkcache = check_linecache_ipython
93 linecache.checkcache = check_linecache_ipython
94
94
95 # Caching a dictionary { filename: execution_count } for nicely
96 # rendered tracebacks. The filename corresponds to the filename
97 # argument used for the builtins.compile function.
98 self._filename_map = {}
95
99
96 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
100 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
97 """Parse code to an AST with the current compiler flags active.
101 """Parse code to an AST with the current compiler flags active.
@@ -153,6 +157,10 b' class CachingCompiler(codeop.Compile):'
153 raw_code = transformed_code
157 raw_code = transformed_code
154
158
155 name = self.get_code_name(raw_code, transformed_code, number)
159 name = self.get_code_name(raw_code, transformed_code, number)
160
161 # Save the execution count
162 self._filename_map[name] = number
163
156 entry = (
164 entry = (
157 len(transformed_code),
165 len(transformed_code),
158 time.time(),
166 time.time(),
@@ -160,7 +160,7 b' def _format_traceback_lines(lines, Colors, has_colors, lvals):'
160 else:
160 else:
161 num = '%*s' % (numbers_width, lineno)
161 num = '%*s' % (numbers_width, lineno)
162 start_color = Colors.lineno
162 start_color = Colors.lineno
163
163
164 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
164 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
165
165
166 res.append(line)
166 res.append(line)
@@ -300,7 +300,7 b' class ListTB(TBTools):'
300
300
301 Calling requires 3 arguments: (etype, evalue, elist)
301 Calling requires 3 arguments: (etype, evalue, elist)
302 as would be obtained by::
302 as would be obtained by::
303
303
304 etype, evalue, tb = sys.exc_info()
304 etype, evalue, tb = sys.exc_info()
305 if tb:
305 if tb:
306 elist = traceback.extract_tb(tb)
306 elist = traceback.extract_tb(tb)
@@ -581,25 +581,31 b' class VerboseTB(TBTools):'
581 Colors = self.Colors # just a shorthand + quicker name lookup
581 Colors = self.Colors # just a shorthand + quicker name lookup
582 ColorsNormal = Colors.Normal # used a lot
582 ColorsNormal = Colors.Normal # used a lot
583
583
584
585
586 if isinstance(frame_info, stack_data.RepeatedFrames):
584 if isinstance(frame_info, stack_data.RepeatedFrames):
587 return ' %s[... skipping similar frames: %s]%s\n' % (
585 return ' %s[... skipping similar frames: %s]%s\n' % (
588 Colors.excName, frame_info.description, ColorsNormal)
586 Colors.excName, frame_info.description, ColorsNormal)
589
587
588 file = frame_info.filename
589
590 ipinst = get_ipython()
591 if ipinst is not None and file in ipinst.compile._filename_map:
592 file = "[%s]" % ipinst.compile._filename_map[file]
593 tpl_link = "In %s%%s%s," % (Colors.filenameEm, ColorsNormal)
594 else:
595 file = util_path.compress_user(
596 py3compat.cast_unicode(file, util_path.fs_encoding)
597 )
598 tpl_link = "File %s%%s%s," % (Colors.filenameEm, ColorsNormal)
599
590 indent = ' ' * INDENT_SIZE
600 indent = ' ' * INDENT_SIZE
591 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
601 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
592 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
593 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
602 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
594 ColorsNormal)
603 ColorsNormal)
595 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
604 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
596 (Colors.vName, Colors.valEm, ColorsNormal)
605 (Colors.vName, Colors.valEm, ColorsNormal)
597 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
598 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
606 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
599
607
600 file = frame_info.filename
608 link = tpl_link % file
601 file = py3compat.cast_unicode(file, util_path.fs_encoding)
602 link = tpl_link % util_path.compress_user(file)
603 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
609 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
604
610
605 func = frame_info.executing.code_qualname()
611 func = frame_info.executing.code_qualname()
General Comments 0
You need to be logged in to leave comments. Login now