##// END OF EJS Templates
Improvements to exception handling to transport structured tracebacks....
Fernando Perez -
Show More
@@ -29,6 +29,7 b' import sys'
29 29 import tempfile
30 30 from contextlib import nested
31 31
32 from IPython.config.configurable import Configurable
32 33 from IPython.core import debugger, oinspect
33 34 from IPython.core import history as ipcorehist
34 35 from IPython.core import prefilter
@@ -36,8 +37,8 b' from IPython.core import shadowns'
36 37 from IPython.core import ultratb
37 38 from IPython.core.alias import AliasManager
38 39 from IPython.core.builtin_trap import BuiltinTrap
39 from IPython.config.configurable import Configurable
40 40 from IPython.core.display_trap import DisplayTrap
41 from IPython.core.displayhook import DisplayHook
41 42 from IPython.core.error import UsageError
42 43 from IPython.core.extensions import ExtensionManager
43 44 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
@@ -47,24 +48,22 b' from IPython.core.magic import Magic'
47 48 from IPython.core.payload import PayloadManager
48 49 from IPython.core.plugin import PluginManager
49 50 from IPython.core.prefilter import PrefilterManager
50 from IPython.core.displayhook import DisplayHook
51 import IPython.core.hooks
52 51 from IPython.external.Itpl import ItplNS
53 52 from IPython.utils import PyColorize
53 from IPython.utils import io
54 54 from IPython.utils import pickleshare
55 55 from IPython.utils.doctestreload import doctest_reload
56 from IPython.utils.io import ask_yes_no, rprint
56 57 from IPython.utils.ipstruct import Struct
57 import IPython.utils.io
58 from IPython.utils.io import ask_yes_no
59 58 from IPython.utils.path import get_home_dir, get_ipython_dir, HomeDirError
60 59 from IPython.utils.process import getoutput, getoutputerror
61 60 from IPython.utils.strdispatch import StrDispatch
62 61 from IPython.utils.syspathcontext import prepended_to_syspath
63 62 from IPython.utils.text import num_ini_spaces
63 from IPython.utils.traitlets import (Int, Str, CBool, CaselessStrEnum, Enum,
64 List, Unicode, Instance, Type)
64 65 from IPython.utils.warn import warn, error, fatal
65 from IPython.utils.traitlets import (
66 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode, Instance, Type
67 )
66 import IPython.core.hooks
68 67
69 68 # from IPython.utils import growl
70 69 # growl.start("IPython")
@@ -430,12 +429,12 b' class InteractiveShell(Configurable, Magic):'
430 429 def init_io(self):
431 430 import IPython.utils.io
432 431 if sys.platform == 'win32' and self.has_readline:
433 Term = IPython.utils.io.IOTerm(
432 Term = io.IOTerm(
434 433 cout=self.readline._outputfile,cerr=self.readline._outputfile
435 434 )
436 435 else:
437 Term = IPython.utils.io.IOTerm()
438 IPython.utils.io.Term = Term
436 Term = io.IOTerm()
437 io.Term = Term
439 438
440 439 def init_prompts(self):
441 440 # TODO: This is a pass for now because the prompts are managed inside
@@ -1181,7 +1180,7 b' class InteractiveShell(Configurable, Magic):'
1181 1180 # Set the exception mode
1182 1181 self.InteractiveTB.set_mode(mode=self.xmode)
1183 1182
1184 def set_custom_exc(self,exc_tuple,handler):
1183 def set_custom_exc(self, exc_tuple, handler):
1185 1184 """set_custom_exc(exc_tuple,handler)
1186 1185
1187 1186 Set a custom exception handler, which will be called if any of the
@@ -1198,7 +1197,12 b' class InteractiveShell(Configurable, Magic):'
1198 1197 exc_tuple == (MyCustomException,)
1199 1198
1200 1199 - handler: this must be defined as a function with the following
1201 basic interface: def my_handler(self,etype,value,tb).
1200 basic interface::
1201
1202 def my_handler(self, etype, value, tb, tb_offset=None)
1203 ...
1204 # The return value must be
1205 return structured_traceback
1202 1206
1203 1207 This will be made into an instance method (via new.instancemethod)
1204 1208 of IPython itself, and it will be called if any of the exceptions
@@ -1272,7 +1276,7 b' class InteractiveShell(Configurable, Magic):'
1272 1276 etype, value, tb = sys.last_type, sys.last_value, \
1273 1277 sys.last_traceback
1274 1278 else:
1275 self.write('No traceback available to show.\n')
1279 self.write_err('No traceback available to show.\n')
1276 1280 return
1277 1281
1278 1282 if etype is SyntaxError:
@@ -1291,22 +1295,39 b' class InteractiveShell(Configurable, Magic):'
1291 1295 sys.last_traceback = tb
1292 1296
1293 1297 if etype in self.custom_exceptions:
1294 self.CustomTB(etype,value,tb)
1298 # FIXME: Old custom traceback objects may just return a
1299 # string, in that case we just put it into a list
1300 stb = self.CustomTB(etype, value, tb, tb_offset)
1301 if isinstance(ctb, basestring):
1302 stb = [stb]
1295 1303 else:
1296 1304 if exception_only:
1297 m = ('An exception has occurred, use %tb to see the '
1298 'full traceback.')
1299 print m
1300 self.InteractiveTB.show_exception_only(etype, value)
1305 stb = ['An exception has occurred, use %tb to see '
1306 'the full traceback.']
1307 stb.extend(self.InteractiveTB.get_exception_only(etype,
1308 value))
1301 1309 else:
1302 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1310 stb = self.InteractiveTB.structured_traceback(etype,
1311 value, tb, tb_offset=tb_offset)
1312 # FIXME: the pdb calling should be done by us, not by
1313 # the code computing the traceback.
1303 1314 if self.InteractiveTB.call_pdb:
1304 1315 # pdb mucks up readline, fix it back
1305 1316 self.set_completer()
1306
1317
1318 # Actually show the traceback
1319 self._showtraceback(etype, value, stb)
1320
1307 1321 except KeyboardInterrupt:
1308 self.write("\nKeyboardInterrupt\n")
1309
1322 self.write_err("\nKeyboardInterrupt\n")
1323
1324 def _showtraceback(self, etype, evalue, stb):
1325 """Actually show a traceback.
1326
1327 Subclasses may override this method to put the traceback on a different
1328 place, like a side channel.
1329 """
1330 self.write_err('\n'.join(stb))
1310 1331
1311 1332 def showsyntaxerror(self, filename=None):
1312 1333 """Display the syntax error that just occurred.
@@ -1339,7 +1360,8 b' class InteractiveShell(Configurable, Magic):'
1339 1360 except:
1340 1361 # If that failed, assume SyntaxError is a string
1341 1362 value = msg, (filename, lineno, offset, line)
1342 self.SyntaxTB(etype,value,[])
1363 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1364 self._showtraceback(etype, value, stb)
1343 1365
1344 1366 #-------------------------------------------------------------------------
1345 1367 # Things related to tab completion
@@ -1792,7 +1814,7 b' class InteractiveShell(Configurable, Magic):'
1792 1814 exposes IPython's processing machinery, the given strings can contain
1793 1815 magic calls (%magic), special shell access (!cmd), etc.
1794 1816 """
1795
1817
1796 1818 if isinstance(lines, (list, tuple)):
1797 1819 lines = '\n'.join(lines)
1798 1820
@@ -1912,6 +1934,7 b' class InteractiveShell(Configurable, Magic):'
1912 1934 try:
1913 1935 try:
1914 1936 self.hooks.pre_runcode_hook()
1937 #rprint('Running code') # dbg
1915 1938 exec code_obj in self.user_global_ns, self.user_ns
1916 1939 finally:
1917 1940 # Reset our crash handler in place
@@ -2080,12 +2103,12 b' class InteractiveShell(Configurable, Magic):'
2080 2103 # TODO: This should be removed when Term is refactored.
2081 2104 def write(self,data):
2082 2105 """Write a string to the default output"""
2083 IPython.utils.io.Term.cout.write(data)
2106 io.Term.cout.write(data)
2084 2107
2085 2108 # TODO: This should be removed when Term is refactored.
2086 2109 def write_err(self,data):
2087 2110 """Write a string to the default error output"""
2088 IPython.utils.io.Term.cerr.write(data)
2111 io.Term.cerr.write(data)
2089 2112
2090 2113 def ask_yes_no(self,prompt,default=True):
2091 2114 if self.quiet:
@@ -90,12 +90,12 b' from inspect import getsourcefile, getfile, getmodule,\\'
90 90
91 91 # IPython's own modules
92 92 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython.utils import PyColorize
94 93 from IPython.core import debugger, ipapi
95 94 from IPython.core.display_trap import DisplayTrap
96 95 from IPython.core.excolors import exception_colors
96 from IPython.utils import PyColorize
97 from IPython.utils import io
97 98 from IPython.utils.data import uniq_stable
98 import IPython.utils.io
99 99 from IPython.utils.warn import info, error
100 100
101 101 # Globals
@@ -310,7 +310,7 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
310 310
311 311 #---------------------------------------------------------------------------
312 312 # Module classes
313 class TBTools:
313 class TBTools(object):
314 314 """Basic tools used by all traceback printer classes."""
315 315
316 316 # This attribute us used in globalipapp.py to have stdout used for
@@ -319,6 +319,9 b' class TBTools:'
319 319 # the string 'stdout' which will cause the override to sys.stdout.
320 320 out_stream = None
321 321
322 # Number of frames to skip when reporting tracebacks
323 tb_offset = 0
324
322 325 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
323 326 # Whether to call the interactive pdb debugger after printing
324 327 # tracebacks or not
@@ -357,6 +360,24 b' class TBTools:'
357 360 self.color_scheme_table.set_active_scheme('NoColor')
358 361 self.Colors = self.color_scheme_table.active_colors
359 362
363 def text(self, etype, value, tb, tb_offset=None, context=5):
364 """Return formatted traceback.
365
366 Subclasses may override this if they add extra arguments.
367 """
368 tb_list = self.structured_traceback(etype, value, tb,
369 tb_offset, context)
370 return '\n'.join(tb_list)
371
372 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
373 context=5, mode=None):
374 """Return a list of traceback frames.
375
376 Must be implemented by each class.
377 """
378 raise NotImplementedError()
379
380
360 381 #---------------------------------------------------------------------------
361 382 class ListTB(TBTools):
362 383 """Print traceback information from a traceback list, with optional color.
@@ -381,11 +402,12 b' class ListTB(TBTools):'
381 402 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
382 403
383 404 def __call__(self, etype, value, elist):
384 IPython.utils.io.Term.cout.flush()
385 IPython.utils.io.Term.cerr.write(self.text(etype,value,elist))
386 IPython.utils.io.Term.cerr.write('\n')
405 io.Term.cout.flush()
406 io.Term.cerr.write(self.text(etype, value, elist))
407 io.Term.cerr.write('\n')
387 408
388 def structured_traceback(self, etype, value, elist, context=5):
409 def structured_traceback(self, etype, value, elist, tb_offset=None,
410 context=5):
389 411 """Return a color formatted string with the traceback info.
390 412
391 413 Parameters
@@ -399,28 +421,43 b' class ListTB(TBTools):'
399 421 elist : list
400 422 List of frames, see class docstring for details.
401 423
424 tb_offset : int, optional
425 Number of frames in the traceback to skip. If not given, the
426 instance value is used (set in constructor).
427
428 context : int, optional
429 Number of lines of context information to print.
430
402 431 Returns
403 432 -------
404 433 String with formatted exception.
405 434 """
406
435 tb_offset = self.tb_offset if tb_offset is None else tb_offset
407 436 Colors = self.Colors
408 out_string = []
437 out_list = []
409 438 if elist:
410 out_string.append('Traceback %s(most recent call last)%s:' %
439
440 if tb_offset and len(elist) > tb_offset:
441 elist = elist[tb_offset:]
442
443 out_list.append('Traceback %s(most recent call last)%s:' %
411 444 (Colors.normalEm, Colors.Normal) + '\n')
412 out_string.extend(self._format_list(elist))
413 lines = self._format_exception_only(etype, value)
414 for line in lines[:-1]:
415 out_string.append(" "+line)
416 out_string.append(lines[-1])
417 return out_string
418
419 def text(self, etype, value, elist, context=5):
420 out_string = ListTB.structured_traceback(
421 self, etype, value, elist, context
422 )
423 return ''.join(out_string)
445 out_list.extend(self._format_list(elist))
446 # The exception info should be a single entry in the list.
447 lines = ''.join(self._format_exception_only(etype, value))
448 out_list.append(lines)
449
450 # Note: this code originally read:
451
452 ## for line in lines[:-1]:
453 ## out_list.append(" "+line)
454 ## out_list.append(lines[-1])
455
456 # This means it was indenting everything but the last line by a little
457 # bit. I've disabled this for now, but if we see ugliness somewhre we
458 # can restore it.
459
460 return out_list
424 461
425 462 def _format_list(self, extracted_list):
426 463 """Format a list of traceback entry tuples for printing.
@@ -457,6 +494,7 b' class ListTB(TBTools):'
457 494 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
458 495 Colors.Normal)
459 496 list.append(item)
497 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
460 498 return list
461 499
462 500 def _format_exception_only(self, etype, value):
@@ -528,6 +566,17 b' class ListTB(TBTools):'
528 566
529 567 return list
530 568
569 def get_exception_only(self, etype, value):
570 """Only print the exception type and message, without a traceback.
571
572 Parameters
573 ----------
574 etype : exception type
575 value : exception value
576 """
577 return ListTB.structured_traceback(self, etype, value, [])
578
579
531 580 def show_exception_only(self, etype, value):
532 581 """Only print the exception type and message, without a traceback.
533 582
@@ -541,9 +590,9 b' class ListTB(TBTools):'
541 590 if self.out_stream == 'stdout':
542 591 ostream = sys.stdout
543 592 else:
544 ostream = IPython.utils.io.Term.cerr
593 ostream = io.Term.cerr
545 594 ostream.flush()
546 ostream.write(ListTB.text(self, etype, value, []))
595 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
547 596 ostream.flush()
548 597
549 598 def _some_str(self, value):
@@ -575,9 +624,12 b' class VerboseTB(TBTools):'
575 624 self.long_header = long_header
576 625 self.include_vars = include_vars
577 626
578 def structured_traceback(self, etype, evalue, etb, context=5):
627 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
628 context=5):
579 629 """Return a nice text document describing the traceback."""
580 630
631 tb_offset = self.tb_offset if tb_offset is None else tb_offset
632
581 633 # some locals
582 634 try:
583 635 etype = etype.__name__
@@ -652,9 +704,9 b' class VerboseTB(TBTools):'
652 704 # Try the default getinnerframes and Alex's: Alex's fixes some
653 705 # problems, but it generates empty tracebacks for console errors
654 706 # (5 blanks lines) where none should be returned.
655 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
707 #records = inspect.getinnerframes(etb, context)[tb_offset:]
656 708 #print 'python records:', records # dbg
657 records = _fixed_getinnerframes(etb, context,self.tb_offset)
709 records = _fixed_getinnerframes(etb, context, tb_offset)
658 710 #print 'alex records:', records # dbg
659 711 except:
660 712
@@ -665,7 +717,7 b' class VerboseTB(TBTools):'
665 717 # So far, I haven't been able to find an isolated example to
666 718 # reproduce the problem.
667 719 inspect_error()
668 traceback.print_exc(file=IPython.utils.io.Term.cerr)
720 traceback.print_exc(file=io.Term.cerr)
669 721 info('\nUnfortunately, your original traceback can not be constructed.\n')
670 722 return ''
671 723
@@ -702,7 +754,7 b' class VerboseTB(TBTools):'
702 754 # able to remove this try/except when 2.4 becomes a
703 755 # requirement. Bug details at http://python.org/sf/1005466
704 756 inspect_error()
705 traceback.print_exc(file=IPython.utils.io.Term.cerr)
757 traceback.print_exc(file=io.Term.cerr)
706 758 info("\nIPython's exception reporting continues...\n")
707 759
708 760 if func == '?':
@@ -723,7 +775,7 b' class VerboseTB(TBTools):'
723 775 # and barfs out. At some point I should dig into this one
724 776 # and file a bug report about it.
725 777 inspect_error()
726 traceback.print_exc(file=IPython.utils.io.Term.cerr)
778 traceback.print_exc(file=io.Term.cerr)
727 779 info("\nIPython's exception reporting continues...\n")
728 780 call = tpl_call_fail % func
729 781
@@ -869,13 +921,7 b' class VerboseTB(TBTools):'
869 921 # return all our info assembled as a single string
870 922 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
871 923 return [head] + frames + [''.join(exception[0])]
872
873 def text(self, etype, evalue, etb, context=5):
874 tb_list = VerboseTB.structured_traceback(
875 self, etype, evalue, etb, context
876 )
877 return '\n'.join(tb_list)
878
924
879 925 def debugger(self,force=False):
880 926 """Call up the pdb debugger if desired, always clean up the tb
881 927 reference.
@@ -923,9 +969,9 b' class VerboseTB(TBTools):'
923 969 def handler(self, info=None):
924 970 (etype, evalue, etb) = info or sys.exc_info()
925 971 self.tb = etb
926 IPython.utils.io.Term.cout.flush()
927 IPython.utils.io.Term.cerr.write(self.text(etype, evalue, etb))
928 IPython.utils.io.Term.cerr.write('\n')
972 io.Term.cout.flush()
973 io.Term.cerr.write(self.text(etype, evalue, etb))
974 io.Term.cerr.write('\n')
929 975
930 976 # Changed so an instance can just be called as VerboseTB_inst() and print
931 977 # out the right info on its own.
@@ -941,7 +987,7 b' class VerboseTB(TBTools):'
941 987 print "\nKeyboardInterrupt"
942 988
943 989 #----------------------------------------------------------------------------
944 class FormattedTB(VerboseTB,ListTB):
990 class FormattedTB(VerboseTB, ListTB):
945 991 """Subclass ListTB but allow calling with a traceback.
946 992
947 993 It can thus be used as a sys.excepthook for Python > 2.1.
@@ -953,8 +999,8 b' class FormattedTB(VerboseTB,ListTB):'
953 999 occurs with python programs that themselves execute other python code,
954 1000 like Python shells). """
955 1001
956 def __init__(self, mode = 'Plain', color_scheme='Linux',
957 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
1002 def __init__(self, mode='Plain', color_scheme='Linux',
1003 tb_offset=0, long_header=0, call_pdb=0, include_vars=0):
958 1004
959 1005 # NEVER change the order of this list. Put new modes at the end:
960 1006 self.valid_modes = ['Plain','Context','Verbose']
@@ -970,12 +1016,14 b' class FormattedTB(VerboseTB,ListTB):'
970 1016 else:
971 1017 return None
972 1018
973 def structured_traceback(self, etype, value, tb, context=5, mode=None):
1019 def structured_traceback(self, etype, value, tb, tb_offset=None,
1020 context=5, mode=None):
1021 tb_offset = self.tb_offset if tb_offset is None else tb_offset
974 1022 mode = self.mode if mode is None else mode
975 1023 if mode in self.verbose_modes:
976 1024 # Verbose modes need a full traceback
977 1025 return VerboseTB.structured_traceback(
978 self, etype, value, tb, context
1026 self, etype, value, tb, tb_offset, context
979 1027 )
980 1028 else:
981 1029 # We must check the source cache because otherwise we can print
@@ -983,21 +1031,21 b' class FormattedTB(VerboseTB,ListTB):'
983 1031 linecache.checkcache()
984 1032 # Now we can extract and format the exception
985 1033 elist = self._extract_tb(tb)
986 if len(elist) > self.tb_offset:
987 del elist[:self.tb_offset]
988 1034 return ListTB.structured_traceback(
989 self, etype, value, elist, context
1035 self, etype, value, elist, tb_offset, context
990 1036 )
991 1037
992 def text(self, etype, value, tb, context=5, mode=None):
1038 def text(self, etype, value, tb, tb_offset=None, context=5, mode=None):
993 1039 """Return formatted traceback.
994 1040
995 1041 If the optional mode parameter is given, it overrides the current
996 1042 mode."""
997 tb_list = FormattedTB.structured_traceback(
998 self, etype, value, tb, context, mode
999 )
1043
1044 mode = self.mode if mode is None else mode
1045 tb_list = self.structured_traceback(etype, value, tb, tb_offset,
1046 context, mode)
1000 1047 return '\n'.join(tb_list)
1048
1001 1049
1002 1050 def set_mode(self,mode=None):
1003 1051 """Switch to the desired mode.
@@ -1056,36 +1104,25 b' class AutoFormattedTB(FormattedTB):'
1056 1104 if self.out_stream == 'stdout':
1057 1105 out = sys.stdout
1058 1106 else:
1059 out = IPython.utils.io.Term.cerr
1107 out = io.Term.cerr
1060 1108 out.flush()
1061 if tb_offset is not None:
1062 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1063 out.write(self.text(etype, evalue, etb))
1064 out.write('\n')
1065 self.tb_offset = tb_offset
1066 else:
1067 out.write(self.text(etype, evalue, etb))
1068 out.write('\n')
1109 out.write(self.text(etype, evalue, etb, tb_offset))
1110 out.write('\n')
1069 1111 out.flush()
1112 # FIXME: we should remove the auto pdb behavior from here and leave
1113 # that to the clients.
1070 1114 try:
1071 1115 self.debugger()
1072 1116 except KeyboardInterrupt:
1073 1117 print "\nKeyboardInterrupt"
1074 1118
1075 1119 def structured_traceback(self, etype=None, value=None, tb=None,
1076 context=5, mode=None):
1120 tb_offset=None, context=5, mode=None):
1077 1121 if etype is None:
1078 1122 etype,value,tb = sys.exc_info()
1079 1123 self.tb = tb
1080 1124 return FormattedTB.structured_traceback(
1081 self, etype, value, tb, context, mode
1082 )
1083
1084 def text(self, etype=None, value=None, tb=None, context=5, mode=None):
1085 tb_list = AutoFormattedTB.structured_traceback(
1086 self, etype, value, tb, context, mode
1087 )
1088 return '\n'.join(tb_list)
1125 self, etype, value, tb, tb_offset, context, mode )
1089 1126
1090 1127 #---------------------------------------------------------------------------
1091 1128
@@ -1114,6 +1151,15 b' class SyntaxTB(ListTB):'
1114 1151 self.last_syntax_error = None
1115 1152 return e
1116 1153
1154 def text(self, etype, value, tb, tb_offset=None, context=5):
1155 """Return formatted traceback.
1156
1157 Subclasses may override this if they add extra arguments.
1158 """
1159 tb_list = self.structured_traceback(etype, value, tb,
1160 tb_offset, context)
1161 return ''.join(tb_list)
1162
1117 1163 #----------------------------------------------------------------------------
1118 1164 # module testing (minimal)
1119 1165 if __name__ == "__main__":
@@ -94,7 +94,7 b' class IPythonWidget(FrontendWidget):'
94 94 def execute_file(self, path, hidden=False):
95 95 """ Reimplemented to use the 'run' magic.
96 96 """
97 self.execute('run %s' % path, hidden=hidden)
97 self.execute('%%run %s' % path, hidden=hidden)
98 98
99 99 #---------------------------------------------------------------------------
100 100 # 'FrontendWidget' protected interface
@@ -109,16 +109,24 b' class IPythonWidget(FrontendWidget):'
109 109 """ Reimplemented for IPython-style traceback formatting.
110 110 """
111 111 content = msg['content']
112 traceback_lines = content['traceback'][:]
113 traceback = ''.join(traceback_lines)
114 traceback = traceback.replace(' ', ' ')
115 traceback = traceback.replace('\n', '<br/>')
116 112
117 ename = content['ename']
118 ename_styled = '<span class="error">%s</span>' % ename
119 traceback = traceback.replace(ename, ename_styled)
113 traceback = '\n'.join(content['traceback'])
120 114
121 self._append_html(traceback)
115 if 0:
116 # FIXME: for now, tracebacks come as plain text, so we can't use
117 # the html renderer yet. Once we refactor ultratb to produce
118 # properly styled tracebacks, this branch should be the default
119 traceback = traceback.replace(' ', '&nbsp;')
120 traceback = traceback.replace('\n', '<br/>')
121
122 ename = content['ename']
123 ename_styled = '<span class="error">%s</span>' % ename
124 traceback = traceback.replace(ename, ename_styled)
125
126 self._append_html(traceback)
127 else:
128 # This is the fallback for now, using plain text with ansi escapes
129 self._append_plain_text(traceback)
122 130
123 131 def _process_execute_payload(self, item):
124 132 """ Reimplemented to handle %edit and paging payloads.
@@ -61,6 +61,10 b' def main():'
61 61 kernel_manager.start_kernel()
62 62 kernel_manager.start_channels()
63 63
64 # FIXME: this is a hack, set colors to lightbg by default in qt terminal
65 # unconditionally, regardless of user settings in config files.
66 kernel_manager.xreq_channel.execute("%colors lightbg")
67
64 68 # Launch the application.
65 69 app = QtGui.QApplication([])
66 70 if args.pure:
@@ -13,7 +13,6 b' IO related utilities.'
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16
17 16 import sys
18 17 import tempfile
19 18
@@ -278,4 +277,10 b" def temp_pyfile(src, ext='.py'):"
278 277 return fname, f
279 278
280 279
281
280 def rprint(*info):
281 """Raw print to sys.__stderr__"""
282
283 for item in info:
284 print >> sys.__stderr__, item,
285 print >> sys.__stderr__
286 sys.__stderr__.flush()
@@ -66,6 +66,9 b' class Kernel(Configurable):'
66 66 self.shell.displayhook.session = self.session
67 67 self.shell.displayhook.pub_socket = self.pub_socket
68 68
69 # TMP - hack while developing
70 self.shell._reply_content = None
71
69 72 # Build dict of handlers for message types
70 73 msg_types = [ 'execute_request', 'complete_request',
71 74 'object_info_request', 'prompt_request',
@@ -156,19 +159,20 b' class Kernel(Configurable):'
156 159 sys.stdout.set_parent(parent)
157 160 sys.stderr.set_parent(parent)
158 161
162 # FIXME: runlines calls the exception handler itself. We should
163 # clean this up.
164 self.shell._reply_content = None
159 165 self.shell.runlines(code)
160 166 except:
167 # FIXME: this code right now isn't being used yet by default,
168 # because the runlines() call above directly fires off exception
169 # reporting. This code, therefore, is only active in the scenario
170 # where runlines itself has an unhandled exception. We need to
171 # uniformize this, for all exception construction to come from a
172 # single location in the codbase.
161 173 etype, evalue, tb = sys.exc_info()
162 tb = traceback.format_exception(etype, evalue, tb)
163 exc_content = {
164 u'status' : u'error',
165 u'traceback' : tb,
166 u'ename' : unicode(etype.__name__),
167 u'evalue' : unicode(evalue)
168 }
169 exc_msg = self.session.msg(u'pyerr', exc_content, parent)
170 self.pub_socket.send_json(exc_msg)
171 reply_content = exc_content
174 tb_list = traceback.format_exception(etype, evalue, tb)
175 reply_content = self.shell._showtraceback(etype, evalue, tb_list)
172 176 else:
173 177 payload = self.shell.payload_manager.read_payload()
174 178 # Be agressive about clearing the payload because we don't want
@@ -185,6 +189,11 b' class Kernel(Configurable):'
185 189 'input_sep' : self.shell.displayhook.input_sep}
186 190 reply_content['next_prompt'] = next_prompt
187 191
192 # TMP - fish exception info out of shell, possibly left there by
193 # runlines
194 if self.shell._reply_content is not None:
195 reply_content.update(self.shell._reply_content)
196
188 197 # Flush output before sending the reply.
189 198 sys.stderr.flush()
190 199 sys.stdout.flush()
@@ -8,6 +8,7 b' from IPython.core.interactiveshell import ('
8 8 )
9 9 from IPython.core.displayhook import DisplayHook
10 10 from IPython.core.macro import Macro
11 from IPython.utils.io import rprint
11 12 from IPython.utils.path import get_py_filename
12 13 from IPython.utils.text import StringTypes
13 14 from IPython.utils.traitlets import Instance, Type, Dict
@@ -359,7 +360,30 b' class ZMQInteractiveShell(InteractiveShell):'
359 360 self.payload_manager.write_payload(payload)
360 361
361 362
362 InteractiveShellABC.register(ZMQInteractiveShell)
363 def _showtraceback(self, etype, evalue, stb):
363 364
365 exc_content = {
366 u'status' : u'error',
367 u'traceback' : stb,
368 u'ename' : unicode(etype.__name__),
369 u'evalue' : unicode(evalue)
370 }
364 371
372 dh = self.displayhook
373 exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
374 # Send exception info over pub socket for other clients than the caller
375 # to pick up
376 dh.pub_socket.send_json(exc_msg)
377
378 # FIXME - Hack: store exception info in shell object. Right now, the
379 # caller is reading this info after the fact, we need to fix this logic
380 # to remove this hack.
381 self._reply_content = exc_content
382 # /FIXME
383
384 return exc_content
365 385
386 def runlines(self, lines, clean=False):
387 return InteractiveShell.runlines(self, lines, clean)
388
389 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now