##// END OF EJS Templates
i1673 implementation of py3 proper error handling...
Justyna Ilczuk -
Show More
@@ -1735,7 +1735,7 b' class InteractiveShell(SingletonConfigurable):'
1735 1735 This hook should be used sparingly, only in places which are not likely
1736 1736 to be true IPython errors.
1737 1737 """
1738 self.showtraceback((etype,value,tb),tb_offset=0)
1738 self.showtraceback((etype, value, tb), tb_offset=0)
1739 1739
1740 1740 def _get_exc_info(self, exc_tuple=None):
1741 1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
@@ -1776,7 +1776,7 b' class InteractiveShell(SingletonConfigurable):'
1776 1776 """
1777 1777 self.write_err("UsageError: %s" % exc)
1778 1778
1779 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1779 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1780 1780 exception_only=False):
1781 1781 """Display the exception that just occurred.
1782 1782
@@ -2918,10 +2918,9 b' class InteractiveShell(SingletonConfigurable):'
2918 2918 False : successful execution.
2919 2919 True : an error occurred.
2920 2920 """
2921
2922 2921 # Set our own excepthook in case the user code tries to call it
2923 2922 # directly, so that the IPython crash handler doesn't get triggered
2924 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2923 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2925 2924
2926 2925 # we save the original sys.excepthook in the instance, in case config
2927 2926 # code (such as magics) needs access to it.
@@ -2939,8 +2938,8 b' class InteractiveShell(SingletonConfigurable):'
2939 2938 self.showtraceback(exception_only=True)
2940 2939 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2941 2940 except self.custom_exceptions:
2942 etype,value,tb = sys.exc_info()
2943 self.CustomTB(etype,value,tb)
2941 etype, value, tb = sys.exc_info()
2942 self.CustomTB(etype, value, tb)
2944 2943 except:
2945 2944 self.showtraceback()
2946 2945 else:
@@ -74,10 +74,10 b' Inheritance diagram:'
74 74
75 75 # *****************************************************************************
76 76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
78 78 #
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
81 81 #*****************************************************************************
82 82
83 83 from __future__ import unicode_literals
@@ -262,7 +262,6 b' def _fixed_getinnerframes(etb, context=1, tb_offset=0):'
262 262 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
263 263
264 264 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
265
266 265 # If the error is at the console, don't build any context, since it would
267 266 # otherwise produce 5 blank lines printed out (there is no file at the
268 267 # console)
@@ -274,6 +273,15 b' def _fixed_getinnerframes(etb, context=1, tb_offset=0):'
274 273 except IndexError:
275 274 pass
276 275
276 # we don't want to truncate too much
277 # when normal exception occurs there are two records usually
278 # first is from ipython and has pre_hooks information and so on
279 # however sometimes we have tracebacks without additional ipython information
280 # for example from nested traceback (python3 exceptions have __context__ which
281 # stores information about previous exceptions)
282 if tb_offset >= len(records):
283 tb_offset = len(records) - 2
284
277 285 aux = traceback.extract_tb(etb)
278 286 assert len(records) == len(aux)
279 287 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
@@ -516,7 +524,7 b' class ListTB(TBTools):'
516 524 ## out_list.append(lines[-1])
517 525
518 526 # This means it was indenting everything but the last line by a little
519 # bit. I've disabled this for now, but if we see ugliness somewhre we
527 # bit. I've disabled this for now, but if we see ugliness somewhere we
520 528 # can restore it.
521 529
522 530 return out_list
@@ -556,7 +564,6 b' class ListTB(TBTools):'
556 564 item += '%s %s%s\n' % (Colors.line, line.strip(),
557 565 Colors.Normal)
558 566 list.append(item)
559 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
560 567 return list
561 568
562 569 def _format_exception_only(self, etype, value):
@@ -582,7 +589,6 b' class ListTB(TBTools):'
582 589 else:
583 590 if issubclass(etype, SyntaxError):
584 591 have_filedata = True
585 #print 'filename is',filename # dbg
586 592 if not value.filename: value.filename = "<string>"
587 593 if value.lineno:
588 594 lineno = value.lineno
@@ -697,107 +703,14 b' class VerboseTB(TBTools):'
697 703 check_cache = linecache.checkcache
698 704 self.check_cache = check_cache
699 705
700 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
701 context=5):
702 """Return a nice text document describing the traceback."""
703
704 tb_offset = self.tb_offset if tb_offset is None else tb_offset
705
706 # some locals
707 try:
708 etype = etype.__name__
709 except AttributeError:
710 pass
706 def format_records(self, records):
711 707 Colors = self.Colors # just a shorthand + quicker name lookup
712 708 ColorsNormal = Colors.Normal # used a lot
713 709 col_scheme = self.color_scheme_table.active_scheme_name
714 710 indent = ' ' * INDENT_SIZE
715 711 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
716 712 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
717 exc = '%s%s%s' % (Colors.excName, etype, ColorsNormal)
718
719 # some internal-use functions
720 def text_repr(value):
721 """Hopefully pretty robust repr equivalent."""
722 # this is pretty horrible but should always return *something*
723 try:
724 return pydoc.text.repr(value)
725 except KeyboardInterrupt:
726 raise
727 except:
728 try:
729 return repr(value)
730 except KeyboardInterrupt:
731 raise
732 except:
733 try:
734 # all still in an except block so we catch
735 # getattr raising
736 name = getattr(value, '__name__', None)
737 if name:
738 # ick, recursion
739 return text_repr(name)
740 klass = getattr(value, '__class__', None)
741 if klass:
742 return '%s instance' % text_repr(klass)
743 except KeyboardInterrupt:
744 raise
745 except:
746 return 'UNRECOVERABLE REPR FAILURE'
747
748 def eqrepr(value, repr=text_repr):
749 return '=%s' % repr(value)
750
751 def nullrepr(value, repr=text_repr):
752 return ''
753
754 # meat of the code begins
755 try:
756 etype = etype.__name__
757 except AttributeError:
758 pass
759
760 if self.long_header:
761 # Header with the exception type, python version, and date
762 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
763 date = time.ctime(time.time())
764
765 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-' * 75, ColorsNormal,
766 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
767 pyver, date.rjust(75) )
768 head += "\nA problem occured executing Python code. Here is the sequence of function" \
769 "\ncalls leading up to the error, with the most recent (innermost) call last."
770 else:
771 # Simplified header
772 head = '%s%s%s\n%s%s' % (Colors.topline, '-' * 75, ColorsNormal, exc,
773 'Traceback (most recent call last)'. \
774 rjust(75 - len(str(etype))) )
775 713 frames = []
776 # Flush cache before calling inspect. This helps alleviate some of the
777 # problems with python 2.3's inspect.py.
778 ##self.check_cache()
779 # Drop topmost frames if requested
780 try:
781 # Try the default getinnerframes and Alex's: Alex's fixes some
782 # problems, but it generates empty tracebacks for console errors
783 # (5 blanks lines) where none should be returned.
784 #records = inspect.getinnerframes(etb, context)[tb_offset:]
785 #print 'python records:', records # dbg
786 records = _fixed_getinnerframes(etb, context, tb_offset)
787 #print 'alex records:', records # dbg
788 except:
789
790 # FIXME: I've been getting many crash reports from python 2.3
791 # users, traceable to inspect.py. If I can find a small test-case
792 # to reproduce this, I should either write a better workaround or
793 # file a bug report against inspect (if that's the real problem).
794 # So far, I haven't been able to find an isolated example to
795 # reproduce the problem.
796 inspect_error()
797 traceback.print_exc(file=self.ostream)
798 info('\nUnfortunately, your original traceback can not be constructed.\n')
799 return ''
800
801 714 # build some color string templates outside these nested loops
802 715 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
803 716 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
@@ -808,11 +721,11 b' class VerboseTB(TBTools):'
808 721 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
809 722 Colors.vName, ColorsNormal)
810 723 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
724
811 725 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
812 726 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
813 727 ColorsNormal)
814 728
815 # now, loop over all records printing context and info
816 729 abspath = os.path.abspath
817 730 for frame, file, lnum, func, lines, index in records:
818 731 #print '*** record:',file,lnum,func,lines,index # dbg
@@ -820,7 +733,7 b' class VerboseTB(TBTools):'
820 733 file = '?'
821 734 elif not (file.startswith(str("<")) and file.endswith(str(">"))):
822 735 # Guess that filenames like <string> aren't real filenames, so
823 # don't call abspath on them.
736 # don't call abspath on them.
824 737 try:
825 738 file = abspath(file)
826 739 except OSError:
@@ -953,6 +866,47 b' class VerboseTB(TBTools):'
953 866 _format_traceback_lines(lnum, index, lines, Colors, lvals,
954 867 col_scheme))))
955 868
869 return frames
870
871 def prepare_chained_exception_message(self, cause):
872 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
873 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
874
875 colors = self.Colors # just a shorthand + quicker name lookup
876 colorsnormal = colors.Normal # used a lot
877 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
878 if cause:
879 message = [[head, direct_cause]]
880 else:
881 message = [[head, exception_during_handling]]
882 return message
883
884 def prepare_header(self, etype, long_version=False):
885 colors = self.Colors # just a shorthand + quicker name lookup
886 colorsnormal = colors.Normal # used a lot
887 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
888 if long_version:
889 # Header with the exception type, python version, and date
890 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
891 date = time.ctime(time.time())
892
893 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
894 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
895 pyver, date.rjust(75) )
896 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
897 "\ncalls leading up to the error, with the most recent (innermost) call last."
898 else:
899 # Simplified header
900 head = '%s%s%s\n%s%s' % (colors.topline, '-' * 75, colorsnormal, exc,
901 'Traceback (most recent call last)'. \
902 rjust(75 - len(str(etype))) )
903
904 return head
905
906 def format_exception(self, etype, evalue):
907 colors = self.Colors # just a shorthand + quicker name lookup
908 colorsnormal = colors.Normal # used a lot
909 indent = ' ' * INDENT_SIZE
956 910 # Get (safely) a string form of the exception info
957 911 try:
958 912 etype_str, evalue_str = map(str, (etype, evalue))
@@ -961,38 +915,119 b' class VerboseTB(TBTools):'
961 915 etype, evalue = str, sys.exc_info()[:2]
962 916 etype_str, evalue_str = map(str, (etype, evalue))
963 917 # ... and format it
964 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
965 ColorsNormal, py3compat.cast_unicode(evalue_str))]
918 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
919 colorsnormal, py3compat.cast_unicode(evalue_str))]
920
966 921 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
967 922 try:
968 923 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
969 924 except:
970 # Every now and then, an object with funny inernals blows up
925 # Every now and then, an object with funny internals blows up
971 926 # when dir() is called on it. We do the best we can to report
972 927 # the problem and continue
973 928 _m = '%sException reporting error (object with broken dir())%s:'
974 exception.append(_m % (Colors.excName, ColorsNormal))
929 exception.append(_m % (colors.excName, colorsnormal))
975 930 etype_str, evalue_str = map(str, sys.exc_info()[:2])
976 exception.append('%s%s%s: %s' % (Colors.excName, etype_str,
977 ColorsNormal, py3compat.cast_unicode(evalue_str)))
931 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
932 colorsnormal, py3compat.cast_unicode(evalue_str)))
978 933 names = []
979 934 for name in names:
980 935 value = text_repr(getattr(evalue, name))
981 936 exception.append('\n%s%s = %s' % (indent, name, value))
937 return exception
982 938
983 # vds: >>
984 if records:
985 filepath, lnum = records[-1][1:3]
986 #print "file:", str(file), "linenb", str(lnum) # dbg
987 filepath = os.path.abspath(filepath)
988 ipinst = get_ipython()
989 if ipinst is not None:
990 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
991 # vds: <<
939 def get_records(self, etb, number_of_lines_of_context, tb_offset):
940 try:
941 # Try the default getinnerframes and Alex's: Alex's fixes some
942 # problems, but it generates empty tracebacks for console errors
943 # (5 blanks lines) where none should be returned.
944 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
945 except:
946
947 # FIXME: I've been getting many crash reports from python 2.3
948 # users, traceable to inspect.py. If I can find a small test-case
949 # to reproduce this, I should either write a better workaround or
950 # file a bug report against inspect (if that's the real problem).
951 # So far, I haven't been able to find an isolated example to
952 # reproduce the problem.
953 inspect_error()
954 traceback.print_exc(file=self.ostream)
955 info('\nUnfortunately, your original traceback can not be constructed.\n')
956 return None
992 957
993 # return all our info assembled as a single string
994 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
995 return [head] + frames + [''.join(exception[0])]
958 def get_exception_from_context(self, evalue):
959 if hasattr(evalue, '__context__'): # and not evalue.__suppress_context__:
960 context = evalue.__context__
961 if not context:
962 return None
963 else:
964 exception_traceback = context.__traceback__
965 exception_type = context.__class__.__name__
966 return exception_type, context, exception_traceback
967 else:
968 return None
969
970 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
971 number_of_lines_of_context=5):
972 """Return a nice text document describing the traceback."""
973 tb_offset = self.tb_offset if tb_offset is None else tb_offset
974
975 # some locals
976 try:
977 etype = etype.__name__
978 except AttributeError:
979 pass
980
981 structured_traceback_parts = []
982
983 exceptions = []
984 current_exception_value = evalue
985 if py3compat.PY3:
986 while current_exception_value:
987 head = self.prepare_header(etype, self.long_header)
988 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
989
990 frames = self.format_records(records)
991 if records is None:
992 return ""
993
994 formatted_exception = self.format_exception(etype, current_exception_value)
995 if records:
996 filepath, lnum = records[-1][1:3]
997 filepath = os.path.abspath(filepath)
998 ipinst = get_ipython()
999 if ipinst is not None:
1000 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1001
1002 exceptions += [[head] + frames + [''.join(formatted_exception[0])]]
1003
1004 exception = self.get_exception_from_context(current_exception_value)
1005 if exception:
1006 exceptions += self.prepare_chained_exception_message(current_exception_value.__cause__)
1007 etype, current_exception_value, etb = exception
1008 else:
1009 break
1010
1011 for exception in reversed(exceptions):
1012 structured_traceback_parts += exception
1013 else:
1014 head = self.prepare_header(etype, self.long_header)
1015 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1016
1017 frames = self.format_records(records)
1018 if records is None:
1019 return ""
1020
1021 exception = self.format_exception(etype, evalue)
1022 if records:
1023 filepath, lnum = records[-1][1:3]
1024 filepath = os.path.abspath(filepath)
1025 ipinst = get_ipython()
1026 if ipinst is not None:
1027 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1028 structured_traceback_parts.append([head] + frames + [''.join(exception[0])])
1029
1030 return structured_traceback_parts
996 1031
997 1032 def debugger(self, force=False):
998 1033 """Call up the pdb debugger if desired, always clean up the tb
@@ -1100,13 +1135,13 b' class FormattedTB(VerboseTB, ListTB):'
1100 1135 else:
1101 1136 return None
1102 1137
1103 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1138 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1104 1139 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1105 1140 mode = self.mode
1106 1141 if mode in self.verbose_modes:
1107 1142 # Verbose modes need a full traceback
1108 1143 return VerboseTB.structured_traceback(
1109 self, etype, value, tb, tb_offset, context
1144 self, etype, value, tb, tb_offset, number_of_lines_of_context
1110 1145 )
1111 1146 else:
1112 1147 # We must check the source cache because otherwise we can print
@@ -1115,7 +1150,7 b' class FormattedTB(VerboseTB, ListTB):'
1115 1150 # Now we can extract and format the exception
1116 1151 elist = self._extract_tb(tb)
1117 1152 return ListTB.structured_traceback(
1118 self, etype, value, elist, tb_offset, context
1153 self, etype, value, elist, tb_offset, number_of_lines_of_context
1119 1154 )
1120 1155
1121 1156 def stb2text(self, stb):
@@ -1129,7 +1164,7 b' class FormattedTB(VerboseTB, ListTB):'
1129 1164 If mode is not specified, cycles through the available modes."""
1130 1165
1131 1166 if not mode:
1132 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1167 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1133 1168 len(self.valid_modes)
1134 1169 self.mode = self.valid_modes[new_idx]
1135 1170 elif mode not in self.valid_modes:
@@ -1193,12 +1228,12 b' class AutoFormattedTB(FormattedTB):'
1193 1228 print("\nKeyboardInterrupt")
1194 1229
1195 1230 def structured_traceback(self, etype=None, value=None, tb=None,
1196 tb_offset=None, context=5):
1231 tb_offset=None, number_of_lines_of_context=5):
1197 1232 if etype is None:
1198 1233 etype, value, tb = sys.exc_info()
1199 1234 self.tb = tb
1200 1235 return FormattedTB.structured_traceback(
1201 self, etype, value, tb, tb_offset, context)
1236 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1202 1237
1203 1238
1204 1239 #---------------------------------------------------------------------------
@@ -1221,6 +1256,7 b' class SyntaxTB(ListTB):'
1221 1256
1222 1257 def __call__(self, etype, value, elist):
1223 1258 self.last_syntax_error = value
1259
1224 1260 ListTB.__call__(self, etype, value, elist)
1225 1261
1226 1262 def structured_traceback(self, etype, value, elist, tb_offset=None,
@@ -1249,7 +1285,48 b' class SyntaxTB(ListTB):'
1249 1285 return ''.join(stb)
1250 1286
1251 1287
1288 # some internal-use functions
1289 def text_repr(value):
1290 """Hopefully pretty robust repr equivalent."""
1291 # this is pretty horrible but should always return *something*
1292 try:
1293 return pydoc.text.repr(value)
1294 except KeyboardInterrupt:
1295 raise
1296 except:
1297 try:
1298 return repr(value)
1299 except KeyboardInterrupt:
1300 raise
1301 except:
1302 try:
1303 # all still in an except block so we catch
1304 # getattr raising
1305 name = getattr(value, '__name__', None)
1306 if name:
1307 # ick, recursion
1308 return text_repr(name)
1309 klass = getattr(value, '__class__', None)
1310 if klass:
1311 return '%s instance' % text_repr(klass)
1312 except KeyboardInterrupt:
1313 raise
1314 except:
1315 return 'UNRECOVERABLE REPR FAILURE'
1316
1317
1318 def eqrepr(value, repr=text_repr):
1319 return '=%s' % repr(value)
1320
1321
1322 def nullrepr(value, repr=text_repr):
1323 return ''
1324
1325
1326
1327
1252 1328 #----------------------------------------------------------------------------
1329
1253 1330 # module testing (minimal)
1254 1331 if __name__ == "__main__":
1255 1332 def spam(c, d_e):
General Comments 0
You need to be logged in to leave comments. Login now