Skip to content

Commit

Permalink
Begin rework of TeeStream
Browse files Browse the repository at this point in the history
 - Switch TeeStream to be a generic "tee"
 - Add missing FILE methods to TeeStream
 - Switch to using six.StringIO
 - Switch ConsoleBuffer to use TeeStream
  • Loading branch information
John Siirola committed Apr 12, 2018
1 parent 27a8751 commit 86696e0
Showing 1 changed file with 31 additions and 30 deletions.
61 changes: 31 additions & 30 deletions pyutilib/misc/tee_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,44 @@
# _________________________________________________________________________

import sys
try:
from io import StringIO
except:
from StringIO import StringIO
import six


class TeeStream(object):
"""This class implements a simple 'Tee' of the specified python
stream. Since this presents a full file interface, TeeStream
objects may be arbitrarily nested."""
"""This class implements a simple output stream 'Tee'.
def __init__(self, stream):
self.stream = stream
self.buffer = StringIO()
This class presents a standard FILE interface. Methods called on
this object are passed verbatim to each of the underlying streams
passed to the constructor. Since this presents a full file
interface, TeeStream objects may be arbitrarily nested.
"""

def __init__(self, *streams):
if not streams:
raise ValueError("TeeStream not passed at least one output stream")
self.streams = stream

def write(self, data):
self.buffer.write(data)
self.stream.write(data)
for stream in self.streams:
stream.write(data)

def writelines(self, sequence):
for x in sequence:
self.write(x)

def reset(self):
self.buffer = StringIO()
def flush(self):
for stream in self.streams:
try:
stream.flush()
except:
pass

def close(self):
for stream in self.streams:
stream.close()

# TODO: determine if we should implement tell, seek, read, and readline


class ConsoleBuffer(object):
Expand All @@ -44,16 +57,6 @@ class ConsoleBuffer(object):
instead, we must replace the standard stdout and stderr objects with
our own duplicator."""

class _Duplicate(object):

def __init__(self, a, b):
self.a = a
self.b = b

def write(self, data):
self.a.write(data)
self.b.write(data)

def __init__(self):
self._dup_out = self._dup_err = None
self._raw_out = sys.stdout
Expand Down Expand Up @@ -82,9 +85,7 @@ def reset(self):
"(attempting to reset() when stderr has been redirected " \
"away from this buffer).")

self.out = StringIO()
self.err = StringIO()
self._dup_out = sys.stdout = \
ConsoleBuffer._Duplicate(self.out, self._raw_out)
self._dup_err = sys.stderr = \
ConsoleBuffer._Duplicate(self.err, self._raw_err)
self.out = six.StringIO()
self.err = six.StringIO()
self._dup_out = sys.stdout = TeeStream(self.out, self._raw_out)
self._dup_err = sys.stderr = TeeStream(self.err, self._raw_err)

0 comments on commit 86696e0

Please sign in to comment.