Index: third_party/buildbot_7_12/buildbot/status/client.py |
diff --git a/third_party/buildbot_7_12/buildbot/status/client.py b/third_party/buildbot_7_12/buildbot/status/client.py |
deleted file mode 100644 |
index ef2f9d4706b5181d033de7cc3307c3cb7e474fd6..0000000000000000000000000000000000000000 |
--- a/third_party/buildbot_7_12/buildbot/status/client.py |
+++ /dev/null |
@@ -1,567 +0,0 @@ |
-# -*- test-case-name: buildbot.test.test_status -*- |
- |
-from twisted.spread import pb |
-from twisted.python import components, log as twlog |
-from twisted.internet import reactor |
-from twisted.application import strports |
-from twisted.cred import portal, checkers |
- |
-from buildbot import interfaces |
-from zope.interface import Interface, implements |
-from buildbot.status import builder, base |
-from buildbot.changes import changes |
- |
-class IRemote(Interface): |
- pass |
- |
-def makeRemote(obj): |
- # we want IRemote(None) to be None, but you can't really do that with |
- # adapters, so we fake it |
- if obj is None: |
- return None |
- return IRemote(obj) |
- |
- |
-class RemoteBuildSet(pb.Referenceable): |
- def __init__(self, buildset): |
- self.b = buildset |
- |
- def remote_getSourceStamp(self): |
- return self.b.getSourceStamp() |
- |
- def remote_getReason(self): |
- return self.b.getReason() |
- |
- def remote_getID(self): |
- return self.b.getID() |
- |
- def remote_getBuilderNames(self): |
- return self.b.getBuilderNames() |
- |
- def remote_getBuildRequests(self): |
- """Returns a list of (builderName, BuildRequest) tuples.""" |
- return [(br.getBuilderName(), IRemote(br)) |
- for br in self.b.getBuildRequests()] |
- |
- def remote_isFinished(self): |
- return self.b.isFinished() |
- |
- def remote_waitUntilSuccess(self): |
- d = self.b.waitUntilSuccess() |
- d.addCallback(lambda res: self) |
- return d |
- |
- def remote_waitUntilFinished(self): |
- d = self.b.waitUntilFinished() |
- d.addCallback(lambda res: self) |
- return d |
- |
- def remote_getResults(self): |
- return self.b.getResults() |
- |
-components.registerAdapter(RemoteBuildSet, |
- interfaces.IBuildSetStatus, IRemote) |
- |
- |
-class RemoteBuilder(pb.Referenceable): |
- def __init__(self, builder): |
- self.b = builder |
- |
- def remote_getName(self): |
- return self.b.getName() |
- |
- def remote_getCategory(self): |
- return self.b.getCategory() |
- |
- def remote_getState(self): |
- state, builds = self.b.getState() |
- return (state, |
- None, # TODO: remove leftover ETA |
- [makeRemote(b) for b in builds]) |
- |
- def remote_getSlaves(self): |
- return [IRemote(s) for s in self.b.getSlaves()] |
- |
- def remote_getLastFinishedBuild(self): |
- return makeRemote(self.b.getLastFinishedBuild()) |
- |
- def remote_getCurrentBuilds(self): |
- return [IRemote(b) for b in self.b.getCurrentBuilds()] |
- |
- def remote_getBuild(self, number): |
- return makeRemote(self.b.getBuild(number)) |
- |
- def remote_getEvent(self, number): |
- return IRemote(self.b.getEvent(number)) |
- |
-components.registerAdapter(RemoteBuilder, |
- interfaces.IBuilderStatus, IRemote) |
- |
- |
-class RemoteBuildRequest(pb.Referenceable): |
- def __init__(self, buildreq): |
- self.b = buildreq |
- self.observers = [] |
- |
- def remote_getSourceStamp(self): |
- return self.b.getSourceStamp() |
- |
- def remote_getBuilderName(self): |
- return self.b.getBuilderName() |
- |
- def remote_subscribe(self, observer): |
- """The observer's remote_newbuild method will be called (with two |
- arguments: the RemoteBuild object, and our builderName) for each new |
- Build that is created to handle this BuildRequest.""" |
- self.observers.append(observer) |
- def send(bs): |
- d = observer.callRemote("newbuild", |
- IRemote(bs), self.b.getBuilderName()) |
- d.addErrback(lambda err: None) |
- reactor.callLater(0, self.b.subscribe, send) |
- |
- def remote_unsubscribe(self, observer): |
- # PB (well, at least oldpb) doesn't re-use RemoteReference instances, |
- # so sending the same object across the wire twice will result in two |
- # separate objects that compare as equal ('a is not b' and 'a == b'). |
- # That means we can't use a simple 'self.observers.remove(observer)' |
- # here. |
- for o in self.observers: |
- if o == observer: |
- self.observers.remove(o) |
- |
-components.registerAdapter(RemoteBuildRequest, |
- interfaces.IBuildRequestStatus, IRemote) |
- |
-class RemoteBuild(pb.Referenceable): |
- def __init__(self, build): |
- self.b = build |
- self.observers = [] |
- |
- def remote_getBuilderName(self): |
- return self.b.getBuilder().getName() |
- |
- def remote_getNumber(self): |
- return self.b.getNumber() |
- |
- def remote_getReason(self): |
- return self.b.getReason() |
- |
- def remote_getChanges(self): |
- return [IRemote(c) for c in self.b.getChanges()] |
- |
- def remote_getResponsibleUsers(self): |
- return self.b.getResponsibleUsers() |
- |
- def remote_getSteps(self): |
- return [IRemote(s) for s in self.b.getSteps()] |
- |
- def remote_getTimes(self): |
- return self.b.getTimes() |
- |
- def remote_isFinished(self): |
- return self.b.isFinished() |
- |
- def remote_waitUntilFinished(self): |
- # the Deferred returned by callRemote() will fire when this build is |
- # finished |
- d = self.b.waitUntilFinished() |
- d.addCallback(lambda res: self) |
- return d |
- |
- def remote_getETA(self): |
- return self.b.getETA() |
- |
- def remote_getCurrentStep(self): |
- return makeRemote(self.b.getCurrentStep()) |
- |
- def remote_getText(self): |
- return self.b.getText() |
- |
- def remote_getResults(self): |
- return self.b.getResults() |
- |
- def remote_getLogs(self): |
- logs = {} |
- for name,log in self.b.getLogs().items(): |
- logs[name] = IRemote(log) |
- return logs |
- |
- def remote_subscribe(self, observer, updateInterval=None): |
- """The observer will have remote_stepStarted(buildername, build, |
- stepname, step), remote_stepFinished(buildername, build, stepname, |
- step, results), and maybe remote_buildETAUpdate(buildername, build, |
- eta)) messages sent to it.""" |
- self.observers.append(observer) |
- s = BuildSubscriber(observer) |
- self.b.subscribe(s, updateInterval) |
- |
- def remote_unsubscribe(self, observer): |
- # TODO: is the observer automatically unsubscribed when the build |
- # finishes? Or are they responsible for unsubscribing themselves |
- # anyway? How do we avoid a race condition here? |
- for o in self.observers: |
- if o == observer: |
- self.observers.remove(o) |
- |
- |
-components.registerAdapter(RemoteBuild, |
- interfaces.IBuildStatus, IRemote) |
- |
-class BuildSubscriber: |
- def __init__(self, observer): |
- self.observer = observer |
- |
- def buildETAUpdate(self, build, eta): |
- self.observer.callRemote("buildETAUpdate", |
- build.getBuilder().getName(), |
- IRemote(build), |
- eta) |
- |
- def stepStarted(self, build, step): |
- self.observer.callRemote("stepStarted", |
- build.getBuilder().getName(), |
- IRemote(build), |
- step.getName(), IRemote(step)) |
- return None |
- |
- def stepFinished(self, build, step, results): |
- self.observer.callRemote("stepFinished", |
- build.getBuilder().getName(), |
- IRemote(build), |
- step.getName(), IRemote(step), |
- results) |
- |
- |
-class RemoteBuildStep(pb.Referenceable): |
- def __init__(self, step): |
- self.s = step |
- |
- def remote_getName(self): |
- return self.s.getName() |
- |
- def remote_getBuild(self): |
- return IRemote(self.s.getBuild()) |
- |
- def remote_getTimes(self): |
- return self.s.getTimes() |
- |
- def remote_getExpectations(self): |
- return self.s.getExpectations() |
- |
- def remote_getLogs(self): |
- logs = {} |
- for log in self.s.getLogs(): |
- logs[log.getName()] = IRemote(log) |
- return logs |
- |
- def remote_isFinished(self): |
- return self.s.isFinished() |
- |
- def remote_waitUntilFinished(self): |
- return self.s.waitUntilFinished() # returns a Deferred |
- |
- def remote_getETA(self): |
- return self.s.getETA() |
- |
- def remote_getText(self): |
- return self.s.getText() |
- |
- def remote_getResults(self): |
- return self.s.getResults() |
- |
-components.registerAdapter(RemoteBuildStep, |
- interfaces.IBuildStepStatus, IRemote) |
- |
-class RemoteSlave: |
- def __init__(self, slave): |
- self.s = slave |
- |
- def remote_getName(self): |
- return self.s.getName() |
- def remote_getAdmin(self): |
- return self.s.getAdmin() |
- def remote_getHost(self): |
- return self.s.getHost() |
- def remote_isConnected(self): |
- return self.s.isConnected() |
- |
-components.registerAdapter(RemoteSlave, |
- interfaces.ISlaveStatus, IRemote) |
- |
-class RemoteEvent: |
- def __init__(self, event): |
- self.e = event |
- |
- def remote_getTimes(self): |
- return self.s.getTimes() |
- def remote_getText(self): |
- return self.s.getText() |
- |
-components.registerAdapter(RemoteEvent, |
- interfaces.IStatusEvent, IRemote) |
- |
-class RemoteLog(pb.Referenceable): |
- def __init__(self, log): |
- self.l = log |
- |
- def remote_getName(self): |
- return self.l.getName() |
- |
- def remote_isFinished(self): |
- return self.l.isFinished() |
- def remote_waitUntilFinished(self): |
- d = self.l.waitUntilFinished() |
- d.addCallback(lambda res: self) |
- return d |
- |
- def remote_getText(self): |
- return self.l.getText() |
- def remote_getTextWithHeaders(self): |
- return self.l.getTextWithHeaders() |
- def remote_getChunks(self): |
- return self.l.getChunks() |
- # TODO: subscription interface |
- |
-components.registerAdapter(RemoteLog, builder.LogFile, IRemote) |
-# TODO: something similar for builder.HTMLLogfile ? |
- |
-class RemoteChange: |
- def __init__(self, change): |
- self.c = change |
- |
- def getWho(self): |
- return self.c.who |
- def getFiles(self): |
- return self.c.files |
- def getComments(self): |
- return self.c.comments |
- |
-components.registerAdapter(RemoteChange, changes.Change, IRemote) |
- |
- |
-class StatusClientPerspective(base.StatusReceiverPerspective): |
- |
- subscribed = None |
- client = None |
- |
- def __init__(self, status): |
- self.status = status # the IStatus |
- self.subscribed_to_builders = [] # Builders to which we're subscribed |
- self.subscribed_to = [] # everything else we're subscribed to |
- |
- def __getstate__(self): |
- d = self.__dict__.copy() |
- d['client'] = None |
- return d |
- |
- def attached(self, mind): |
- #twlog.msg("StatusClientPerspective.attached") |
- return self |
- |
- def detached(self, mind): |
- twlog.msg("PB client detached") |
- self.client = None |
- for name in self.subscribed_to_builders: |
- twlog.msg(" unsubscribing from Builder(%s)" % name) |
- self.status.getBuilder(name).unsubscribe(self) |
- for s in self.subscribed_to: |
- twlog.msg(" unsubscribe from %s" % s) |
- s.unsubscribe(self) |
- self.subscribed = None |
- |
- def perspective_subscribe(self, mode, interval, target): |
- """The remote client wishes to subscribe to some set of events. |
- 'target' will be sent remote messages when these events happen. |
- 'mode' indicates which events are desired: it is a string with one |
- of the following values: |
- |
- 'builders': builderAdded, builderRemoved |
- 'builds': those plus builderChangedState, buildStarted, buildFinished |
- 'steps': all those plus buildETAUpdate, stepStarted, stepFinished |
- 'logs': all those plus stepETAUpdate, logStarted, logFinished |
- 'full': all those plus logChunk (with the log contents) |
- |
- |
- Messages are defined by buildbot.interfaces.IStatusReceiver . |
- 'interval' is used to specify how frequently ETAUpdate messages |
- should be sent. |
- |
- Raising or lowering the subscription level will take effect starting |
- with the next build or step.""" |
- |
- assert mode in ("builders", "builds", "steps", "logs", "full") |
- assert target |
- twlog.msg("PB subscribe(%s)" % mode) |
- |
- self.client = target |
- self.subscribed = mode |
- self.interval = interval |
- self.subscribed_to.append(self.status) |
- # wait a moment before subscribing, so the new-builder messages |
- # won't appear before this remote method finishes |
- reactor.callLater(0, self.status.subscribe, self) |
- return None |
- |
- def perspective_unsubscribe(self): |
- twlog.msg("PB unsubscribe") |
- self.status.unsubscribe(self) |
- self.subscribed_to.remove(self.status) |
- self.client = None |
- |
- def perspective_getBuildSets(self): |
- """This returns tuples of (buildset, bsid), because that is much more |
- convenient for tryclient.""" |
- return [(IRemote(s), s.getID()) for s in self.status.getBuildSets()] |
- |
- def perspective_getBuilderNames(self): |
- return self.status.getBuilderNames() |
- |
- def perspective_getBuilder(self, name): |
- b = self.status.getBuilder(name) |
- return IRemote(b) |
- |
- def perspective_getSlave(self, name): |
- s = self.status.getSlave(name) |
- return IRemote(s) |
- |
- def perspective_ping(self): |
- """Ping method to allow pb clients to validate their connections.""" |
- return "pong" |
- |
- # IStatusReceiver methods, invoked if we've subscribed |
- |
- # mode >= builder |
- def builderAdded(self, name, builder): |
- self.client.callRemote("builderAdded", name, IRemote(builder)) |
- if self.subscribed in ("builds", "steps", "logs", "full"): |
- self.subscribed_to_builders.append(name) |
- return self |
- return None |
- |
- def builderChangedState(self, name, state): |
- self.client.callRemote("builderChangedState", name, state, None) |
- # TODO: remove leftover ETA argument |
- |
- def builderRemoved(self, name): |
- if name in self.subscribed_to_builders: |
- self.subscribed_to_builders.remove(name) |
- self.client.callRemote("builderRemoved", name) |
- |
- def buildsetSubmitted(self, buildset): |
- # TODO: deliver to client, somehow |
- pass |
- |
- # mode >= builds |
- def buildStarted(self, name, build): |
- self.client.callRemote("buildStarted", name, IRemote(build)) |
- if self.subscribed in ("steps", "logs", "full"): |
- self.subscribed_to.append(build) |
- return (self, self.interval) |
- return None |
- |
- def buildFinished(self, name, build, results): |
- if build in self.subscribed_to: |
- # we might have joined during the build |
- self.subscribed_to.remove(build) |
- self.client.callRemote("buildFinished", |
- name, IRemote(build), results) |
- |
- # mode >= steps |
- def buildETAUpdate(self, build, eta): |
- self.client.callRemote("buildETAUpdate", |
- build.getBuilder().getName(), IRemote(build), |
- eta) |
- |
- def stepStarted(self, build, step): |
- # we add some information here so the client doesn't have to do an |
- # extra round-trip |
- self.client.callRemote("stepStarted", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step)) |
- if self.subscribed in ("logs", "full"): |
- self.subscribed_to.append(step) |
- return (self, self.interval) |
- return None |
- |
- def stepFinished(self, build, step, results): |
- self.client.callRemote("stepFinished", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step), |
- results) |
- if step in self.subscribed_to: |
- # eventually (through some new subscription method) we could |
- # join in the middle of the step |
- self.subscribed_to.remove(step) |
- |
- # mode >= logs |
- def stepETAUpdate(self, build, step, ETA, expectations): |
- self.client.callRemote("stepETAUpdate", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step), |
- ETA, expectations) |
- |
- def logStarted(self, build, step, log): |
- # TODO: make the HTMLLog adapter |
- rlog = IRemote(log, None) |
- if not rlog: |
- print "hey, couldn't adapt %s to IRemote" % log |
- self.client.callRemote("logStarted", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step), |
- log.getName(), IRemote(log, None)) |
- if self.subscribed in ("full",): |
- self.subscribed_to.append(log) |
- return self |
- return None |
- |
- def logFinished(self, build, step, log): |
- self.client.callRemote("logFinished", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step), |
- log.getName(), IRemote(log, None)) |
- if log in self.subscribed_to: |
- self.subscribed_to.remove(log) |
- |
- # mode >= full |
- def logChunk(self, build, step, log, channel, text): |
- self.client.callRemote("logChunk", |
- build.getBuilder().getName(), IRemote(build), |
- step.getName(), IRemote(step), |
- log.getName(), IRemote(log), |
- channel, text) |
- |
- |
-class PBListener(base.StatusReceiverMultiService): |
- """I am a listener for PB-based status clients.""" |
- |
- compare_attrs = ["port", "cred"] |
- implements(portal.IRealm) |
- |
- def __init__(self, port, user="statusClient", passwd="clientpw"): |
- base.StatusReceiverMultiService.__init__(self) |
- if type(port) is int: |
- port = "tcp:%d" % port |
- self.port = port |
- self.cred = (user, passwd) |
- p = portal.Portal(self) |
- c = checkers.InMemoryUsernamePasswordDatabaseDontUse() |
- c.addUser(user, passwd) |
- p.registerChecker(c) |
- f = pb.PBServerFactory(p) |
- s = strports.service(port, f) |
- s.setServiceParent(self) |
- |
- def setServiceParent(self, parent): |
- base.StatusReceiverMultiService.setServiceParent(self, parent) |
- self.setup() |
- |
- def setup(self): |
- self.status = self.parent.getStatus() |
- |
- def requestAvatar(self, avatarID, mind, interface): |
- assert interface == pb.IPerspective |
- p = StatusClientPerspective(self.status) |
- p.attached(mind) # perhaps .callLater(0) ? |
- return (pb.IPerspective, p, |
- lambda p=p,mind=mind: p.detached(mind)) |