# HG changeset patch # User cmlenz # Date 1119908055 0 # Node ID 02db4eabf0a9ff17ecbd9b1e526ac7e80e3bee99 # Parent ef78d71667ad8fd175b95e0be35cd255c4322d6e Fix splitting of output into text lines in {{{bitten.util.cmdline}}}. diff --git a/bitten/util/cmdline.py b/bitten/util/cmdline.py --- a/bitten/util/cmdline.py +++ b/bitten/util/cmdline.py @@ -18,8 +18,10 @@ # # Author: Christopher Lenz +import logging import os import os.path +import time class TimeoutError(Exception): @@ -40,7 +42,7 @@ command """ self.executable = executable - self.arguments = args or [] + self.arguments = [str(arg) for arg in args] self.cwd = cwd if self.cwd: assert os.path.isdir(self.cwd) @@ -55,6 +57,8 @@ import fcntl, popen2, select if self.cwd: os.chdir(self.cwd) + + logging.debug('Executing %s', self) pipe = popen2.Popen3([self.executable] + self.arguments, capturestderr=True) pipe.tochild.close() @@ -70,7 +74,7 @@ map(make_non_blocking, [out_file.fileno(), err_file.fileno()]) out_data, err_data = [], [] out_eof = err_eof = False - while True: + while not out_eof or not err_eof: to_check = [out_file] * (not out_eof) + [err_file] * (not err_eof) ready = select.select(to_check, [], [], timeout) if not ready[0]: @@ -92,9 +96,7 @@ err_lines = self._extract_lines(err_data) for out_line, err_line in self._combine(out_lines, err_lines): yield out_line, err_line - - if out_eof and err_eof: - break + time.sleep(.1) self.returncode = pipe.wait() def _combine(self, *iterables): @@ -112,27 +114,23 @@ yield tuple(to_yield) def _extract_lines(self, data): - def endswith_linesep(string): - for linesep in ('\n', '\r\n', '\r'): - if lines[0].endswith(linesep): - return True extracted = [] - while data: - chunk = data[0] - lines = chunk.splitlines(True) - if len(lines) > 1: - extracted += lines[:-1] - if endswith_linesep(lines[-1]): - extracted.append(lines[-1]) - data.pop(0) - else: - data[0] = lines[-1] - elif endswith_linesep(chunk): - extracted.append(chunk) - data.pop(0) - elif len(data) > 2: - data[1] = data[0] + data[1] - data.pop(0) + def _endswith_linesep(string): + for linesep in ('\n', '\r\n', '\r'): + if string.endswith(linesep): + return True + buf = ''.join(data) + lines = buf.splitlines(True) + if len(lines) > 1: + extracted += lines[:-1] + if _endswith_linesep(lines[-1]): + extracted.append(lines[-1]) + buf = '' else: - break + buf = lines[-1] + elif _endswith_linesep(buf): + extracted.append(buf) + buf = '' + data[:] = [buf] + return [line.rstrip() for line in extracted]