Show More
@@ -232,6 +232,8 b' class TaskRejectError(KernelError):' | |||
|
232 | 232 | |
|
233 | 233 | class CompositeError(RemoteError): |
|
234 | 234 | """Error for representing possibly multiple errors on engines""" |
|
235 | tb_limit = 4 # limit on how many tracebacks to draw | |
|
236 | ||
|
235 | 237 | def __init__(self, message, elist): |
|
236 | 238 | Exception.__init__(self, *(message, elist)) |
|
237 | 239 | # Don't use pack_exception because it will conflict with the .message |
@@ -256,22 +258,28 b' class CompositeError(RemoteError):' | |||
|
256 | 258 | |
|
257 | 259 | def __str__(self): |
|
258 | 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 | 262 | engine_str = self._get_engine_str(ei) |
|
261 | 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 | 266 | return s |
|
263 | 267 | |
|
264 | 268 | def __repr__(self): |
|
265 | return "CompositeError(%i)"%len(self.elist) | |
|
269 | return "CompositeError(%i)" % len(self.elist) | |
|
266 | 270 | |
|
267 | 271 | def render_traceback(self, excid=None): |
|
268 | 272 | """render one or all of my tracebacks to a list of lines""" |
|
269 | 273 | lines = [] |
|
270 | 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 | 276 | lines.append(self._get_engine_str(ei)) |
|
273 | 277 | lines.extend((etb or 'No traceback available').splitlines()) |
|
274 | 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 | 283 | else: |
|
276 | 284 | try: |
|
277 | 285 | en,ev,etb,ei = self.elist[excid] |
@@ -619,6 +619,33 b' class TestView(ClusterTestCase, ParametricTestCase):' | |||
|
619 | 619 | self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout) |
|
620 | 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 | 649 | @dec.skipif_not_matplotlib |
|
623 | 650 | def test_magic_pylab(self): |
|
624 | 651 | """%pylab works on engines""" |
General Comments 0
You need to be logged in to leave comments.
Login now