Show More
@@ -1735,7 +1735,7 b' 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 b' 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 |
|
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 b' 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 b' 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 b' 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 |
# |
|
77 | # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> | |
78 | # |
|
78 | # | |
79 |
# |
|
79 | # Distributed under the terms of the BSD License. The full license is in | |
80 |
# |
|
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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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' % ( |
|
918 | exception = ['%s%s%s: %s' % (colors.excName, etype_str, | |
965 |
|
|
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 % ( |
|
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' % ( |
|
931 | exception.append('%s%s%s: %s' % (colors.excName, etype_str, | |
977 |
|
|
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 |
|
|
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 b' 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 b' 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 b' 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 = ( |
|
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 b' 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 b' 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 b' 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