##// END OF EJS Templates
truncate potentially long CompositeErrors...
MinRK -
Show More
@@ -232,6 +232,8 b' class TaskRejectError(KernelError):'
232
232
233 class CompositeError(RemoteError):
233 class CompositeError(RemoteError):
234 """Error for representing possibly multiple errors on engines"""
234 """Error for representing possibly multiple errors on engines"""
235 tb_limit = 4 # limit on how many tracebacks to draw
236
235 def __init__(self, message, elist):
237 def __init__(self, message, elist):
236 Exception.__init__(self, *(message, elist))
238 Exception.__init__(self, *(message, elist))
237 # Don't use pack_exception because it will conflict with the .message
239 # Don't use pack_exception because it will conflict with the .message
@@ -256,22 +258,28 b' class CompositeError(RemoteError):'
256
258
257 def __str__(self):
259 def __str__(self):
258 s = str(self.msg)
260 s = str(self.msg)
259 for en, ev, etb, ei in self.elist:
261 for en, ev, etb, ei in self.elist[:self.tb_limit]:
260 engine_str = self._get_engine_str(ei)
262 engine_str = self._get_engine_str(ei)
261 s = s + '\n' + engine_str + en + ': ' + str(ev)
263 s = s + '\n' + engine_str + en + ': ' + str(ev)
264 if len(self.elist) > self.tb_limit:
265 s = s + '\n.... %i more exceptions ...' % (len(self.elist) - self.tb_limit)
262 return s
266 return s
263
267
264 def __repr__(self):
268 def __repr__(self):
265 return "CompositeError(%i)"%len(self.elist)
269 return "CompositeError(%i)" % len(self.elist)
266
270
267 def render_traceback(self, excid=None):
271 def render_traceback(self, excid=None):
268 """render one or all of my tracebacks to a list of lines"""
272 """render one or all of my tracebacks to a list of lines"""
269 lines = []
273 lines = []
270 if excid is None:
274 if excid is None:
271 for (en,ev,etb,ei) in self.elist:
275 for (en,ev,etb,ei) in self.elist[:self.tb_limit]:
272 lines.append(self._get_engine_str(ei))
276 lines.append(self._get_engine_str(ei))
273 lines.extend((etb or 'No traceback available').splitlines())
277 lines.extend((etb or 'No traceback available').splitlines())
274 lines.append('')
278 lines.append('')
279 if len(self.elist) > self.tb_limit:
280 lines.append(
281 '... %i more exceptions ...' % (len(self.elist) - self.tb_limit)
282 )
275 else:
283 else:
276 try:
284 try:
277 en,ev,etb,ei = self.elist[excid]
285 en,ev,etb,ei = self.elist[excid]
@@ -619,6 +619,33 b' class TestView(ClusterTestCase, ParametricTestCase):'
619 self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout)
619 self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout)
620 self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout)
620 self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout)
621
621
622 def test_compositeerror_truncate(self):
623 """Truncate CompositeErrors with many exceptions"""
624 view = self.client[:]
625 msg_ids = []
626 for i in range(10):
627 ar = view.execute("1/0")
628 msg_ids.extend(ar.msg_ids)
629
630 ar = self.client.get_result(msg_ids)
631 try:
632 ar.get()
633 except error.CompositeError as e:
634 pass
635 else:
636 self.fail("Should have raised CompositeError")
637
638 lines = e.render_traceback()
639 with capture_output() as io:
640 e.print_traceback()
641
642 self.assertTrue("more exceptions" in lines[-1])
643 count = e.tb_limit
644
645 self.assertEqual(io.stdout.count('ZeroDivisionError'), 2 * count, io.stdout)
646 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
647 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
648
622 @dec.skipif_not_matplotlib
649 @dec.skipif_not_matplotlib
623 def test_magic_pylab(self):
650 def test_magic_pylab(self):
624 """%pylab works on engines"""
651 """%pylab works on engines"""
General Comments 0
You need to be logged in to leave comments. Login now