From 12c5e74b84b75975b010bcebc693a18d994dddd9 Mon Sep 17 00:00:00 2001 From: warner Date: Sat, 9 Sep 2006 02:55:02 +0100 Subject: [PATCH] enhance IStatusLog.readlines to accept a channel= argument --- ChangeLog | 6 ++++-- buildbot/interfaces.py | 17 ++++++++++------- buildbot/status/builder.py | 5 +++-- buildbot/test/test_status.py | 9 ++++++--- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7eb2dc..1b6bbc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,10 @@ 2006-09-08 Brian Warner * buildbot/interfaces.py (IStatusLog.readlines): make it easier to - walk through StatusLogs one line at a time, mostly for the benefit of - ShellCommand.createSummary methods. + walk through StatusLogs one line at a time, mostly for the benefit + of ShellCommand.createSummary methods. You can either walk through + STDOUT or STDERR, but the default is STDOUT. + * buildbot/status/builder.py (LogFile.readlines): implement it. Note that this is not yet memory-efficient, it just pulls the whole file into RAM and then splits it up with a StringIO. diff --git a/buildbot/interfaces.py b/buildbot/interfaces.py index 213c3d6..58e3104 100644 --- a/buildbot/interfaces.py +++ b/buildbot/interfaces.py @@ -557,6 +557,11 @@ class IStatusEvent(Interface): """Returns a single string with the color that should be used to display this event. 'red' and 'yellow' are the most likely ones.""" + +LOG_CHANNEL_STDOUT = 0 +LOG_CHANNEL_STDERR = 1 +LOG_CHANNEL_HEADER = 2 + class IStatusLog(Interface): """I represent a single Log, which is a growing list of text items that contains some kind of output for a single BuildStep. I might be finished, @@ -661,9 +666,11 @@ class IStatusLog(Interface): """Return one big string with the contents of the Log. This merges all non-header chunks together.""" - def readlines(): - """Return a list (really an iterator) of newline-terminated lines, - excluding header chunks.""" + def readlines(channel=LOG_CHANNEL_STDOUT): + """Read lines from one channel of the logfile. This returns an + iterator that will provide single lines of text (including the + trailing newline). + """ def getTextWithHeaders(): """Return one big string with the contents of the Log. This merges @@ -674,10 +681,6 @@ class IStatusLog(Interface): 0 for stdout, 1 for stderr, 2 for header. (note that stderr is merged into stdout if PTYs are in use).""" -LOG_CHANNEL_STDOUT = 0 -LOG_CHANNEL_STDERR = 1 -LOG_CHANNEL_HEADER = 2 - class IStatusLogConsumer(Interface): """I am an object which can be passed to IStatusLog.subscribeConsumer(). I represent a target for writing the contents of an IStatusLog. This diff --git a/buildbot/status/builder.py b/buildbot/status/builder.py index 6fdfb21..5b44039 100644 --- a/buildbot/status/builder.py +++ b/buildbot/status/builder.py @@ -338,13 +338,14 @@ class LogFile: else: yield leftover - def readlines(self): + def readlines(self, channel=STDOUT): """Return an iterator that produces newline-terminated lines, excluding header chunks.""" # TODO: make this memory-efficient, by turning it into a generator # that retrieves chunks as necessary, like a pull-driven version of # twisted.protocols.basic.LineReceiver - io = StringIO(self.getText()) + alltext = "".join(self.getChunks([channel], onlyText=True)) + io = StringIO(alltext) return io.readlines() def subscribe(self, receiver, catchup): diff --git a/buildbot/test/test_status.py b/buildbot/test/test_status.py index 926177b..566f740 100644 --- a/buildbot/test/test_status.py +++ b/buildbot/test/test_status.py @@ -497,10 +497,13 @@ class Log(unittest.TestCase): l.addStdout("Last line\n") l.finish() alllines = list(l.readlines()) - self.failUnlessEqual(len(alllines), 5) + self.failUnlessEqual(len(alllines), 4) self.failUnlessEqual(alllines[0], "Some text\n") - self.failUnlessEqual(alllines[3], "Some Stderr\n") - self.failUnlessEqual(alllines[4], "Last line\n") + self.failUnlessEqual(alllines[2], "And Some More\n") + self.failUnlessEqual(alllines[3], "Last line\n") + stderr = list(l.readlines(interfaces.LOG_CHANNEL_STDERR)) + self.failUnlessEqual(len(stderr), 1) + self.failUnlessEqual(stderr[0], "Some Stderr\n") lines = l.readlines() if False: # TODO: l.readlines() is not yet an iterator # verify that it really is an iterator -- 2.11.4.GIT