##// 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 class TBTools(object):
313 class TBTools(object):
314 """Basic tools used by all traceback printer classes."""
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 # Number of frames to skip when reporting tracebacks
316 # Number of frames to skip when reporting tracebacks
323 tb_offset = 0
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 # Whether to call the interactive pdb debugger after printing
320 # Whether to call the interactive pdb debugger after printing
327 # tracebacks or not
321 # tracebacks or not
328 self.call_pdb = call_pdb
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 # Create color table
333 # Create color table
331 self.color_scheme_table = exception_colors()
334 self.color_scheme_table = exception_colors()
332
335
@@ -338,6 +341,25 b' class TBTools(object):'
338 else:
341 else:
339 self.pdb = None
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 def set_colors(self,*args,**kw):
363 def set_colors(self,*args,**kw):
342 """Shorthand access to the color table scheme selector method."""
364 """Shorthand access to the color table scheme selector method."""
343
365
@@ -402,8 +424,9 b' class ListTB(TBTools):'
402 Because they are meant to be called without a full traceback (only a
424 Because they are meant to be called without a full traceback (only a
403 list), instances of this class can't call the interactive pdb debugger."""
425 list), instances of this class can't call the interactive pdb debugger."""
404
426
405 def __init__(self,color_scheme = 'NoColor'):
427 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
406 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
428 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
429 ostream=ostream)
407
430
408 def __call__(self, etype, value, elist):
431 def __call__(self, etype, value, elist):
409 io.Term.cout.flush()
432 io.Term.cout.flush()
@@ -591,10 +614,7 b' class ListTB(TBTools):'
591 """
614 """
592 # This method needs to use __call__ from *this* class, not the one from
615 # This method needs to use __call__ from *this* class, not the one from
593 # a subclass whose signature or behavior may be different
616 # a subclass whose signature or behavior may be different
594 if self.out_stream == 'stdout':
617 ostream = self.ostream
595 ostream = sys.stdout
596 else:
597 ostream = io.Term.cerr
598 ostream.flush()
618 ostream.flush()
599 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
619 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
600 ostream.flush()
620 ostream.flush()
@@ -615,15 +635,16 b' class VerboseTB(TBTools):'
615 traceback, to be used with alternate interpreters (because their own code
635 traceback, to be used with alternate interpreters (because their own code
616 would appear in the traceback)."""
636 would appear in the traceback)."""
617
637
618 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
638 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
619 call_pdb = 0, include_vars=1):
639 tb_offset=0, long_header=False, include_vars=True):
620 """Specify traceback offset, headers and color scheme.
640 """Specify traceback offset, headers and color scheme.
621
641
622 Define how many frames to drop from the tracebacks. Calling it with
642 Define how many frames to drop from the tracebacks. Calling it with
623 tb_offset=1 allows use of this handler in interpreters which will have
643 tb_offset=1 allows use of this handler in interpreters which will have
624 their own code at the top of the traceback (VerboseTB will first
644 their own code at the top of the traceback (VerboseTB will first
625 remove that frame before printing the traceback info)."""
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 self.tb_offset = tb_offset
648 self.tb_offset = tb_offset
628 self.long_header = long_header
649 self.long_header = long_header
629 self.include_vars = include_vars
650 self.include_vars = include_vars
@@ -973,9 +994,11 b' class VerboseTB(TBTools):'
973 def handler(self, info=None):
994 def handler(self, info=None):
974 (etype, evalue, etb) = info or sys.exc_info()
995 (etype, evalue, etb) = info or sys.exc_info()
975 self.tb = etb
996 self.tb = etb
976 io.Term.cout.flush()
997 ostream = self.ostream
977 io.Term.cerr.write(self.text(etype, evalue, etb))
998 ostream.flush()
978 io.Term.cerr.write('\n')
999 ostream.write(self.text(etype, evalue, etb))
1000 ostream.write('\n')
1001 ostream.flush()
979
1002
980 # Changed so an instance can just be called as VerboseTB_inst() and print
1003 # Changed so an instance can just be called as VerboseTB_inst() and print
981 # out the right info on its own.
1004 # out the right info on its own.
@@ -1003,15 +1026,17 b' class FormattedTB(VerboseTB, ListTB):'
1003 occurs with python programs that themselves execute other python code,
1026 occurs with python programs that themselves execute other python code,
1004 like Python shells). """
1027 like Python shells). """
1005
1028
1006 def __init__(self, mode='Plain', color_scheme='Linux',
1029 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1007 tb_offset=0, long_header=0, call_pdb=0, include_vars=0):
1030 ostream=None,
1031 tb_offset=0, long_header=False, include_vars=False):
1008
1032
1009 # NEVER change the order of this list. Put new modes at the end:
1033 # NEVER change the order of this list. Put new modes at the end:
1010 self.valid_modes = ['Plain','Context','Verbose']
1034 self.valid_modes = ['Plain','Context','Verbose']
1011 self.verbose_modes = self.valid_modes[1:3]
1035 self.verbose_modes = self.valid_modes[1:3]
1012
1036
1013 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
1037 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1014 call_pdb=call_pdb,include_vars=include_vars)
1038 ostream=ostream, tb_offset=tb_offset,
1039 long_header=long_header, include_vars=include_vars)
1015
1040
1016 # Different types of tracebacks are joined with different separators to
1041 # Different types of tracebacks are joined with different separators to
1017 # form a single string. They are taken from this dict
1042 # form a single string. They are taken from this dict
@@ -1103,11 +1128,9 b' class AutoFormattedTB(FormattedTB):'
1103 per-call basis (this overrides temporarily the instance's tb_offset
1128 per-call basis (this overrides temporarily the instance's tb_offset
1104 given at initialization time. """
1129 given at initialization time. """
1105
1130
1131
1106 if out is None:
1132 if out is None:
1107 if self.out_stream == 'stdout':
1133 out = self.ostream
1108 out = sys.stdout
1109 else:
1110 out = io.Term.cerr
1111 out.flush()
1134 out.flush()
1112 out.write(self.text(etype, evalue, etb, tb_offset))
1135 out.write(self.text(etype, evalue, etb, tb_offset))
1113 out.write('\n')
1136 out.write('\n')
@@ -146,9 +146,6 b' def start_ipython():'
146 # permanently since we'll be mocking interactive sessions.
146 # permanently since we'll be mocking interactive sessions.
147 shell.builtin_trap.set()
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 # Modify the IPython system call with one that uses getoutput, so that we
149 # Modify the IPython system call with one that uses getoutput, so that we
153 # can capture subcommands and print them to Python's stdout, otherwise the
150 # can capture subcommands and print them to Python's stdout, otherwise the
154 # doctest machinery would miss them.
151 # doctest machinery would miss them.
General Comments 0
You need to be logged in to leave comments. Login now