##// END OF EJS Templates
Simplified output stream management in ultratb....
Fernando Perez -
Show More
@@ -313,20 +313,23 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
313 313 class TBTools(object):
314 314 """Basic tools used by all traceback printer classes."""
315 315
316 # This attribute us used in globalipapp.py to have stdout used for
317 # writting exceptions. This is needed so nose can trap them. This attribute
318 # should be None (the default, which will use IPython.utils.io.Term) or
319 # the string 'stdout' which will cause the override to sys.stdout.
320 out_stream = None
321
322 316 # Number of frames to skip when reporting tracebacks
323 317 tb_offset = 0
324 318
325 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
319 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
326 320 # Whether to call the interactive pdb debugger after printing
327 321 # tracebacks or not
328 322 self.call_pdb = call_pdb
329 323
324 # Output stream to write to. Note that we store the original value in
325 # a private attribute and then make the public ostream a property, so
326 # that we can delay accessing io.Term.cout until runtime. The way
327 # things are written now, the Term.cout object is dynamically managed
328 # so a reference to it should NEVER be stored statically. This
329 # property approach confines this detail to a single location, and all
330 # subclasses can simply access self.ostream for writing.
331 self._ostream = ostream
332
330 333 # Create color table
331 334 self.color_scheme_table = exception_colors()
332 335
@@ -338,6 +341,25 b' class TBTools(object):'
338 341 else:
339 342 self.pdb = None
340 343
344 def _get_ostream(self):
345 """Output stream that exceptions are written to.
346
347 Valid values are:
348
349 - None: the default, which means that IPython will dynamically resolve
350 to io.Term.cout. This ensures compatibility with most tools, including
351 Windows (where plain stdout doesn't recognize ANSI escapes).
352
353 - Any object with 'write' and 'flush' attributes.
354 """
355 return io.Term.cout if self._ostream is None else self._ostream
356
357 def _set_ostream(self, val):
358 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
359 self._ostream = val
360
361 ostream = property(_get_ostream, _set_ostream)
362
341 363 def set_colors(self,*args,**kw):
342 364 """Shorthand access to the color table scheme selector method."""
343 365
@@ -402,8 +424,9 b' class ListTB(TBTools):'
402 424 Because they are meant to be called without a full traceback (only a
403 425 list), instances of this class can't call the interactive pdb debugger."""
404 426
405 def __init__(self,color_scheme = 'NoColor'):
406 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
427 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
428 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
429 ostream=ostream)
407 430
408 431 def __call__(self, etype, value, elist):
409 432 io.Term.cout.flush()
@@ -591,10 +614,7 b' class ListTB(TBTools):'
591 614 """
592 615 # This method needs to use __call__ from *this* class, not the one from
593 616 # a subclass whose signature or behavior may be different
594 if self.out_stream == 'stdout':
595 ostream = sys.stdout
596 else:
597 ostream = io.Term.cerr
617 ostream = self.ostream
598 618 ostream.flush()
599 619 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
600 620 ostream.flush()
@@ -615,15 +635,16 b' class VerboseTB(TBTools):'
615 635 traceback, to be used with alternate interpreters (because their own code
616 636 would appear in the traceback)."""
617 637
618 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
619 call_pdb = 0, include_vars=1):
638 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
639 tb_offset=0, long_header=False, include_vars=True):
620 640 """Specify traceback offset, headers and color scheme.
621 641
622 642 Define how many frames to drop from the tracebacks. Calling it with
623 643 tb_offset=1 allows use of this handler in interpreters which will have
624 644 their own code at the top of the traceback (VerboseTB will first
625 645 remove that frame before printing the traceback info)."""
626 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
646 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
647 ostream=ostream)
627 648 self.tb_offset = tb_offset
628 649 self.long_header = long_header
629 650 self.include_vars = include_vars
@@ -973,9 +994,11 b' class VerboseTB(TBTools):'
973 994 def handler(self, info=None):
974 995 (etype, evalue, etb) = info or sys.exc_info()
975 996 self.tb = etb
976 io.Term.cout.flush()
977 io.Term.cerr.write(self.text(etype, evalue, etb))
978 io.Term.cerr.write('\n')
997 ostream = self.ostream
998 ostream.flush()
999 ostream.write(self.text(etype, evalue, etb))
1000 ostream.write('\n')
1001 ostream.flush()
979 1002
980 1003 # Changed so an instance can just be called as VerboseTB_inst() and print
981 1004 # out the right info on its own.
@@ -1003,15 +1026,17 b' class FormattedTB(VerboseTB, ListTB):'
1003 1026 occurs with python programs that themselves execute other python code,
1004 1027 like Python shells). """
1005 1028
1006 def __init__(self, mode='Plain', color_scheme='Linux',
1007 tb_offset=0, long_header=0, call_pdb=0, include_vars=0):
1029 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1030 ostream=None,
1031 tb_offset=0, long_header=False, include_vars=False):
1008 1032
1009 1033 # NEVER change the order of this list. Put new modes at the end:
1010 1034 self.valid_modes = ['Plain','Context','Verbose']
1011 1035 self.verbose_modes = self.valid_modes[1:3]
1012 1036
1013 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
1014 call_pdb=call_pdb,include_vars=include_vars)
1037 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1038 ostream=ostream, tb_offset=tb_offset,
1039 long_header=long_header, include_vars=include_vars)
1015 1040
1016 1041 # Different types of tracebacks are joined with different separators to
1017 1042 # form a single string. They are taken from this dict
@@ -1103,11 +1128,9 b' class AutoFormattedTB(FormattedTB):'
1103 1128 per-call basis (this overrides temporarily the instance's tb_offset
1104 1129 given at initialization time. """
1105 1130
1131
1106 1132 if out is None:
1107 if self.out_stream == 'stdout':
1108 out = sys.stdout
1109 else:
1110 out = io.Term.cerr
1133 out = self.ostream
1111 1134 out.flush()
1112 1135 out.write(self.text(etype, evalue, etb, tb_offset))
1113 1136 out.write('\n')
@@ -146,9 +146,6 b' def start_ipython():'
146 146 # permanently since we'll be mocking interactive sessions.
147 147 shell.builtin_trap.set()
148 148
149 # Set error printing to stdout so nose can doctest exceptions
150 shell.InteractiveTB.out_stream = 'stdout'
151
152 149 # Modify the IPython system call with one that uses getoutput, so that we
153 150 # can capture subcommands and print them to Python's stdout, otherwise the
154 151 # doctest machinery would miss them.
General Comments 0
You need to be logged in to leave comments. Login now