distinguish capture_output from buffer_output

allow capturing output without silencing it,
which is useful for slimerjs,
which requires looking at output to determine failure.
This commit is contained in:
Min RK 2014-11-01 13:59:42 -07:00
parent e6939f9aa5
commit c88bd5025a
2 changed files with 18 additions and 12 deletions

View File

@ -35,6 +35,7 @@ from nose.plugins import Plugin
from nose.util import safe_str
from IPython.utils.process import is_cmd_found
from IPython.utils.py3compat import bytes_to_str
from IPython.utils.importstring import import_item
from IPython.testing.plugin.ipdoctest import IPythonDoctest
from IPython.external.decorators import KnownFailure, knownfailureif
@ -345,8 +346,9 @@ class ExclusionPlugin(Plugin):
class StreamCapturer(Thread):
daemon = True # Don't hang if main thread crashes
started = False
def __init__(self):
def __init__(self, echo=False):
super(StreamCapturer, self).__init__()
self.echo = echo
self.streams = []
self.buffer = BytesIO()
self.readfd, self.writefd = os.pipe()
@ -361,6 +363,8 @@ class StreamCapturer(Thread):
with self.buffer_lock:
self.buffer.write(chunk)
if self.echo:
sys.stdout.write(bytes_to_str(chunk))
os.close(self.readfd)
os.close(self.writefd)

View File

@ -81,18 +81,24 @@ class TestController(object):
"""
pass
def launch(self, buffer_output=False):
def launch(self, buffer_output=False, capture_output=False):
# print('*** ENV:', self.env) # dbg
# print('*** CMD:', self.cmd) # dbg
env = os.environ.copy()
env.update(self.env)
output = subprocess.PIPE if buffer_output else None
stdout = subprocess.STDOUT if buffer_output else None
self.process = subprocess.Popen(self.cmd, stdout=output,
stderr=stdout, env=env)
if buffer_output:
capture_output = True
self.stdout_capturer = c = StreamCapturer(echo=not buffer_output)
c.start()
stdout = c.writefd if capture_output else None
stderr = subprocess.STDOUT if capture_output else None
self.process = subprocess.Popen(self.cmd, stdout=stdout,
stderr=stderr, env=env)
def wait(self):
self.stdout, _ = self.process.communicate()
self.process.wait()
self.stdout_capturer.halt()
self.stdout = self.stdout_capturer.get_buffer()
return self.process.returncode
def print_extra_info(self):
@ -224,7 +230,6 @@ class JSController(TestController):
requirements = ['zmq', 'tornado', 'jinja2', 'casperjs', 'sqlite3',
'jsonschema']
display_slimer_output = False
def __init__(self, section, xunit=True, engine='phantomjs', url=None):
"""Create new test runner."""
@ -279,8 +284,7 @@ class JSController(TestController):
# If the engine is SlimerJS, we need to buffer the output because
# SlimerJS does not support exit codes, so CasperJS always returns 0.
if self.engine == 'slimerjs' and not buffer_output:
self.display_slimer_output = True
return super(JSController, self).launch(buffer_output=True)
return super(JSController, self).launch(capture_output=True)
else:
return super(JSController, self).launch(buffer_output=buffer_output)
@ -292,8 +296,6 @@ class JSController(TestController):
# errors. Otherwise, just return the return code.
if self.engine == 'slimerjs':
stdout = bytes_to_str(self.stdout)
if self.display_slimer_output:
print(stdout)
if ret != 0:
# This could still happen e.g. if it's stopped by SIGINT
return ret