diff --git a/IPython/parallel/error.py b/IPython/parallel/error.py index c797f7c..13c3928 100644 --- a/IPython/parallel/error.py +++ b/IPython/parallel/error.py @@ -194,9 +194,15 @@ class RemoteError(KernelError): """render traceback to a list of lines""" return (self.traceback or "No traceback available").splitlines() - # Special method for custom tracebacks within IPython - _render_traceback_ = render_traceback - + def _render_traceback_(self): + """Special method for custom tracebacks within IPython. + + This will be called by IPython instead of displaying the local traceback. + + It should return a traceback rendered as a list of lines. + """ + return self.render_traceback() + def print_traceback(self, excid=None): """print my traceback""" print('\n'.join(self.render_traceback())) diff --git a/IPython/parallel/tests/test_view.py b/IPython/parallel/tests/test_view.py index 3458f73..29715d0 100644 --- a/IPython/parallel/tests/test_view.py +++ b/IPython/parallel/tests/test_view.py @@ -27,6 +27,7 @@ from nose import SkipTest from IPython.testing import decorators as dec from IPython.testing.ipunittest import ParametricTestCase +from IPython.utils.io import capture_output from IPython import parallel as pmod from IPython.parallel import error @@ -578,6 +579,30 @@ class TestView(ClusterTestCase, ParametricTestCase): ar = view.execute("1/0") self.assertRaisesRemote(ZeroDivisionError, ar.get, 2) + def test_remoteerror_render_exception(self): + """RemoteErrors get nice tracebacks""" + view = self.client[-1] + ar = view.execute("1/0") + ip = get_ipython() + ip.user_ns['ar'] = ar + with capture_output() as io: + ip.run_cell("ar.get(2)") + + self.assertTrue('ZeroDivisionError' in io.stdout, io.stdout) + + def test_compositeerror_render_exception(self): + """CompositeErrors get nice tracebacks""" + view = self.client[:] + ar = view.execute("1/0") + ip = get_ipython() + ip.user_ns['ar'] = ar + with capture_output() as io: + ip.run_cell("ar.get(2)") + + self.assertEqual(io.stdout.count('ZeroDivisionError'), len(view) * 2, io.stdout) + self.assertEqual(io.stdout.count('integer division'), len(view), io.stdout) + self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout) + @dec.skipif_not_matplotlib def test_magic_pylab(self): """%pylab works on engines"""