##// END OF EJS Templates
i1673 implementation of py3 proper error handling...
Justyna Ilczuk -
r17157:552f2a77
parent child
Show More
@@ -1735,7 +1735,7 class InteractiveShell(SingletonConfigurable):
1735 This hook should be used sparingly, only in places which are not likely
1735 This hook should be used sparingly, only in places which are not likely
1736 to be true IPython errors.
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 def _get_exc_info(self, exc_tuple=None):
1740 def _get_exc_info(self, exc_tuple=None):
1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
@@ -1776,7 +1776,7 class InteractiveShell(SingletonConfigurable):
1776 """
1776 """
1777 self.write_err("UsageError: %s" % exc)
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 exception_only=False):
1780 exception_only=False):
1781 """Display the exception that just occurred.
1781 """Display the exception that just occurred.
1782
1782
@@ -2918,10 +2918,9 class InteractiveShell(SingletonConfigurable):
2918 False : successful execution.
2918 False : successful execution.
2919 True : an error occurred.
2919 True : an error occurred.
2920 """
2920 """
2921
2922 # Set our own excepthook in case the user code tries to call it
2921 # Set our own excepthook in case the user code tries to call it
2923 # directly, so that the IPython crash handler doesn't get triggered
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 # we save the original sys.excepthook in the instance, in case config
2925 # we save the original sys.excepthook in the instance, in case config
2927 # code (such as magics) needs access to it.
2926 # code (such as magics) needs access to it.
@@ -2939,8 +2938,8 class InteractiveShell(SingletonConfigurable):
2939 self.showtraceback(exception_only=True)
2938 self.showtraceback(exception_only=True)
2940 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2939 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2941 except self.custom_exceptions:
2940 except self.custom_exceptions:
2942 etype,value,tb = sys.exc_info()
2941 etype, value, tb = sys.exc_info()
2943 self.CustomTB(etype,value,tb)
2942 self.CustomTB(etype, value, tb)
2944 except:
2943 except:
2945 self.showtraceback()
2944 self.showtraceback()
2946 else:
2945 else:
@@ -74,10 +74,10 Inheritance diagram:
74
74
75 # *****************************************************************************
75 # *****************************************************************************
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
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
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
80 # the file COPYING, distributed as part of this software.
81 #*****************************************************************************
81 #*****************************************************************************
82
82
83 from __future__ import unicode_literals
83 from __future__ import unicode_literals
@@ -262,7 +262,6 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
262 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
262 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
263
263
264 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
264 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
265
266 # If the error is at the console, don't build any context, since it would
265 # If the error is at the console, don't build any context, since it would
267 # otherwise produce 5 blank lines printed out (there is no file at the
266 # otherwise produce 5 blank lines printed out (there is no file at the
268 # console)
267 # console)
@@ -274,6 +273,15 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
274 except IndexError:
273 except IndexError:
275 pass
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 aux = traceback.extract_tb(etb)
285 aux = traceback.extract_tb(etb)
278 assert len(records) == len(aux)
286 assert len(records) == len(aux)
279 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
287 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
@@ -516,7 +524,7 class ListTB(TBTools):
516 ## out_list.append(lines[-1])
524 ## out_list.append(lines[-1])
517
525
518 # This means it was indenting everything but the last line by a little
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 # can restore it.
528 # can restore it.
521
529
522 return out_list
530 return out_list
@@ -556,7 +564,6 class ListTB(TBTools):
556 item += '%s %s%s\n' % (Colors.line, line.strip(),
564 item += '%s %s%s\n' % (Colors.line, line.strip(),
557 Colors.Normal)
565 Colors.Normal)
558 list.append(item)
566 list.append(item)
559 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
560 return list
567 return list
561
568
562 def _format_exception_only(self, etype, value):
569 def _format_exception_only(self, etype, value):
@@ -582,7 +589,6 class ListTB(TBTools):
582 else:
589 else:
583 if issubclass(etype, SyntaxError):
590 if issubclass(etype, SyntaxError):
584 have_filedata = True
591 have_filedata = True
585 #print 'filename is',filename # dbg
586 if not value.filename: value.filename = "<string>"
592 if not value.filename: value.filename = "<string>"
587 if value.lineno:
593 if value.lineno:
588 lineno = value.lineno
594 lineno = value.lineno
@@ -697,107 +703,14 class VerboseTB(TBTools):
697 check_cache = linecache.checkcache
703 check_cache = linecache.checkcache
698 self.check_cache = check_cache
704 self.check_cache = check_cache
699
705
700 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
706 def format_records(self, records):
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
711 Colors = self.Colors # just a shorthand + quicker name lookup
707 Colors = self.Colors # just a shorthand + quicker name lookup
712 ColorsNormal = Colors.Normal # used a lot
708 ColorsNormal = Colors.Normal # used a lot
713 col_scheme = self.color_scheme_table.active_scheme_name
709 col_scheme = self.color_scheme_table.active_scheme_name
714 indent = ' ' * INDENT_SIZE
710 indent = ' ' * INDENT_SIZE
715 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
711 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
716 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
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 frames = []
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 # build some color string templates outside these nested loops
714 # build some color string templates outside these nested loops
802 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
715 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
803 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
716 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
@@ -808,11 +721,11 class VerboseTB(TBTools):
808 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
721 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
809 Colors.vName, ColorsNormal)
722 Colors.vName, ColorsNormal)
810 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
723 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
724
811 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
725 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
812 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
726 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
813 ColorsNormal)
727 ColorsNormal)
814
728
815 # now, loop over all records printing context and info
816 abspath = os.path.abspath
729 abspath = os.path.abspath
817 for frame, file, lnum, func, lines, index in records:
730 for frame, file, lnum, func, lines, index in records:
818 #print '*** record:',file,lnum,func,lines,index # dbg
731 #print '*** record:',file,lnum,func,lines,index # dbg
@@ -820,7 +733,7 class VerboseTB(TBTools):
820 file = '?'
733 file = '?'
821 elif not (file.startswith(str("<")) and file.endswith(str(">"))):
734 elif not (file.startswith(str("<")) and file.endswith(str(">"))):
822 # Guess that filenames like <string> aren't real filenames, so
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 try:
737 try:
825 file = abspath(file)
738 file = abspath(file)
826 except OSError:
739 except OSError:
@@ -953,6 +866,47 class VerboseTB(TBTools):
953 _format_traceback_lines(lnum, index, lines, Colors, lvals,
866 _format_traceback_lines(lnum, index, lines, Colors, lvals,
954 col_scheme))))
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 # Get (safely) a string form of the exception info
910 # Get (safely) a string form of the exception info
957 try:
911 try:
958 etype_str, evalue_str = map(str, (etype, evalue))
912 etype_str, evalue_str = map(str, (etype, evalue))
@@ -961,38 +915,119 class VerboseTB(TBTools):
961 etype, evalue = str, sys.exc_info()[:2]
915 etype, evalue = str, sys.exc_info()[:2]
962 etype_str, evalue_str = map(str, (etype, evalue))
916 etype_str, evalue_str = map(str, (etype, evalue))
963 # ... and format it
917 # ... and format it
964 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
918 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
965 ColorsNormal, py3compat.cast_unicode(evalue_str))]
919 colorsnormal, py3compat.cast_unicode(evalue_str))]
920
966 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
921 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
967 try:
922 try:
968 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
923 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
969 except:
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 # when dir() is called on it. We do the best we can to report
926 # when dir() is called on it. We do the best we can to report
972 # the problem and continue
927 # the problem and continue
973 _m = '%sException reporting error (object with broken dir())%s:'
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 etype_str, evalue_str = map(str, sys.exc_info()[:2])
930 etype_str, evalue_str = map(str, sys.exc_info()[:2])
976 exception.append('%s%s%s: %s' % (Colors.excName, etype_str,
931 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
977 ColorsNormal, py3compat.cast_unicode(evalue_str)))
932 colorsnormal, py3compat.cast_unicode(evalue_str)))
978 names = []
933 names = []
979 for name in names:
934 for name in names:
980 value = text_repr(getattr(evalue, name))
935 value = text_repr(getattr(evalue, name))
981 exception.append('\n%s%s = %s' % (indent, name, value))
936 exception.append('\n%s%s = %s' % (indent, name, value))
937 return exception
982
938
983 # vds: >>
939 def get_records(self, etb, number_of_lines_of_context, tb_offset):
984 if records:
940 try:
985 filepath, lnum = records[-1][1:3]
941 # Try the default getinnerframes and Alex's: Alex's fixes some
986 #print "file:", str(file), "linenb", str(lnum) # dbg
942 # problems, but it generates empty tracebacks for console errors
987 filepath = os.path.abspath(filepath)
943 # (5 blanks lines) where none should be returned.
988 ipinst = get_ipython()
944 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
989 if ipinst is not None:
945 except:
990 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
946
991 # vds: <<
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
958 def get_exception_from_context(self, evalue):
994 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
959 if hasattr(evalue, '__context__'): # and not evalue.__suppress_context__:
995 return [head] + frames + [''.join(exception[0])]
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 def debugger(self, force=False):
1032 def debugger(self, force=False):
998 """Call up the pdb debugger if desired, always clean up the tb
1033 """Call up the pdb debugger if desired, always clean up the tb
@@ -1100,13 +1135,13 class FormattedTB(VerboseTB, ListTB):
1100 else:
1135 else:
1101 return None
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 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1139 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1105 mode = self.mode
1140 mode = self.mode
1106 if mode in self.verbose_modes:
1141 if mode in self.verbose_modes:
1107 # Verbose modes need a full traceback
1142 # Verbose modes need a full traceback
1108 return VerboseTB.structured_traceback(
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 else:
1146 else:
1112 # We must check the source cache because otherwise we can print
1147 # We must check the source cache because otherwise we can print
@@ -1115,7 +1150,7 class FormattedTB(VerboseTB, ListTB):
1115 # Now we can extract and format the exception
1150 # Now we can extract and format the exception
1116 elist = self._extract_tb(tb)
1151 elist = self._extract_tb(tb)
1117 return ListTB.structured_traceback(
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 def stb2text(self, stb):
1156 def stb2text(self, stb):
@@ -1129,7 +1164,7 class FormattedTB(VerboseTB, ListTB):
1129 If mode is not specified, cycles through the available modes."""
1164 If mode is not specified, cycles through the available modes."""
1130
1165
1131 if not mode:
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 len(self.valid_modes)
1168 len(self.valid_modes)
1134 self.mode = self.valid_modes[new_idx]
1169 self.mode = self.valid_modes[new_idx]
1135 elif mode not in self.valid_modes:
1170 elif mode not in self.valid_modes:
@@ -1193,12 +1228,12 class AutoFormattedTB(FormattedTB):
1193 print("\nKeyboardInterrupt")
1228 print("\nKeyboardInterrupt")
1194
1229
1195 def structured_traceback(self, etype=None, value=None, tb=None,
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 if etype is None:
1232 if etype is None:
1198 etype, value, tb = sys.exc_info()
1233 etype, value, tb = sys.exc_info()
1199 self.tb = tb
1234 self.tb = tb
1200 return FormattedTB.structured_traceback(
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 class SyntaxTB(ListTB):
1221
1256
1222 def __call__(self, etype, value, elist):
1257 def __call__(self, etype, value, elist):
1223 self.last_syntax_error = value
1258 self.last_syntax_error = value
1259
1224 ListTB.__call__(self, etype, value, elist)
1260 ListTB.__call__(self, etype, value, elist)
1225
1261
1226 def structured_traceback(self, etype, value, elist, tb_offset=None,
1262 def structured_traceback(self, etype, value, elist, tb_offset=None,
@@ -1249,7 +1285,48 class SyntaxTB(ListTB):
1249 return ''.join(stb)
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 # module testing (minimal)
1330 # module testing (minimal)
1254 if __name__ == "__main__":
1331 if __name__ == "__main__":
1255 def spam(c, d_e):
1332 def spam(c, d_e):
General Comments 0
You need to be logged in to leave comments. Login now