From 58335ad7f9099b25d742e74dc2058637a9626618 2012-08-26 23:16:19
From: Min RK <benjaminrk@gmail.com>
Date: 2012-08-26 23:16:19
Subject: [PATCH] Merge pull request #2305 from minrk/render_traceback

RemoteError._render_traceback_ calls self.render_traceback

rather than an alias, which can be broken by subclassing

closes #2303



---

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"""