diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
index 711b2f9..edf5c9c 100644
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -29,6 +29,7 @@ import sys
import tempfile
from contextlib import nested
+from IPython.config.configurable import Configurable
from IPython.core import debugger, oinspect
from IPython.core import history as ipcorehist
from IPython.core import prefilter
@@ -36,8 +37,8 @@ from IPython.core import shadowns
from IPython.core import ultratb
from IPython.core.alias import AliasManager
from IPython.core.builtin_trap import BuiltinTrap
-from IPython.config.configurable import Configurable
from IPython.core.display_trap import DisplayTrap
+from IPython.core.displayhook import DisplayHook
from IPython.core.error import UsageError
from IPython.core.extensions import ExtensionManager
from IPython.core.fakemodule import FakeModule, init_fakemod_dict
@@ -47,24 +48,22 @@ from IPython.core.magic import Magic
from IPython.core.payload import PayloadManager
from IPython.core.plugin import PluginManager
from IPython.core.prefilter import PrefilterManager
-from IPython.core.displayhook import DisplayHook
-import IPython.core.hooks
from IPython.external.Itpl import ItplNS
from IPython.utils import PyColorize
+from IPython.utils import io
from IPython.utils import pickleshare
from IPython.utils.doctestreload import doctest_reload
+from IPython.utils.io import ask_yes_no, rprint
from IPython.utils.ipstruct import Struct
-import IPython.utils.io
-from IPython.utils.io import ask_yes_no
from IPython.utils.path import get_home_dir, get_ipython_dir, HomeDirError
from IPython.utils.process import getoutput, getoutputerror
from IPython.utils.strdispatch import StrDispatch
from IPython.utils.syspathcontext import prepended_to_syspath
from IPython.utils.text import num_ini_spaces
+from IPython.utils.traitlets import (Int, Str, CBool, CaselessStrEnum, Enum,
+ List, Unicode, Instance, Type)
from IPython.utils.warn import warn, error, fatal
-from IPython.utils.traitlets import (
- Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode, Instance, Type
-)
+import IPython.core.hooks
# from IPython.utils import growl
# growl.start("IPython")
@@ -430,12 +429,12 @@ class InteractiveShell(Configurable, Magic):
def init_io(self):
import IPython.utils.io
if sys.platform == 'win32' and self.has_readline:
- Term = IPython.utils.io.IOTerm(
+ Term = io.IOTerm(
cout=self.readline._outputfile,cerr=self.readline._outputfile
)
else:
- Term = IPython.utils.io.IOTerm()
- IPython.utils.io.Term = Term
+ Term = io.IOTerm()
+ io.Term = Term
def init_prompts(self):
# TODO: This is a pass for now because the prompts are managed inside
@@ -1181,7 +1180,7 @@ class InteractiveShell(Configurable, Magic):
# Set the exception mode
self.InteractiveTB.set_mode(mode=self.xmode)
- def set_custom_exc(self,exc_tuple,handler):
+ def set_custom_exc(self, exc_tuple, handler):
"""set_custom_exc(exc_tuple,handler)
Set a custom exception handler, which will be called if any of the
@@ -1198,7 +1197,12 @@ class InteractiveShell(Configurable, Magic):
exc_tuple == (MyCustomException,)
- handler: this must be defined as a function with the following
- basic interface: def my_handler(self,etype,value,tb).
+ basic interface::
+
+ def my_handler(self, etype, value, tb, tb_offset=None)
+ ...
+ # The return value must be
+ return structured_traceback
This will be made into an instance method (via new.instancemethod)
of IPython itself, and it will be called if any of the exceptions
@@ -1272,7 +1276,7 @@ class InteractiveShell(Configurable, Magic):
etype, value, tb = sys.last_type, sys.last_value, \
sys.last_traceback
else:
- self.write('No traceback available to show.\n')
+ self.write_err('No traceback available to show.\n')
return
if etype is SyntaxError:
@@ -1291,22 +1295,39 @@ class InteractiveShell(Configurable, Magic):
sys.last_traceback = tb
if etype in self.custom_exceptions:
- self.CustomTB(etype,value,tb)
+ # FIXME: Old custom traceback objects may just return a
+ # string, in that case we just put it into a list
+ stb = self.CustomTB(etype, value, tb, tb_offset)
+ if isinstance(ctb, basestring):
+ stb = [stb]
else:
if exception_only:
- m = ('An exception has occurred, use %tb to see the '
- 'full traceback.')
- print m
- self.InteractiveTB.show_exception_only(etype, value)
+ stb = ['An exception has occurred, use %tb to see '
+ 'the full traceback.']
+ stb.extend(self.InteractiveTB.get_exception_only(etype,
+ value))
else:
- self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
+ stb = self.InteractiveTB.structured_traceback(etype,
+ value, tb, tb_offset=tb_offset)
+ # FIXME: the pdb calling should be done by us, not by
+ # the code computing the traceback.
if self.InteractiveTB.call_pdb:
# pdb mucks up readline, fix it back
self.set_completer()
-
+
+ # Actually show the traceback
+ self._showtraceback(etype, value, stb)
+
except KeyboardInterrupt:
- self.write("\nKeyboardInterrupt\n")
-
+ self.write_err("\nKeyboardInterrupt\n")
+
+ def _showtraceback(self, etype, evalue, stb):
+ """Actually show a traceback.
+
+ Subclasses may override this method to put the traceback on a different
+ place, like a side channel.
+ """
+ self.write_err('\n'.join(stb))
def showsyntaxerror(self, filename=None):
"""Display the syntax error that just occurred.
@@ -1339,7 +1360,8 @@ class InteractiveShell(Configurable, Magic):
except:
# If that failed, assume SyntaxError is a string
value = msg, (filename, lineno, offset, line)
- self.SyntaxTB(etype,value,[])
+ stb = self.SyntaxTB.structured_traceback(etype, value, [])
+ self._showtraceback(etype, value, stb)
#-------------------------------------------------------------------------
# Things related to tab completion
@@ -1792,7 +1814,7 @@ class InteractiveShell(Configurable, Magic):
exposes IPython's processing machinery, the given strings can contain
magic calls (%magic), special shell access (!cmd), etc.
"""
-
+
if isinstance(lines, (list, tuple)):
lines = '\n'.join(lines)
@@ -1912,6 +1934,7 @@ class InteractiveShell(Configurable, Magic):
try:
try:
self.hooks.pre_runcode_hook()
+ #rprint('Running code') # dbg
exec code_obj in self.user_global_ns, self.user_ns
finally:
# Reset our crash handler in place
@@ -2080,12 +2103,12 @@ class InteractiveShell(Configurable, Magic):
# TODO: This should be removed when Term is refactored.
def write(self,data):
"""Write a string to the default output"""
- IPython.utils.io.Term.cout.write(data)
+ io.Term.cout.write(data)
# TODO: This should be removed when Term is refactored.
def write_err(self,data):
"""Write a string to the default error output"""
- IPython.utils.io.Term.cerr.write(data)
+ io.Term.cerr.write(data)
def ask_yes_no(self,prompt,default=True):
if self.quiet:
diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py
index 7606ab6..8a4cabd 100644
--- a/IPython/core/ultratb.py
+++ b/IPython/core/ultratb.py
@@ -90,12 +90,12 @@ from inspect import getsourcefile, getfile, getmodule,\
# IPython's own modules
# Modified pdb which doesn't damage IPython's readline handling
-from IPython.utils import PyColorize
from IPython.core import debugger, ipapi
from IPython.core.display_trap import DisplayTrap
from IPython.core.excolors import exception_colors
+from IPython.utils import PyColorize
+from IPython.utils import io
from IPython.utils.data import uniq_stable
-import IPython.utils.io
from IPython.utils.warn import info, error
# Globals
@@ -310,7 +310,7 @@ def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
#---------------------------------------------------------------------------
# Module classes
-class TBTools:
+class TBTools(object):
"""Basic tools used by all traceback printer classes."""
# This attribute us used in globalipapp.py to have stdout used for
@@ -319,6 +319,9 @@ class TBTools:
# the string 'stdout' which will cause the override to sys.stdout.
out_stream = None
+ # Number of frames to skip when reporting tracebacks
+ tb_offset = 0
+
def __init__(self,color_scheme = 'NoColor',call_pdb=False):
# Whether to call the interactive pdb debugger after printing
# tracebacks or not
@@ -357,6 +360,24 @@ class TBTools:
self.color_scheme_table.set_active_scheme('NoColor')
self.Colors = self.color_scheme_table.active_colors
+ def text(self, etype, value, tb, tb_offset=None, context=5):
+ """Return formatted traceback.
+
+ Subclasses may override this if they add extra arguments.
+ """
+ tb_list = self.structured_traceback(etype, value, tb,
+ tb_offset, context)
+ return '\n'.join(tb_list)
+
+ def structured_traceback(self, etype, evalue, tb, tb_offset=None,
+ context=5, mode=None):
+ """Return a list of traceback frames.
+
+ Must be implemented by each class.
+ """
+ raise NotImplementedError()
+
+
#---------------------------------------------------------------------------
class ListTB(TBTools):
"""Print traceback information from a traceback list, with optional color.
@@ -381,11 +402,12 @@ class ListTB(TBTools):
TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
def __call__(self, etype, value, elist):
- IPython.utils.io.Term.cout.flush()
- IPython.utils.io.Term.cerr.write(self.text(etype,value,elist))
- IPython.utils.io.Term.cerr.write('\n')
+ io.Term.cout.flush()
+ io.Term.cerr.write(self.text(etype, value, elist))
+ io.Term.cerr.write('\n')
- def structured_traceback(self, etype, value, elist, context=5):
+ def structured_traceback(self, etype, value, elist, tb_offset=None,
+ context=5):
"""Return a color formatted string with the traceback info.
Parameters
@@ -399,28 +421,43 @@ class ListTB(TBTools):
elist : list
List of frames, see class docstring for details.
+ tb_offset : int, optional
+ Number of frames in the traceback to skip. If not given, the
+ instance value is used (set in constructor).
+
+ context : int, optional
+ Number of lines of context information to print.
+
Returns
-------
String with formatted exception.
"""
-
+ tb_offset = self.tb_offset if tb_offset is None else tb_offset
Colors = self.Colors
- out_string = []
+ out_list = []
if elist:
- out_string.append('Traceback %s(most recent call last)%s:' %
+
+ if tb_offset and len(elist) > tb_offset:
+ elist = elist[tb_offset:]
+
+ out_list.append('Traceback %s(most recent call last)%s:' %
(Colors.normalEm, Colors.Normal) + '\n')
- out_string.extend(self._format_list(elist))
- lines = self._format_exception_only(etype, value)
- for line in lines[:-1]:
- out_string.append(" "+line)
- out_string.append(lines[-1])
- return out_string
-
- def text(self, etype, value, elist, context=5):
- out_string = ListTB.structured_traceback(
- self, etype, value, elist, context
- )
- return ''.join(out_string)
+ out_list.extend(self._format_list(elist))
+ # The exception info should be a single entry in the list.
+ lines = ''.join(self._format_exception_only(etype, value))
+ out_list.append(lines)
+
+ # Note: this code originally read:
+
+ ## for line in lines[:-1]:
+ ## out_list.append(" "+line)
+ ## out_list.append(lines[-1])
+
+ # This means it was indenting everything but the last line by a little
+ # bit. I've disabled this for now, but if we see ugliness somewhre we
+ # can restore it.
+
+ return out_list
def _format_list(self, extracted_list):
"""Format a list of traceback entry tuples for printing.
@@ -457,6 +494,7 @@ class ListTB(TBTools):
item = item + '%s %s%s\n' % (Colors.line, line.strip(),
Colors.Normal)
list.append(item)
+ #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
return list
def _format_exception_only(self, etype, value):
@@ -528,6 +566,17 @@ class ListTB(TBTools):
return list
+ def get_exception_only(self, etype, value):
+ """Only print the exception type and message, without a traceback.
+
+ Parameters
+ ----------
+ etype : exception type
+ value : exception value
+ """
+ return ListTB.structured_traceback(self, etype, value, [])
+
+
def show_exception_only(self, etype, value):
"""Only print the exception type and message, without a traceback.
@@ -541,9 +590,9 @@ class ListTB(TBTools):
if self.out_stream == 'stdout':
ostream = sys.stdout
else:
- ostream = IPython.utils.io.Term.cerr
+ ostream = io.Term.cerr
ostream.flush()
- ostream.write(ListTB.text(self, etype, value, []))
+ ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
ostream.flush()
def _some_str(self, value):
@@ -575,9 +624,12 @@ class VerboseTB(TBTools):
self.long_header = long_header
self.include_vars = include_vars
- def structured_traceback(self, etype, evalue, etb, context=5):
+ def structured_traceback(self, etype, evalue, etb, tb_offset=None,
+ context=5):
"""Return a nice text document describing the traceback."""
+ tb_offset = self.tb_offset if tb_offset is None else tb_offset
+
# some locals
try:
etype = etype.__name__
@@ -652,9 +704,9 @@ class VerboseTB(TBTools):
# Try the default getinnerframes and Alex's: Alex's fixes some
# problems, but it generates empty tracebacks for console errors
# (5 blanks lines) where none should be returned.
- #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
+ #records = inspect.getinnerframes(etb, context)[tb_offset:]
#print 'python records:', records # dbg
- records = _fixed_getinnerframes(etb, context,self.tb_offset)
+ records = _fixed_getinnerframes(etb, context, tb_offset)
#print 'alex records:', records # dbg
except:
@@ -665,7 +717,7 @@ class VerboseTB(TBTools):
# So far, I haven't been able to find an isolated example to
# reproduce the problem.
inspect_error()
- traceback.print_exc(file=IPython.utils.io.Term.cerr)
+ traceback.print_exc(file=io.Term.cerr)
info('\nUnfortunately, your original traceback can not be constructed.\n')
return ''
@@ -702,7 +754,7 @@ class VerboseTB(TBTools):
# able to remove this try/except when 2.4 becomes a
# requirement. Bug details at http://python.org/sf/1005466
inspect_error()
- traceback.print_exc(file=IPython.utils.io.Term.cerr)
+ traceback.print_exc(file=io.Term.cerr)
info("\nIPython's exception reporting continues...\n")
if func == '?':
@@ -723,7 +775,7 @@ class VerboseTB(TBTools):
# and barfs out. At some point I should dig into this one
# and file a bug report about it.
inspect_error()
- traceback.print_exc(file=IPython.utils.io.Term.cerr)
+ traceback.print_exc(file=io.Term.cerr)
info("\nIPython's exception reporting continues...\n")
call = tpl_call_fail % func
@@ -869,13 +921,7 @@ class VerboseTB(TBTools):
# return all our info assembled as a single string
# return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
return [head] + frames + [''.join(exception[0])]
-
- def text(self, etype, evalue, etb, context=5):
- tb_list = VerboseTB.structured_traceback(
- self, etype, evalue, etb, context
- )
- return '\n'.join(tb_list)
-
+
def debugger(self,force=False):
"""Call up the pdb debugger if desired, always clean up the tb
reference.
@@ -923,9 +969,9 @@ class VerboseTB(TBTools):
def handler(self, info=None):
(etype, evalue, etb) = info or sys.exc_info()
self.tb = etb
- IPython.utils.io.Term.cout.flush()
- IPython.utils.io.Term.cerr.write(self.text(etype, evalue, etb))
- IPython.utils.io.Term.cerr.write('\n')
+ io.Term.cout.flush()
+ io.Term.cerr.write(self.text(etype, evalue, etb))
+ io.Term.cerr.write('\n')
# Changed so an instance can just be called as VerboseTB_inst() and print
# out the right info on its own.
@@ -941,7 +987,7 @@ class VerboseTB(TBTools):
print "\nKeyboardInterrupt"
#----------------------------------------------------------------------------
-class FormattedTB(VerboseTB,ListTB):
+class FormattedTB(VerboseTB, ListTB):
"""Subclass ListTB but allow calling with a traceback.
It can thus be used as a sys.excepthook for Python > 2.1.
@@ -953,8 +999,8 @@ class FormattedTB(VerboseTB,ListTB):
occurs with python programs that themselves execute other python code,
like Python shells). """
- def __init__(self, mode = 'Plain', color_scheme='Linux',
- tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
+ def __init__(self, mode='Plain', color_scheme='Linux',
+ tb_offset=0, long_header=0, call_pdb=0, include_vars=0):
# NEVER change the order of this list. Put new modes at the end:
self.valid_modes = ['Plain','Context','Verbose']
@@ -970,12 +1016,14 @@ class FormattedTB(VerboseTB,ListTB):
else:
return None
- def structured_traceback(self, etype, value, tb, context=5, mode=None):
+ def structured_traceback(self, etype, value, tb, tb_offset=None,
+ context=5, mode=None):
+ tb_offset = self.tb_offset if tb_offset is None else tb_offset
mode = self.mode if mode is None else mode
if mode in self.verbose_modes:
# Verbose modes need a full traceback
return VerboseTB.structured_traceback(
- self, etype, value, tb, context
+ self, etype, value, tb, tb_offset, context
)
else:
# We must check the source cache because otherwise we can print
@@ -983,21 +1031,21 @@ class FormattedTB(VerboseTB,ListTB):
linecache.checkcache()
# Now we can extract and format the exception
elist = self._extract_tb(tb)
- if len(elist) > self.tb_offset:
- del elist[:self.tb_offset]
return ListTB.structured_traceback(
- self, etype, value, elist, context
+ self, etype, value, elist, tb_offset, context
)
- def text(self, etype, value, tb, context=5, mode=None):
+ def text(self, etype, value, tb, tb_offset=None, context=5, mode=None):
"""Return formatted traceback.
If the optional mode parameter is given, it overrides the current
mode."""
- tb_list = FormattedTB.structured_traceback(
- self, etype, value, tb, context, mode
- )
+
+ mode = self.mode if mode is None else mode
+ tb_list = self.structured_traceback(etype, value, tb, tb_offset,
+ context, mode)
return '\n'.join(tb_list)
+
def set_mode(self,mode=None):
"""Switch to the desired mode.
@@ -1056,36 +1104,25 @@ class AutoFormattedTB(FormattedTB):
if self.out_stream == 'stdout':
out = sys.stdout
else:
- out = IPython.utils.io.Term.cerr
+ out = io.Term.cerr
out.flush()
- if tb_offset is not None:
- tb_offset, self.tb_offset = self.tb_offset, tb_offset
- out.write(self.text(etype, evalue, etb))
- out.write('\n')
- self.tb_offset = tb_offset
- else:
- out.write(self.text(etype, evalue, etb))
- out.write('\n')
+ out.write(self.text(etype, evalue, etb, tb_offset))
+ out.write('\n')
out.flush()
+ # FIXME: we should remove the auto pdb behavior from here and leave
+ # that to the clients.
try:
self.debugger()
except KeyboardInterrupt:
print "\nKeyboardInterrupt"
def structured_traceback(self, etype=None, value=None, tb=None,
- context=5, mode=None):
+ tb_offset=None, context=5, mode=None):
if etype is None:
etype,value,tb = sys.exc_info()
self.tb = tb
return FormattedTB.structured_traceback(
- self, etype, value, tb, context, mode
- )
-
- def text(self, etype=None, value=None, tb=None, context=5, mode=None):
- tb_list = AutoFormattedTB.structured_traceback(
- self, etype, value, tb, context, mode
- )
- return '\n'.join(tb_list)
+ self, etype, value, tb, tb_offset, context, mode )
#---------------------------------------------------------------------------
@@ -1114,6 +1151,15 @@ class SyntaxTB(ListTB):
self.last_syntax_error = None
return e
+ def text(self, etype, value, tb, tb_offset=None, context=5):
+ """Return formatted traceback.
+
+ Subclasses may override this if they add extra arguments.
+ """
+ tb_list = self.structured_traceback(etype, value, tb,
+ tb_offset, context)
+ return ''.join(tb_list)
+
#----------------------------------------------------------------------------
# module testing (minimal)
if __name__ == "__main__":
diff --git a/IPython/frontend/qt/console/ipython_widget.py b/IPython/frontend/qt/console/ipython_widget.py
index b140e7b..e6e5334 100644
--- a/IPython/frontend/qt/console/ipython_widget.py
+++ b/IPython/frontend/qt/console/ipython_widget.py
@@ -94,7 +94,7 @@ class IPythonWidget(FrontendWidget):
def execute_file(self, path, hidden=False):
""" Reimplemented to use the 'run' magic.
"""
- self.execute('run %s' % path, hidden=hidden)
+ self.execute('%%run %s' % path, hidden=hidden)
#---------------------------------------------------------------------------
# 'FrontendWidget' protected interface
@@ -109,16 +109,24 @@ class IPythonWidget(FrontendWidget):
""" Reimplemented for IPython-style traceback formatting.
"""
content = msg['content']
- traceback_lines = content['traceback'][:]
- traceback = ''.join(traceback_lines)
- traceback = traceback.replace(' ', ' ')
- traceback = traceback.replace('\n', '
')
- ename = content['ename']
- ename_styled = '%s' % ename
- traceback = traceback.replace(ename, ename_styled)
+ traceback = '\n'.join(content['traceback'])
- self._append_html(traceback)
+ if 0:
+ # FIXME: for now, tracebacks come as plain text, so we can't use
+ # the html renderer yet. Once we refactor ultratb to produce
+ # properly styled tracebacks, this branch should be the default
+ traceback = traceback.replace(' ', ' ')
+ traceback = traceback.replace('\n', '
')
+
+ ename = content['ename']
+ ename_styled = '%s' % ename
+ traceback = traceback.replace(ename, ename_styled)
+
+ self._append_html(traceback)
+ else:
+ # This is the fallback for now, using plain text with ansi escapes
+ self._append_plain_text(traceback)
def _process_execute_payload(self, item):
""" Reimplemented to handle %edit and paging payloads.
diff --git a/IPython/frontend/qt/console/scripts/ipythonqt.py b/IPython/frontend/qt/console/scripts/ipythonqt.py
index cdf50a2..1a8033c 100755
--- a/IPython/frontend/qt/console/scripts/ipythonqt.py
+++ b/IPython/frontend/qt/console/scripts/ipythonqt.py
@@ -61,6 +61,10 @@ def main():
kernel_manager.start_kernel()
kernel_manager.start_channels()
+ # FIXME: this is a hack, set colors to lightbg by default in qt terminal
+ # unconditionally, regardless of user settings in config files.
+ kernel_manager.xreq_channel.execute("%colors lightbg")
+
# Launch the application.
app = QtGui.QApplication([])
if args.pure:
diff --git a/IPython/utils/io.py b/IPython/utils/io.py
index e38445b..e32c49f 100644
--- a/IPython/utils/io.py
+++ b/IPython/utils/io.py
@@ -13,7 +13,6 @@ IO related utilities.
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
-
import sys
import tempfile
@@ -278,4 +277,10 @@ def temp_pyfile(src, ext='.py'):
return fname, f
-
+def rprint(*info):
+ """Raw print to sys.__stderr__"""
+
+ for item in info:
+ print >> sys.__stderr__, item,
+ print >> sys.__stderr__
+ sys.__stderr__.flush()
diff --git a/IPython/zmq/ipkernel.py b/IPython/zmq/ipkernel.py
index bcdf342..4839785 100755
--- a/IPython/zmq/ipkernel.py
+++ b/IPython/zmq/ipkernel.py
@@ -66,6 +66,9 @@ class Kernel(Configurable):
self.shell.displayhook.session = self.session
self.shell.displayhook.pub_socket = self.pub_socket
+ # TMP - hack while developing
+ self.shell._reply_content = None
+
# Build dict of handlers for message types
msg_types = [ 'execute_request', 'complete_request',
'object_info_request', 'prompt_request',
@@ -156,19 +159,20 @@ class Kernel(Configurable):
sys.stdout.set_parent(parent)
sys.stderr.set_parent(parent)
+ # FIXME: runlines calls the exception handler itself. We should
+ # clean this up.
+ self.shell._reply_content = None
self.shell.runlines(code)
except:
+ # FIXME: this code right now isn't being used yet by default,
+ # because the runlines() call above directly fires off exception
+ # reporting. This code, therefore, is only active in the scenario
+ # where runlines itself has an unhandled exception. We need to
+ # uniformize this, for all exception construction to come from a
+ # single location in the codbase.
etype, evalue, tb = sys.exc_info()
- tb = traceback.format_exception(etype, evalue, tb)
- exc_content = {
- u'status' : u'error',
- u'traceback' : tb,
- u'ename' : unicode(etype.__name__),
- u'evalue' : unicode(evalue)
- }
- exc_msg = self.session.msg(u'pyerr', exc_content, parent)
- self.pub_socket.send_json(exc_msg)
- reply_content = exc_content
+ tb_list = traceback.format_exception(etype, evalue, tb)
+ reply_content = self.shell._showtraceback(etype, evalue, tb_list)
else:
payload = self.shell.payload_manager.read_payload()
# Be agressive about clearing the payload because we don't want
@@ -185,6 +189,11 @@ class Kernel(Configurable):
'input_sep' : self.shell.displayhook.input_sep}
reply_content['next_prompt'] = next_prompt
+ # TMP - fish exception info out of shell, possibly left there by
+ # runlines
+ if self.shell._reply_content is not None:
+ reply_content.update(self.shell._reply_content)
+
# Flush output before sending the reply.
sys.stderr.flush()
sys.stdout.flush()
diff --git a/IPython/zmq/zmqshell.py b/IPython/zmq/zmqshell.py
index ecbf85e..0e2c1a8 100644
--- a/IPython/zmq/zmqshell.py
+++ b/IPython/zmq/zmqshell.py
@@ -8,6 +8,7 @@ from IPython.core.interactiveshell import (
)
from IPython.core.displayhook import DisplayHook
from IPython.core.macro import Macro
+from IPython.utils.io import rprint
from IPython.utils.path import get_py_filename
from IPython.utils.text import StringTypes
from IPython.utils.traitlets import Instance, Type, Dict
@@ -359,7 +360,30 @@ class ZMQInteractiveShell(InteractiveShell):
self.payload_manager.write_payload(payload)
-InteractiveShellABC.register(ZMQInteractiveShell)
+ def _showtraceback(self, etype, evalue, stb):
+ exc_content = {
+ u'status' : u'error',
+ u'traceback' : stb,
+ u'ename' : unicode(etype.__name__),
+ u'evalue' : unicode(evalue)
+ }
+ dh = self.displayhook
+ exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
+ # Send exception info over pub socket for other clients than the caller
+ # to pick up
+ dh.pub_socket.send_json(exc_msg)
+
+ # FIXME - Hack: store exception info in shell object. Right now, the
+ # caller is reading this info after the fact, we need to fix this logic
+ # to remove this hack.
+ self._reply_content = exc_content
+ # /FIXME
+
+ return exc_content
+ def runlines(self, lines, clean=False):
+ return InteractiveShell.runlines(self, lines, clean)
+
+InteractiveShellABC.register(ZMQInteractiveShell)