aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status')
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/__init__.py19
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/base.py104
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/build.py479
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/builder.py583
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildrequest.py149
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildset.py68
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildstep.py386
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/client.py586
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/event.py35
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/html.py21
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/logfile.py699
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/mail.py798
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/master.py475
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/persistent_queue.py382
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/progress.py324
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/results.py25
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/slave.py118
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_gerrit.py149
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_push.py442
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/testresult.py39
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/tinderbox.py276
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py0
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py35
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py220
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py188
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py806
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py607
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py332
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py632
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py66
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py136
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py71
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py744
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py275
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpgbin1822 -> 0 bytes
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css604
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.icobin1150 -> 0 bytes
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt11
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt12
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py341
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py1
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py80
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py147
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py87
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py54
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py177
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py118
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py57
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py121
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py203
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py741
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py96
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html32
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html11
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html10
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html37
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html238
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html45
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html184
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html50
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html68
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html76
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html19
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html73
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html20
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html76
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html21
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html276
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html37
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html5
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml40
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html18
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml39
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html16
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html23
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html288
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html31
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html65
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html30
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html28
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html90
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html23
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html36
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html18
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html35
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html61
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html34
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html29
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html27
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html66
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html140
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py84
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py90
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py813
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/words.py1097
95 files changed, 0 insertions, 17618 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/__init__.py
deleted file mode 100644
index 080f18f1..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import build, builder, buildstep, buildset, testresult, logfile
-import slave, master, buildrequest
-
-# styles.Versioned requires this, as it keys the version numbers on the fully
-# qualified class name; see master/buildbot/test/regressions/test_unpickling.py
-buildstep.BuildStepStatus.__module__ = 'buildbot.status.builder'
-build.BuildStatus.__module__ = 'buildbot.status.builder'
-
-# add all of these classes to builder; this is a form of late binding to allow
-# circular module references among the status modules
-builder.BuildStepStatus = buildstep.BuildStepStatus
-builder.BuildSetStatus = buildset.BuildSetStatus
-builder.TestResult = testresult.TestResult
-builder.LogFile = logfile.LogFile
-builder.HTMLLogFile = logfile.HTMLLogFile
-builder.SlaveStatus = slave.SlaveStatus
-builder.Status = master.Status
-builder.BuildStatus = build.BuildStatus
-builder.BuildRequestStatus = buildrequest.BuildRequestStatus
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/base.py
deleted file mode 100644
index 5efaf20f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/base.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from zope.interface import implements
-from twisted.application import service
-
-from buildbot.interfaces import IStatusReceiver
-from buildbot import util, pbutil
-
-class StatusReceiverBase:
- implements(IStatusReceiver)
-
- def requestSubmitted(self, request):
- pass
-
- def requestCancelled(self, builder, request):
- pass
-
- def buildsetSubmitted(self, buildset):
- pass
-
- def builderAdded(self, builderName, builder):
- pass
-
- def builderChangedState(self, builderName, state):
- pass
-
- def buildStarted(self, builderName, build):
- pass
-
- def buildETAUpdate(self, build, ETA):
- pass
-
- def changeAdded(self, change):
- pass
-
- def stepStarted(self, build, step):
- pass
-
- def stepTextChanged(self, build, step, text):
- pass
-
- def stepText2Changed(self, build, step, text2):
- pass
-
- def stepETAUpdate(self, build, step, ETA, expectations):
- pass
-
- def logStarted(self, build, step, log):
- pass
-
- def logChunk(self, build, step, log, channel, text):
- pass
-
- def logFinished(self, build, step, log):
- pass
-
- def stepFinished(self, build, step, results):
- pass
-
- def buildFinished(self, builderName, build, results):
- pass
-
- def builderRemoved(self, builderName):
- pass
-
- def slaveConnected(self, slaveName):
- pass
-
- def slaveDisconnected(self, slaveName):
- pass
-
- def checkConfig(self, otherStatusReceivers):
- pass
-
-class StatusReceiverMultiService(StatusReceiverBase, service.MultiService,
- util.ComparableMixin):
-
- def __init__(self):
- service.MultiService.__init__(self)
-
-class StatusReceiverService(StatusReceiverBase, service.Service,
- util.ComparableMixin):
- pass
-
-StatusReceiver = StatusReceiverService
-
-
-class StatusReceiverPerspective(StatusReceiver, pbutil.NewCredPerspective):
- implements(IStatusReceiver)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/build.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/build.py
deleted file mode 100644
index d1efa96d..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/build.py
+++ /dev/null
@@ -1,479 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from __future__ import with_statement
-
-import os, shutil, re
-from cPickle import dump
-from zope.interface import implements
-from twisted.python import log, runtime, components
-from twisted.persisted import styles
-from twisted.internet import reactor, defer
-from buildbot import interfaces, util, sourcestamp
-from buildbot.process import properties
-from buildbot.status.buildstep import BuildStepStatus
-
-class BuildStatus(styles.Versioned, properties.PropertiesMixin):
- implements(interfaces.IBuildStatus, interfaces.IStatusEvent)
-
- persistenceVersion = 4
- persistenceForgets = ( 'wasUpgraded', )
-
- sources = None
- reason = None
- changes = []
- blamelist = []
- progress = None
- started = None
- finished = None
- currentStep = None
- text = []
- results = None
- slavename = "???"
-
- set_runtime_properties = True
-
- # these lists/dicts are defined here so that unserialized instances have
- # (empty) values. They are set in __init__ to new objects to make sure
- # each instance gets its own copy.
- watchers = []
- updates = {}
- finishedWatchers = []
- testResults = {}
-
- def __init__(self, parent, master, number):
- """
- @type parent: L{BuilderStatus}
- @type number: int
- """
- assert interfaces.IBuilderStatus(parent)
- self.builder = parent
- self.master = master
- self.number = number
- self.watchers = []
- self.updates = {}
- self.finishedWatchers = []
- self.steps = []
- self.testResults = {}
- self.properties = properties.Properties()
-
- def __repr__(self):
- return "<%s #%s>" % (self.__class__.__name__, self.number)
-
- # IBuildStatus
-
- def getBuilder(self):
- """
- @rtype: L{BuilderStatus}
- """
- return self.builder
-
- def getNumber(self):
- return self.number
-
- def getPreviousBuild(self):
- if self.number == 0:
- return None
- return self.builder.getBuild(self.number-1)
-
- def getAllGotRevisions(self):
- all_got_revisions = self.properties.getProperty('got_revision', {})
- # For backwards compatibility all_got_revisions is a string if codebases
- # are not used. Convert to the default internal type (dict)
- if not isinstance(all_got_revisions, dict):
- all_got_revisions = {'': all_got_revisions}
- return all_got_revisions
-
- def getSourceStamps(self, absolute=False):
- sourcestamps = []
- if not absolute:
- sourcestamps.extend(self.sources)
- else:
- all_got_revisions = self.getAllGotRevisions() or {}
- # always make a new instance
- for ss in self.sources:
- if ss.codebase in all_got_revisions:
- got_revision = all_got_revisions[ss.codebase]
- sourcestamps.append(ss.getAbsoluteSourceStamp(got_revision))
- else:
- # No absolute revision information available
- # Probably build has been stopped before ending all sourcesteps
- # Return a clone with original revision
- sourcestamps.append(ss.clone())
- return sourcestamps
-
- def getReason(self):
- return self.reason
-
- def getChanges(self):
- return self.changes
-
- def getRevisions(self):
- revs = []
- for c in self.changes:
- rev = str(c.revision)
- if rev > 7: # for long hashes
- rev = rev[:7]
- revs.append(rev)
- return ", ".join(revs)
-
- def getResponsibleUsers(self):
- return self.blamelist
-
- def getInterestedUsers(self):
- # TODO: the Builder should add others: sheriffs, domain-owners
- return self.properties.getProperty('owners', [])
-
- def getSteps(self):
- """Return a list of IBuildStepStatus objects. For invariant builds
- (those which always use the same set of Steps), this should be the
- complete list, however some of the steps may not have started yet
- (step.getTimes()[0] will be None). For variant builds, this may not
- be complete (asking again later may give you more of them)."""
- return self.steps
-
- def getTimes(self):
- return (self.started, self.finished)
-
- _sentinel = [] # used as a sentinel to indicate unspecified initial_value
- def getSummaryStatistic(self, name, summary_fn, initial_value=_sentinel):
- """Summarize the named statistic over all steps in which it
- exists, using combination_fn and initial_value to combine multiple
- results into a single result. This translates to a call to Python's
- X{reduce}::
- return reduce(summary_fn, step_stats_list, initial_value)
- """
- step_stats_list = [
- st.getStatistic(name)
- for st in self.steps
- if st.hasStatistic(name) ]
- if initial_value is self._sentinel:
- return reduce(summary_fn, step_stats_list)
- else:
- return reduce(summary_fn, step_stats_list, initial_value)
-
- def isFinished(self):
- return (self.finished is not None)
-
- def waitUntilFinished(self):
- if self.finished:
- d = defer.succeed(self)
- else:
- d = defer.Deferred()
- self.finishedWatchers.append(d)
- return d
-
- # while the build is running, the following methods make sense.
- # Afterwards they return None
-
- def getETA(self):
- if self.finished is not None:
- return None
- if not self.progress:
- return None
- eta = self.progress.eta()
- if eta is None:
- return None
- return eta - util.now()
-
- def getCurrentStep(self):
- return self.currentStep
-
- # Once you know the build has finished, the following methods are legal.
- # Before ths build has finished, they all return None.
-
- def getText(self):
- text = []
- text.extend(self.text)
- for s in self.steps:
- text.extend(s.text2)
- return text
-
- def getResults(self):
- return self.results
-
- def getSlavename(self):
- return self.slavename
-
- def getTestResults(self):
- return self.testResults
-
- def getLogs(self):
- logs = []
- for s in self.steps:
- for loog in s.getLogs():
- logs.append(loog)
- return logs
-
- # subscription interface
-
- def subscribe(self, receiver, updateInterval=None):
- # will receive stepStarted and stepFinished messages
- # and maybe buildETAUpdate
- self.watchers.append(receiver)
- if updateInterval is not None:
- self.sendETAUpdate(receiver, updateInterval)
-
- def sendETAUpdate(self, receiver, updateInterval):
- self.updates[receiver] = None
- ETA = self.getETA()
- if ETA is not None:
- receiver.buildETAUpdate(self, self.getETA())
- # they might have unsubscribed during buildETAUpdate
- if receiver in self.watchers:
- self.updates[receiver] = reactor.callLater(updateInterval,
- self.sendETAUpdate,
- receiver,
- updateInterval)
-
- def unsubscribe(self, receiver):
- if receiver in self.watchers:
- self.watchers.remove(receiver)
- if receiver in self.updates:
- if self.updates[receiver] is not None:
- self.updates[receiver].cancel()
- del self.updates[receiver]
-
- # methods for the base.Build to invoke
-
- def addStepWithName(self, name):
- """The Build is setting up, and has added a new BuildStep to its
- list. Create a BuildStepStatus object to which it can send status
- updates."""
-
- s = BuildStepStatus(self, self.master, len(self.steps))
- s.setName(name)
- self.steps.append(s)
- return s
-
- def addTestResult(self, result):
- self.testResults[result.getName()] = result
-
- def setSourceStamps(self, sourceStamps):
- self.sources = sourceStamps
- self.changes = []
- for source in self.sources:
- self.changes.extend(source.changes)
-
- def setReason(self, reason):
- self.reason = reason
- def setBlamelist(self, blamelist):
- self.blamelist = blamelist
- def setProgress(self, progress):
- self.progress = progress
-
- def buildStarted(self, build):
- """The Build has been set up and is about to be started. It can now
- be safely queried, so it is time to announce the new build."""
-
- self.started = util.now()
- # now that we're ready to report status, let the BuilderStatus tell
- # the world about us
- self.builder.buildStarted(self)
-
- def setSlavename(self, slavename):
- self.slavename = slavename
-
- def setText(self, text):
- assert isinstance(text, (list, tuple))
- self.text = text
- def setResults(self, results):
- self.results = results
-
- def buildFinished(self):
- self.currentStep = None
- self.finished = util.now()
-
- for r in self.updates.keys():
- if self.updates[r] is not None:
- self.updates[r].cancel()
- del self.updates[r]
-
- watchers = self.finishedWatchers
- self.finishedWatchers = []
- for w in watchers:
- w.callback(self)
-
- # methods called by our BuildStepStatus children
-
- def stepStarted(self, step):
- self.currentStep = step
- for w in self.watchers:
- receiver = w.stepStarted(self, step)
- if receiver:
- if type(receiver) == type(()):
- step.subscribe(receiver[0], receiver[1])
- else:
- step.subscribe(receiver)
- d = step.waitUntilFinished()
- d.addCallback(lambda step: step.unsubscribe(receiver))
-
- step.waitUntilFinished().addCallback(self._stepFinished)
-
- def _stepFinished(self, step):
- results = step.getResults()
- for w in self.watchers:
- w.stepFinished(self, step, results)
-
- # methods called by our BuilderStatus parent
-
- def pruneSteps(self):
- # this build is very old: remove the build steps too
- self.steps = []
-
- # persistence stuff
-
- def generateLogfileName(self, stepname, logname):
- """Return a filename (relative to the Builder's base directory) where
- the logfile's contents can be stored uniquely.
-
- The base filename is made by combining our build number, the Step's
- name, and the log's name, then removing unsuitable characters. The
- filename is then made unique by appending _0, _1, etc, until it does
- not collide with any other logfile.
-
- These files are kept in the Builder's basedir (rather than a
- per-Build subdirectory) because that makes cleanup easier: cron and
- find will help get rid of the old logs, but the empty directories are
- more of a hassle to remove."""
-
- starting_filename = "%d-log-%s-%s" % (self.number, stepname, logname)
- starting_filename = re.sub(r'[^\w\.\-]', '_', starting_filename)
- # now make it unique
- unique_counter = 0
- filename = starting_filename
- while filename in [l.filename
- for step in self.steps
- for l in step.getLogs()
- if l.filename]:
- filename = "%s_%d" % (starting_filename, unique_counter)
- unique_counter += 1
- return filename
-
- def __getstate__(self):
- d = styles.Versioned.__getstate__(self)
- # for now, a serialized Build is always "finished". We will never
- # save unfinished builds.
- if not self.finished:
- d['finished'] = util.now()
- # TODO: push an "interrupted" step so it is clear that the build
- # was interrupted. The builder will have a 'shutdown' event, but
- # someone looking at just this build will be confused as to why
- # the last log is truncated.
- for k in [ 'builder', 'watchers', 'updates', 'finishedWatchers',
- 'master' ]:
- if k in d: del d[k]
- return d
-
- def __setstate__(self, d):
- styles.Versioned.__setstate__(self, d)
- self.watchers = []
- self.updates = {}
- self.finishedWatchers = []
-
- def setProcessObjects(self, builder, master):
- self.builder = builder
- self.master = master
- for step in self.steps:
- step.setProcessObjects(self, master)
- def upgradeToVersion1(self):
- if hasattr(self, "sourceStamp"):
- # the old .sourceStamp attribute wasn't actually very useful
- maxChangeNumber, patch = self.sourceStamp
- changes = getattr(self, 'changes', [])
- source = sourcestamp.SourceStamp(branch=None,
- revision=None,
- patch=patch,
- changes=changes)
- self.source = source
- self.changes = source.changes
- del self.sourceStamp
- self.wasUpgraded = True
-
- def upgradeToVersion2(self):
- self.properties = {}
- self.wasUpgraded = True
-
- def upgradeToVersion3(self):
- # in version 3, self.properties became a Properties object
- propdict = self.properties
- self.properties = properties.Properties()
- self.properties.update(propdict, "Upgrade from previous version")
- self.wasUpgraded = True
-
- def upgradeToVersion4(self):
- # buildstatus contains list of sourcestamps, convert single to list
- if hasattr(self, "source"):
- self.sources = [self.source]
- del self.source
- self.wasUpgraded = True
-
- def checkLogfiles(self):
- # check that all logfiles exist, and remove references to any that
- # have been deleted (e.g., by purge())
- for s in self.steps:
- s.checkLogfiles()
-
- def saveYourself(self):
- filename = os.path.join(self.builder.basedir, "%d" % self.number)
- if os.path.isdir(filename):
- # leftover from 0.5.0, which stored builds in directories
- shutil.rmtree(filename, ignore_errors=True)
- tmpfilename = filename + ".tmp"
- try:
- with open(tmpfilename, "wb") as f:
- dump(self, f, -1)
- if runtime.platformType == 'win32':
- # windows cannot rename a file on top of an existing one, so
- # fall back to delete-first. There are ways this can fail and
- # lose the builder's history, so we avoid using it in the
- # general (non-windows) case
- if os.path.exists(filename):
- os.unlink(filename)
- os.rename(tmpfilename, filename)
- except:
- log.msg("unable to save build %s-#%d" % (self.builder.name,
- self.number))
- log.err()
-
- def asDict(self):
- result = {}
- # Constant
- result['builderName'] = self.builder.name
- result['number'] = self.getNumber()
- result['sourceStamps'] = [ss.asDict() for ss in self.getSourceStamps()]
- result['reason'] = self.getReason()
- result['blame'] = self.getResponsibleUsers()
-
- # Transient
- result['properties'] = self.getProperties().asList()
- result['times'] = self.getTimes()
- result['text'] = self.getText()
- result['results'] = self.getResults()
- result['slave'] = self.getSlavename()
- # TODO(maruel): Add.
- #result['test_results'] = self.getTestResults()
- result['logs'] = [[l.getName(),
- self.builder.status.getURLForThing(l)] for l in self.getLogs()]
- result['eta'] = self.getETA()
- result['steps'] = [bss.asDict() for bss in self.steps]
- if self.getCurrentStep():
- result['currentStep'] = self.getCurrentStep().asDict()
- else:
- result['currentStep'] = None
- return result
-
-components.registerAdapter(lambda build_status : build_status.properties,
- BuildStatus, interfaces.IProperties)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/builder.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/builder.py
deleted file mode 100644
index 8430d13e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/builder.py
+++ /dev/null
@@ -1,583 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from __future__ import with_statement
-
-
-import os, re, itertools
-from cPickle import load, dump
-
-from zope.interface import implements
-from twisted.python import log, runtime
-from twisted.persisted import styles
-from buildbot import interfaces, util
-from buildbot.util.lru import LRUCache
-from buildbot.status.event import Event
-from buildbot.status.build import BuildStatus
-from buildbot.status.buildrequest import BuildRequestStatus
-
-# user modules expect these symbols to be present here
-from buildbot.status.results import SUCCESS, WARNINGS, FAILURE, SKIPPED
-from buildbot.status.results import EXCEPTION, RETRY, Results, worst_status
-_hush_pyflakes = [ SUCCESS, WARNINGS, FAILURE, SKIPPED,
- EXCEPTION, RETRY, Results, worst_status ]
-
-class BuilderStatus(styles.Versioned):
- """I handle status information for a single process.build.Builder object.
- That object sends status changes to me (frequently as Events), and I
- provide them on demand to the various status recipients, like the HTML
- waterfall display and the live status clients. It also sends build
- summaries to me, which I log and provide to status clients who aren't
- interested in seeing details of the individual build steps.
-
- I am responsible for maintaining the list of historic Events and Builds,
- pruning old ones, and loading them from / saving them to disk.
-
- I live in the buildbot.process.build.Builder object, in the
- .builder_status attribute.
-
- @type category: string
- @ivar category: user-defined category this builder belongs to; can be
- used to filter on in status clients
- """
-
- implements(interfaces.IBuilderStatus, interfaces.IEventSource)
-
- persistenceVersion = 1
- persistenceForgets = ( 'wasUpgraded', )
-
- category = None
- currentBigState = "offline" # or idle/waiting/interlocked/building
- basedir = None # filled in by our parent
-
- def __init__(self, buildername, category, master, description):
- self.name = buildername
- self.category = category
- self.description = description
- self.master = master
-
- self.slavenames = []
- self.events = []
- # these three hold Events, and are used to retrieve the current
- # state of the boxes.
- self.lastBuildStatus = None
- #self.currentBig = None
- #self.currentSmall = None
- self.currentBuilds = []
- self.nextBuild = None
- self.watchers = []
- self.buildCache = LRUCache(self.cacheMiss)
-
- # persistence
-
- def __getstate__(self):
- # when saving, don't record transient stuff like what builds are
- # currently running, because they won't be there when we start back
- # up. Nor do we save self.watchers, nor anything that gets set by our
- # parent like .basedir and .status
- d = styles.Versioned.__getstate__(self)
- d['watchers'] = []
- del d['buildCache']
- for b in self.currentBuilds:
- b.saveYourself()
- # TODO: push a 'hey, build was interrupted' event
- del d['currentBuilds']
- d.pop('pendingBuilds', None)
- del d['currentBigState']
- del d['basedir']
- del d['status']
- del d['nextBuildNumber']
- del d['master']
- return d
-
- def __setstate__(self, d):
- # when loading, re-initialize the transient stuff. Remember that
- # upgradeToVersion1 and such will be called after this finishes.
- styles.Versioned.__setstate__(self, d)
- self.buildCache = LRUCache(self.cacheMiss)
- self.currentBuilds = []
- self.watchers = []
- self.slavenames = []
- # self.basedir must be filled in by our parent
- # self.status must be filled in by our parent
- # self.master must be filled in by our parent
-
- def upgradeToVersion1(self):
- if hasattr(self, 'slavename'):
- self.slavenames = [self.slavename]
- del self.slavename
- if hasattr(self, 'nextBuildNumber'):
- del self.nextBuildNumber # determineNextBuildNumber chooses this
- self.wasUpgraded = True
-
- def determineNextBuildNumber(self):
- """Scan our directory of saved BuildStatus instances to determine
- what our self.nextBuildNumber should be. Set it one larger than the
- highest-numbered build we discover. This is called by the top-level
- Status object shortly after we are created or loaded from disk.
- """
- existing_builds = [int(f)
- for f in os.listdir(self.basedir)
- if re.match("^\d+$", f)]
- if existing_builds:
- self.nextBuildNumber = max(existing_builds) + 1
- else:
- self.nextBuildNumber = 0
-
- def saveYourself(self):
- for b in self.currentBuilds:
- if not b.isFinished:
- # interrupted build, need to save it anyway.
- # BuildStatus.saveYourself will mark it as interrupted.
- b.saveYourself()
- filename = os.path.join(self.basedir, "builder")
- tmpfilename = filename + ".tmp"
- try:
- with open(tmpfilename, "wb") as f:
- dump(self, f, -1)
- if runtime.platformType == 'win32':
- # windows cannot rename a file on top of an existing one
- if os.path.exists(filename):
- os.unlink(filename)
- os.rename(tmpfilename, filename)
- except:
- log.msg("unable to save builder %s" % self.name)
- log.err()
-
- # build cache management
-
- def setCacheSize(self, size):
- self.buildCache.set_max_size(size)
-
- def makeBuildFilename(self, number):
- return os.path.join(self.basedir, "%d" % number)
-
- def getBuildByNumber(self, number):
- return self.buildCache.get(number)
-
- def loadBuildFromFile(self, number):
- filename = self.makeBuildFilename(number)
- try:
- log.msg("Loading builder %s's build %d from on-disk pickle"
- % (self.name, number))
- with open(filename, "rb") as f:
- build = load(f)
- build.setProcessObjects(self, self.master)
-
- # (bug #1068) if we need to upgrade, we probably need to rewrite
- # this pickle, too. We determine this by looking at the list of
- # Versioned objects that have been unpickled, and (after doUpgrade)
- # checking to see if any of them set wasUpgraded. The Versioneds'
- # upgradeToVersionNN methods all set this.
- versioneds = styles.versionedsToUpgrade
- styles.doUpgrade()
- if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]:
- log.msg("re-writing upgraded build pickle")
- build.saveYourself()
-
- # check that logfiles exist
- build.checkLogfiles()
- return build
- except IOError:
- raise IndexError("no such build %d" % number)
- except EOFError:
- raise IndexError("corrupted build pickle %d" % number)
-
- def cacheMiss(self, number, **kwargs):
- # If kwargs['val'] exists, this is a new value being added to
- # the cache. Just return it.
- if 'val' in kwargs:
- return kwargs['val']
-
- # first look in currentBuilds
- for b in self.currentBuilds:
- if b.number == number:
- return b
-
- # then fall back to loading it from disk
- return self.loadBuildFromFile(number)
-
- def prune(self, events_only=False):
- # begin by pruning our own events
- eventHorizon = self.master.config.eventHorizon
- self.events = self.events[-eventHorizon:]
-
- if events_only:
- return
-
- # get the horizons straight
- buildHorizon = self.master.config.buildHorizon
- if buildHorizon is not None:
- earliest_build = self.nextBuildNumber - buildHorizon
- else:
- earliest_build = 0
-
- logHorizon = self.master.config.logHorizon
- if logHorizon is not None:
- earliest_log = self.nextBuildNumber - logHorizon
- else:
- earliest_log = 0
-
- if earliest_log < earliest_build:
- earliest_log = earliest_build
-
- if earliest_build == 0:
- return
-
- # skim the directory and delete anything that shouldn't be there anymore
- build_re = re.compile(r"^([0-9]+)$")
- build_log_re = re.compile(r"^([0-9]+)-.*$")
- # if the directory doesn't exist, bail out here
- if not os.path.exists(self.basedir):
- return
-
- for filename in os.listdir(self.basedir):
- num = None
- mo = build_re.match(filename)
- is_logfile = False
- if mo:
- num = int(mo.group(1))
- else:
- mo = build_log_re.match(filename)
- if mo:
- num = int(mo.group(1))
- is_logfile = True
-
- if num is None: continue
- if num in self.buildCache.cache: continue
-
- if (is_logfile and num < earliest_log) or num < earliest_build:
- pathname = os.path.join(self.basedir, filename)
- log.msg("pruning '%s'" % pathname)
- try: os.unlink(pathname)
- except OSError: pass
-
- # IBuilderStatus methods
- def getName(self):
- # if builderstatus page does show not up without any reason then
- # str(self.name) may be a workaround
- return self.name
-
- def setDescription(self, description):
- # used during reconfig
- self.description = description
-
- def getDescription(self):
- return self.description
-
- def getState(self):
- return (self.currentBigState, self.currentBuilds)
-
- def getSlaves(self):
- return [self.status.getSlave(name) for name in self.slavenames]
-
- def getPendingBuildRequestStatuses(self):
- db = self.status.master.db
- d = db.buildrequests.getBuildRequests(claimed=False,
- buildername=self.name)
- def make_statuses(brdicts):
- return [BuildRequestStatus(self.name, brdict['brid'],
- self.status)
- for brdict in brdicts]
- d.addCallback(make_statuses)
- return d
-
- def getCurrentBuilds(self):
- return self.currentBuilds
-
- def getLastFinishedBuild(self):
- b = self.getBuild(-1)
- if not (b and b.isFinished()):
- b = self.getBuild(-2)
- return b
-
- def setCategory(self, category):
- # used during reconfig
- self.category = category
-
- def getCategory(self):
- return self.category
-
- def getBuild(self, number):
- if number < 0:
- number = self.nextBuildNumber + number
- if number < 0 or number >= self.nextBuildNumber:
- return None
-
- try:
- return self.getBuildByNumber(number)
- except IndexError:
- return None
-
- def getEvent(self, number):
- try:
- return self.events[number]
- except IndexError:
- return None
-
- def _getBuildBranches(self, build):
- return set([ ss.branch
- for ss in build.getSourceStamps() ])
-
- def generateFinishedBuilds(self, branches=[],
- num_builds=None,
- max_buildnum=None,
- finished_before=None,
- results=None,
- max_search=200):
- got = 0
- branches = set(branches)
- for Nb in itertools.count(1):
- if Nb > self.nextBuildNumber:
- break
- if Nb > max_search:
- break
- build = self.getBuild(-Nb)
- if build is None:
- continue
- if max_buildnum is not None:
- if build.getNumber() > max_buildnum:
- continue
- if not build.isFinished():
- continue
- if finished_before is not None:
- start, end = build.getTimes()
- if end >= finished_before:
- continue
- # if we were asked to filter on branches, and none of the
- # sourcestamps match, skip this build
- if branches and not branches & self._getBuildBranches(build):
- continue
- if results is not None:
- if build.getResults() not in results:
- continue
- got += 1
- yield build
- if num_builds is not None:
- if got >= num_builds:
- return
-
- def eventGenerator(self, branches=[], categories=[], committers=[], minTime=0):
- """This function creates a generator which will provide all of this
- Builder's status events, starting with the most recent and
- progressing backwards in time. """
-
- # remember the oldest-to-earliest flow here. "next" means earlier.
-
- # TODO: interleave build steps and self.events by timestamp.
- # TODO: um, I think we're already doing that.
-
- # TODO: there's probably something clever we could do here to
- # interleave two event streams (one from self.getBuild and the other
- # from self.getEvent), which would be simpler than this control flow
-
- eventIndex = -1
- e = self.getEvent(eventIndex)
- branches = set(branches)
- for Nb in range(1, self.nextBuildNumber+1):
- b = self.getBuild(-Nb)
- if not b:
- # HACK: If this is the first build we are looking at, it is
- # possible it's in progress but locked before it has written a
- # pickle; in this case keep looking.
- if Nb == 1:
- continue
- break
- if b.getTimes()[0] < minTime:
- break
- # if we were asked to filter on branches, and none of the
- # sourcestamps match, skip this build
- if branches and not branches & self._getBuildBranches(b):
- continue
- if categories and not b.getBuilder().getCategory() in categories:
- continue
- if committers and not [True for c in b.getChanges() if c.who in committers]:
- continue
- steps = b.getSteps()
- for Ns in range(1, len(steps)+1):
- if steps[-Ns].started:
- step_start = steps[-Ns].getTimes()[0]
- while e is not None and e.getTimes()[0] > step_start:
- yield e
- eventIndex -= 1
- e = self.getEvent(eventIndex)
- yield steps[-Ns]
- yield b
- while e is not None:
- yield e
- eventIndex -= 1
- e = self.getEvent(eventIndex)
- if e and e.getTimes()[0] < minTime:
- break
-
- def subscribe(self, receiver):
- # will get builderChangedState, buildStarted, buildFinished,
- # requestSubmitted, requestCancelled. Note that a request which is
- # resubmitted (due to a slave disconnect) will cause requestSubmitted
- # to be invoked multiple times.
- self.watchers.append(receiver)
- self.publishState(receiver)
- # our parent Status provides requestSubmitted and requestCancelled
- self.status._builder_subscribe(self.name, receiver)
-
- def unsubscribe(self, receiver):
- self.watchers.remove(receiver)
- self.status._builder_unsubscribe(self.name, receiver)
-
- ## Builder interface (methods called by the Builder which feeds us)
-
- def setSlavenames(self, names):
- self.slavenames = names
-
- def addEvent(self, text=[]):
- # this adds a duration event. When it is done, the user should call
- # e.finish(). They can also mangle it by modifying .text
- e = Event()
- e.started = util.now()
- e.text = text
- self.events.append(e)
- self.prune(events_only=True)
- return e # they are free to mangle it further
-
- def addPointEvent(self, text=[]):
- # this adds a point event, one which occurs as a single atomic
- # instant of time.
- e = Event()
- e.started = util.now()
- e.finished = 0
- e.text = text
- self.events.append(e)
- self.prune(events_only=True)
- return e # for consistency, but they really shouldn't touch it
-
- def setBigState(self, state):
- needToUpdate = state != self.currentBigState
- self.currentBigState = state
- if needToUpdate:
- self.publishState()
-
- def publishState(self, target=None):
- state = self.currentBigState
-
- if target is not None:
- # unicast
- target.builderChangedState(self.name, state)
- return
- for w in self.watchers:
- try:
- w.builderChangedState(self.name, state)
- except:
- log.msg("Exception caught publishing state to %r" % w)
- log.err()
-
- def newBuild(self):
- """The Builder has decided to start a build, but the Build object is
- not yet ready to report status (it has not finished creating the
- Steps). Create a BuildStatus object that it can use."""
- number = self.nextBuildNumber
- self.nextBuildNumber += 1
- # TODO: self.saveYourself(), to make sure we don't forget about the
- # build number we've just allocated. This is not quite as important
- # as it was before we switch to determineNextBuildNumber, but I think
- # it may still be useful to have the new build save itself.
- s = BuildStatus(self, self.master, number)
- s.waitUntilFinished().addCallback(self._buildFinished)
- return s
-
- # buildStarted is called by our child BuildStatus instances
- def buildStarted(self, s):
- """Now the BuildStatus object is ready to go (it knows all of its
- Steps, its ETA, etc), so it is safe to notify our watchers."""
-
- assert s.builder is self # paranoia
- assert s not in self.currentBuilds
- self.currentBuilds.append(s)
- self.buildCache.get(s.number, val=s)
-
- # now that the BuildStatus is prepared to answer queries, we can
- # announce the new build to all our watchers
-
- for w in self.watchers: # TODO: maybe do this later? callLater(0)?
- try:
- receiver = w.buildStarted(self.getName(), s)
- if receiver:
- if type(receiver) == type(()):
- s.subscribe(receiver[0], receiver[1])
- else:
- s.subscribe(receiver)
- d = s.waitUntilFinished()
- d.addCallback(lambda s: s.unsubscribe(receiver))
- except:
- log.msg("Exception caught notifying %r of buildStarted event" % w)
- log.err()
-
- def _buildFinished(self, s):
- assert s in self.currentBuilds
- s.saveYourself()
- self.currentBuilds.remove(s)
-
- name = self.getName()
- results = s.getResults()
- for w in self.watchers:
- try:
- w.buildFinished(name, s, results)
- except:
- log.msg("Exception caught notifying %r of buildFinished event" % w)
- log.err()
-
- self.prune() # conserve disk
-
-
- def asDict(self):
- result = {}
- # Constant
- # TODO(maruel): Fix me. We don't want to leak the full path.
- result['basedir'] = os.path.basename(self.basedir)
- result['category'] = self.category
- result['slaves'] = self.slavenames
- result['schedulers'] = [ s.name
- for s in self.status.master.allSchedulers()
- if self.name in s.builderNames ]
- #result['url'] = self.parent.getURLForThing(self)
- # TODO(maruel): Add cache settings? Do we care?
-
- # Transient
- # Collect build numbers.
- # Important: Only grab the *cached* builds numbers to reduce I/O.
- current_builds = [b.getNumber() for b in self.currentBuilds]
- cached_builds = list(set(self.buildCache.keys() + current_builds))
- cached_builds.sort()
- result['cachedBuilds'] = cached_builds
- result['currentBuilds'] = current_builds
- result['state'] = self.getState()[0]
- # lies, but we don't have synchronous access to this info; use
- # asDict_async instead
- result['pendingBuilds'] = 0
- return result
-
- def asDict_async(self):
- """Just like L{asDict}, but with a nonzero pendingBuilds."""
- result = self.asDict()
- d = self.getPendingBuildRequestStatuses()
- def combine(statuses):
- result['pendingBuilds'] = len(statuses)
- return result
- d.addCallback(combine)
- return d
-
- def getMetrics(self):
- return self.botmaster.parent.metrics
-
-# vim: set ts=4 sts=4 sw=4 et:
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildrequest.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildrequest.py
deleted file mode 100644
index 1f52902e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildrequest.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from zope.interface import implements
-from twisted.python import log
-from twisted.internet import defer
-from buildbot import interfaces
-from buildbot.util.eventual import eventually
-
-class BuildRequestStatus:
- implements(interfaces.IBuildRequestStatus)
-
- def __init__(self, buildername, brid, status):
- self.buildername = buildername
- self.brid = brid
- self.status = status
- self.master = status.master
-
- self._buildrequest = None
- self._buildrequest_lock = defer.DeferredLock()
-
- @defer.inlineCallbacks
- def _getBuildRequest(self):
- """
- Get the underlying BuildRequest object for this status. This is a slow
- operation!
-
- @returns: BuildRequest instance or None, via Deferred
- """
- # late binding to avoid an import cycle
- from buildbot.process import buildrequest
-
- # this is only set once, so no need to lock if we already have it
- if self._buildrequest:
- defer.returnValue(self._buildrequest)
- return
-
- yield self._buildrequest_lock.acquire()
-
- try:
- if not self._buildrequest:
- brd = yield self.master.db.buildrequests.getBuildRequest(
- self.brid)
-
- br = yield buildrequest.BuildRequest.fromBrdict(self.master,
- brd)
- self._buildrequest = br
- except: # try/finally isn't allowed in generators in older Pythons
- self._buildrequest_lock.release()
- raise
-
- self._buildrequest_lock.release()
-
- defer.returnValue(self._buildrequest)
-
- def buildStarted(self, build):
- self.status._buildrequest_buildStarted(build.status)
- self.builds.append(build.status)
-
- # methods called by our clients
- @defer.inlineCallbacks
- def getBsid(self):
- br = yield self._getBuildRequest()
- defer.returnValue(br.bsid)
-
- @defer.inlineCallbacks
- def getBuildProperties(self):
- br = yield self._getBuildRequest()
- defer.returnValue(br.properties)
-
- @defer.inlineCallbacks
- def getSourceStamp(self):
- br = yield self._getBuildRequest()
- defer.returnValue(br.source)
-
- def getBuilderName(self):
- return self.buildername
-
- @defer.inlineCallbacks
- def getBuilds(self):
- builder = self.status.getBuilder(self.getBuilderName())
- builds = []
-
- bdicts = yield self.master.db.builds.getBuildsForRequest(self.brid)
-
- buildnums = sorted([ bdict['number'] for bdict in bdicts ])
-
- for buildnum in buildnums:
- bs = builder.getBuild(buildnum)
- if bs:
- builds.append(bs)
- defer.returnValue(builds)
-
- def subscribe(self, observer):
- d = self.getBuilds()
- def notify_old(oldbuilds):
- for bs in oldbuilds:
- eventually(observer, bs)
- d.addCallback(notify_old)
- d.addCallback(lambda _ :
- self.status._buildrequest_subscribe(self.brid, observer))
- d.addErrback(log.err, 'while notifying subscribers')
-
- def unsubscribe(self, observer):
- self.status._buildrequest_unsubscribe(self.brid, observer)
-
- @defer.inlineCallbacks
- def getSubmitTime(self):
- br = yield self._getBuildRequest()
- defer.returnValue(br.submittedAt)
-
- def asDict(self):
- result = {}
- # Constant
- result['source'] = None # not available sync, sorry
- result['builderName'] = self.buildername
- result['submittedAt'] = None # not availably sync, sorry
-
- # Transient
- result['builds'] = [] # not available async, sorry
- return result
-
- @defer.inlineCallbacks
- def asDict_async(self):
- result = {}
-
- ss = yield self.getSourceStamp()
- result['source'] = ss.asDict()
- props = yield self.getBuildProperties()
- result['properties'] = props.asList()
- result['builderName'] = self.getBuilderName()
- result['submittedAt'] = yield self.getSubmitTime()
-
- builds = yield self.getBuilds()
- result['builds'] = [ build.asDict() for build in builds ]
-
- defer.returnValue(result)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildset.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildset.py
deleted file mode 100644
index 524473a7..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildset.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from zope.interface import implements
-from buildbot import interfaces
-from buildbot.status.buildrequest import BuildRequestStatus
-
-class BuildSetStatus:
- implements(interfaces.IBuildSetStatus)
-
- def __init__(self, bsdict, status):
- self.id = bsdict['bsid']
- self.bsdict = bsdict
- self.status = status
- self.master = status.master
-
- # methods for our clients
-
- def getReason(self):
- return self.bsdict['reason']
-
- def getResults(self):
- return self.bsdict['results']
-
- def getID(self):
- return self.bsdict['external_idstring']
-
- def isFinished(self):
- return self.bsdict['complete']
-
- def getBuilderNamesAndBuildRequests(self):
- # returns a Deferred; undocumented method that may be removed
- # without warning
- d = self.master.db.buildrequests.getBuildRequests(bsid=self.id)
- def get_objects(brdicts):
- return dict([
- (brd['buildername'], BuildRequestStatus(brd['buildername'],
- brd['brid'], self.status))
- for brd in brdicts ])
- d.addCallback(get_objects)
- return d
-
- def getBuilderNames(self):
- d = self.master.db.buildrequests.getBuildRequests(bsid=self.id)
- def get_names(brdicts):
- return sorted([ brd['buildername'] for brd in brdicts ])
- d.addCallback(get_names)
- return d
-
- def waitUntilFinished(self):
- return self.status._buildset_waitUntilFinished(self.id)
-
- def asDict(self):
- d = dict(self.bsdict)
- d["submitted_at"] = str(self.bsdict["submitted_at"])
- return d
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildstep.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildstep.py
deleted file mode 100644
index 8e453873..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/buildstep.py
+++ /dev/null
@@ -1,386 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import os
-from zope.interface import implements
-from twisted.persisted import styles
-from twisted.python import log
-from twisted.internet import reactor, defer
-from buildbot import interfaces, util
-from buildbot.status.logfile import LogFile, HTMLLogFile
-
-class BuildStepStatus(styles.Versioned):
- """
- I represent a collection of output status for a
- L{buildbot.process.step.BuildStep}.
-
- Statistics contain any information gleaned from a step that is
- not in the form of a logfile. As an example, steps that run
- tests might gather statistics about the number of passed, failed,
- or skipped tests.
-
- @type progress: L{buildbot.status.progress.StepProgress}
- @cvar progress: tracks ETA for the step
- @type text: list of strings
- @cvar text: list of short texts that describe the command and its status
- @type text2: list of strings
- @cvar text2: list of short texts added to the overall build description
- @type logs: dict of string -> L{buildbot.status.logfile.LogFile}
- @ivar logs: logs of steps
- @type statistics: dict
- @ivar statistics: results from running this step
- """
- # note that these are created when the Build is set up, before each
- # corresponding BuildStep has started.
- implements(interfaces.IBuildStepStatus, interfaces.IStatusEvent)
-
- persistenceVersion = 4
- persistenceForgets = ( 'wasUpgraded', )
-
- started = None
- finished = None
- progress = None
- text = []
- results = None
- text2 = []
- watchers = []
- updates = {}
- finishedWatchers = []
- statistics = {}
- step_number = None
- hidden = False
-
- def __init__(self, parent, master, step_number):
- assert interfaces.IBuildStatus(parent)
- self.build = parent
- self.step_number = step_number
- self.hidden = False
- self.logs = []
- self.urls = {}
- self.watchers = []
- self.updates = {}
- self.finishedWatchers = []
- self.statistics = {}
- self.skipped = False
-
- self.master = master
-
- self.waitingForLocks = False
-
- def getName(self):
- """Returns a short string with the name of this step. This string
- may have spaces in it."""
- return self.name
-
- def getBuild(self):
- return self.build
-
- def getTimes(self):
- return (self.started, self.finished)
-
- def getExpectations(self):
- """Returns a list of tuples (name, current, target)."""
- if not self.progress:
- return []
- ret = []
- metrics = self.progress.progress.keys()
- metrics.sort()
- for m in metrics:
- t = (m, self.progress.progress[m], self.progress.expectations[m])
- ret.append(t)
- return ret
-
- def getLogs(self):
- return self.logs
-
- def getURLs(self):
- return self.urls.copy()
-
- def isStarted(self):
- return (self.started is not None)
-
- def isSkipped(self):
- return self.skipped
-
- def isFinished(self):
- return (self.finished is not None)
-
- def isHidden(self):
- return self.hidden
-
- def waitUntilFinished(self):
- if self.finished:
- d = defer.succeed(self)
- else:
- d = defer.Deferred()
- self.finishedWatchers.append(d)
- return d
-
- # while the step is running, the following methods make sense.
- # Afterwards they return None
-
- def getETA(self):
- if self.started is None:
- return None # not started yet
- if self.finished is not None:
- return None # already finished
- if not self.progress:
- return None # no way to predict
- return self.progress.remaining()
-
- # Once you know the step has finished, the following methods are legal.
- # Before this step has finished, they all return None.
-
- def getText(self):
- """Returns a list of strings which describe the step. These are
- intended to be displayed in a narrow column. If more space is
- available, the caller should join them together with spaces before
- presenting them to the user."""
- return self.text
-
- def getResults(self):
- """Return a tuple describing the results of the step.
- 'result' is one of the constants in L{buildbot.status.builder}:
- SUCCESS, WARNINGS, FAILURE, or SKIPPED.
- 'strings' is an optional list of strings that the step wants to
- append to the overall build's results. These strings are usually
- more terse than the ones returned by getText(): in particular,
- successful Steps do not usually contribute any text to the
- overall build.
-
- @rtype: tuple of int, list of strings
- @returns: (result, strings)
- """
- return (self.results, self.text2)
-
- def hasStatistic(self, name):
- """Return true if this step has a value for the given statistic.
- """
- return self.statistics.has_key(name)
-
- def getStatistic(self, name, default=None):
- """Return the given statistic, if present
- """
- return self.statistics.get(name, default)
-
- def getStatistics(self):
- return self.statistics.copy()
-
- # subscription interface
-
- def subscribe(self, receiver, updateInterval=10):
- # will get logStarted, logFinished, stepETAUpdate
- assert receiver not in self.watchers
- self.watchers.append(receiver)
- self.sendETAUpdate(receiver, updateInterval)
-
- def sendETAUpdate(self, receiver, updateInterval):
- self.updates[receiver] = None
- # they might unsubscribe during stepETAUpdate
- receiver.stepETAUpdate(self.build, self,
- self.getETA(), self.getExpectations())
- if receiver in self.watchers:
- self.updates[receiver] = reactor.callLater(updateInterval,
- self.sendETAUpdate,
- receiver,
- updateInterval)
-
- def unsubscribe(self, receiver):
- if receiver in self.watchers:
- self.watchers.remove(receiver)
- if receiver in self.updates:
- if self.updates[receiver] is not None:
- self.updates[receiver].cancel()
- del self.updates[receiver]
-
-
- # methods to be invoked by the BuildStep
-
- def setName(self, stepname):
- self.name = stepname
-
- def setColor(self, color):
- log.msg("BuildStepStatus.setColor is no longer supported -- ignoring color %s" % (color,))
-
- def setProgress(self, stepprogress):
- self.progress = stepprogress
-
- def setHidden(self, hidden):
- self.hidden = hidden
-
- def stepStarted(self):
- self.started = util.now()
- if self.build:
- self.build.stepStarted(self)
-
- def addLog(self, name):
- assert self.started # addLog before stepStarted won't notify watchers
- logfilename = self.build.generateLogfileName(self.name, name)
- log = LogFile(self, name, logfilename)
- self.logs.append(log)
- for w in self.watchers:
- receiver = w.logStarted(self.build, self, log)
- if receiver:
- log.subscribe(receiver, True)
- d = log.waitUntilFinished()
- d.addCallback(lambda log: log.unsubscribe(receiver))
- d = log.waitUntilFinished()
- d.addCallback(self.logFinished)
- return log
-
- def addHTMLLog(self, name, html):
- assert self.started # addLog before stepStarted won't notify watchers
- logfilename = self.build.generateLogfileName(self.name, name)
- log = HTMLLogFile(self, name, logfilename, html)
- self.logs.append(log)
- for w in self.watchers:
- w.logStarted(self.build, self, log)
- w.logFinished(self.build, self, log)
-
- def logFinished(self, log):
- for w in self.watchers:
- w.logFinished(self.build, self, log)
-
- def addURL(self, name, url):
- self.urls[name] = url
-
- def setText(self, text):
- self.text = text
- for w in self.watchers:
- w.stepTextChanged(self.build, self, text)
- def setText2(self, text):
- self.text2 = text
- for w in self.watchers:
- w.stepText2Changed(self.build, self, text)
-
- def setStatistic(self, name, value):
- """Set the given statistic. Usually called by subclasses.
- """
- self.statistics[name] = value
-
- def setSkipped(self, skipped):
- self.skipped = skipped
-
- def stepFinished(self, results):
- self.finished = util.now()
- self.results = results
- cld = [] # deferreds for log compression
- logCompressionLimit = self.master.config.logCompressionLimit
- for loog in self.logs:
- if not loog.isFinished():
- loog.finish()
- # if log compression is on, and it's a real LogFile,
- # HTMLLogFiles aren't files
- if logCompressionLimit is not False and \
- isinstance(loog, LogFile):
- if os.path.getsize(loog.getFilename()) > logCompressionLimit:
- loog_deferred = loog.compressLog()
- if loog_deferred:
- cld.append(loog_deferred)
-
- for r in self.updates.keys():
- if self.updates[r] is not None:
- self.updates[r].cancel()
- del self.updates[r]
-
- watchers = self.finishedWatchers
- self.finishedWatchers = []
- for w in watchers:
- w.callback(self)
- if cld:
- return defer.DeferredList(cld)
-
- def checkLogfiles(self):
- # filter out logs that have been deleted
- self.logs = [ l for l in self.logs if l.hasContents() ]
-
- def isWaitingForLocks(self):
- return self.waitingForLocks
-
- def setWaitingForLocks(self, waiting):
- self.waitingForLocks = waiting
-
- # persistence
-
- def __getstate__(self):
- d = styles.Versioned.__getstate__(self)
- del d['build'] # filled in when loading
- if d.has_key('progress'):
- del d['progress']
- del d['watchers']
- del d['finishedWatchers']
- del d['updates']
- del d['master']
- return d
-
- def __setstate__(self, d):
- styles.Versioned.__setstate__(self, d)
- # self.build must be filled in by our parent
-
- # point the logs to this object
- self.watchers = []
- self.finishedWatchers = []
- self.updates = {}
-
- def setProcessObjects(self, build, master):
- self.build = build
- self.master = master
- for loog in self.logs:
- loog.step = self
- loog.master = master
-
- def upgradeToVersion1(self):
- if not hasattr(self, "urls"):
- self.urls = {}
- self.wasUpgraded = True
-
- def upgradeToVersion2(self):
- if not hasattr(self, "statistics"):
- self.statistics = {}
- self.wasUpgraded = True
-
- def upgradeToVersion3(self):
- if not hasattr(self, "step_number"):
- self.step_number = 0
- self.wasUpgraded = True
-
- def upgradeToVersion4(self):
- if not hasattr(self, "hidden"):
- self.hidden = False
- self.wasUpgraded = True
-
- def asDict(self):
- result = {}
- # Constant
- result['name'] = self.getName()
-
- # Transient
- result['text'] = self.getText()
- result['results'] = self.getResults()
- result['isStarted'] = self.isStarted()
- result['isFinished'] = self.isFinished()
- result['statistics'] = self.statistics
- result['times'] = self.getTimes()
- result['expectations'] = self.getExpectations()
- result['eta'] = self.getETA()
- result['urls'] = self.getURLs()
- result['step_number'] = self.step_number
- result['hidden'] = self.hidden
- result['logs'] = [[l.getName(),
- self.build.builder.status.getURLForThing(l)]
- for l in self.getLogs()]
- return result
-
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/client.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/client.py
deleted file mode 100644
index 39adcec5..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/client.py
+++ /dev/null
@@ -1,586 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from twisted.spread import pb
-from twisted.python import components, log as twlog
-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 logfile, base
-from buildbot.changes import changes
-from buildbot.util.eventual import eventually
-
-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() # note: passes along the Deferred
-
- def remote_getBuildRequests(self):
- """Returns a list of (builderName, BuildRequest) tuples."""
- d = self.b.getBuilderNamesAndBuildRequests()
- def add_remote(buildrequests):
- for k,v in buildrequests.iteritems():
- buildrequests[k] = IRemote(v)
- return buildrequests.items()
- d.addCallback(add_remote)
- return d
-
- def remote_isFinished(self):
- return self.b.isFinished()
-
- def remote_waitUntilFinished(self):
- d = self.b.waitUntilFinished()
- d.addCallback(makeRemote)
- 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
- # mapping of observers (RemoteReference instances) to local callable
- # objects that have been passed to BuildRequestStatus.subscribe
- self.observers = []
-
- def remote_getSourceStamp(self):
- # note that this now returns a Deferred
- 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."""
- def send(bs):
- d = observer.callRemote("newbuild",
- IRemote(bs), self.b.getBuilderName())
- d.addErrback(twlog.err,
- "while calling client-side remote_newbuild")
- self.observers.append((observer, send))
- self.b.subscribe(send)
-
- def remote_unsubscribe(self, observer):
- for i, (obs, send) in enumerate(self.observers):
- if obs == observer:
- del self.observers[i]
- self.b.unsubscribe(send)
- break
-
-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_getRevisions(self):
- return self.b.getRevisions()
-
- 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, logfile.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
- eventually(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."""
- d = self.status.getBuildSets()
- def make_remotes(buildsets):
- return [(IRemote(s), s.id) for s in buildsets]
- d.addCallback(make_remotes)
- return d
-
- 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.status = parent
-
- 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))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/event.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/event.py
deleted file mode 100644
index 8e072931..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/event.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from zope.interface import implements
-from buildbot import interfaces, util
-
-class Event:
- implements(interfaces.IStatusEvent)
-
- started = None
- finished = None
- text = []
-
- # IStatusEvent methods
- def getTimes(self):
- return (self.started, self.finished)
- def getText(self):
- return self.text
- def getLogs(self):
- return []
-
- def finish(self):
- self.finished = util.now()
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/html.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/html.py
deleted file mode 100644
index a0fc5755..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/html.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-# compatibility wrapper. This is currently the preferred place for master.cfg
-# to import from.
-
-from buildbot.status.web.baseweb import WebStatus
-_hush_pyflakes = [WebStatus]
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/logfile.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/logfile.py
deleted file mode 100644
index bd1d686d..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/logfile.py
+++ /dev/null
@@ -1,699 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import os
-from cStringIO import StringIO
-from bz2 import BZ2File
-from gzip import GzipFile
-
-from zope.interface import implements
-from twisted.python import log, runtime
-from twisted.internet import defer, threads, reactor
-from buildbot.util import netstrings
-from buildbot.util.eventual import eventually
-from buildbot import interfaces
-
-STDOUT = interfaces.LOG_CHANNEL_STDOUT
-STDERR = interfaces.LOG_CHANNEL_STDERR
-HEADER = interfaces.LOG_CHANNEL_HEADER
-ChunkTypes = ["stdout", "stderr", "header"]
-
-class LogFileScanner(netstrings.NetstringParser):
- def __init__(self, chunk_cb, channels=[]):
- self.chunk_cb = chunk_cb
- self.channels = channels
- netstrings.NetstringParser.__init__(self)
-
- def stringReceived(self, line):
- channel = int(line[0])
- if not self.channels or (channel in self.channels):
- self.chunk_cb((channel, line[1:]))
-
-class LogFileProducer:
- """What's the plan?
-
- the LogFile has just one FD, used for both reading and writing.
- Each time you add an entry, fd.seek to the end and then write.
-
- Each reader (i.e. Producer) keeps track of their own offset. The reader
- starts by seeking to the start of the logfile, and reading forwards.
- Between each hunk of file they yield chunks, so they must remember their
- offset before yielding and re-seek back to that offset before reading
- more data. When their read() returns EOF, they're finished with the first
- phase of the reading (everything that's already been written to disk).
-
- After EOF, the remaining data is entirely in the current entries list.
- These entries are all of the same channel, so we can do one "".join and
- obtain a single chunk to be sent to the listener. But since that involves
- a yield, and more data might arrive after we give up control, we have to
- subscribe them before yielding. We can't subscribe them any earlier,
- otherwise they'd get data out of order.
-
- We're using a generator in the first place so that the listener can
- throttle us, which means they're pulling. But the subscription means
- we're pushing. Really we're a Producer. In the first phase we can be
- either a PullProducer or a PushProducer. In the second phase we're only a
- PushProducer.
-
- So the client gives a LogFileConsumer to File.subscribeConsumer . This
- Consumer must have registerProducer(), unregisterProducer(), and
- writeChunk(), and is just like a regular twisted.interfaces.IConsumer,
- except that writeChunk() takes chunks (tuples of (channel,text)) instead
- of the normal write() which takes just text. The LogFileConsumer is
- allowed to call stopProducing, pauseProducing, and resumeProducing on the
- producer instance it is given. """
-
- paused = False
- subscribed = False
- BUFFERSIZE = 2048
-
- def __init__(self, logfile, consumer):
- self.logfile = logfile
- self.consumer = consumer
- self.chunkGenerator = self.getChunks()
- consumer.registerProducer(self, True)
-
- def getChunks(self):
- f = self.logfile.getFile()
- offset = 0
- chunks = []
- p = LogFileScanner(chunks.append)
- f.seek(offset)
- data = f.read(self.BUFFERSIZE)
- offset = f.tell()
- while data:
- p.dataReceived(data)
- while chunks:
- yield chunks.pop(0)
- f.seek(offset)
- data = f.read(self.BUFFERSIZE)
- offset = f.tell()
- del f
-
- # now subscribe them to receive new entries
- self.subscribed = True
- self.logfile.watchers.append(self)
- d = self.logfile.waitUntilFinished()
-
- # then give them the not-yet-merged data
- if self.logfile.runEntries:
- channel = self.logfile.runEntries[0][0]
- text = "".join([c[1] for c in self.logfile.runEntries])
- yield (channel, text)
-
- # now we've caught up to the present. Anything further will come from
- # the logfile subscription. We add the callback *after* yielding the
- # data from runEntries, because the logfile might have finished
- # during the yield.
- d.addCallback(self.logfileFinished)
-
- def stopProducing(self):
- # TODO: should we still call consumer.finish? probably not.
- self.paused = True
- self.consumer = None
- self.done()
-
- def done(self):
- if self.chunkGenerator:
- self.chunkGenerator = None # stop making chunks
- if self.subscribed:
- self.logfile.watchers.remove(self)
- self.subscribed = False
-
- def pauseProducing(self):
- self.paused = True
-
- def resumeProducing(self):
- # Twisted-1.3.0 has a bug which causes hangs when resumeProducing
- # calls transport.write (there is a recursive loop, fixed in 2.0 in
- # t.i.abstract.FileDescriptor.doWrite by setting the producerPaused
- # flag *before* calling resumeProducing). To work around this, we
- # just put off the real resumeProducing for a moment. This probably
- # has a performance hit, but I'm going to assume that the log files
- # are not retrieved frequently enough for it to be an issue.
-
- eventually(self._resumeProducing)
-
- def _resumeProducing(self):
- self.paused = False
- if not self.chunkGenerator:
- return
- try:
- while not self.paused:
- chunk = self.chunkGenerator.next()
- self.consumer.writeChunk(chunk)
- # we exit this when the consumer says to stop, or we run out
- # of chunks
- except StopIteration:
- # if the generator finished, it will have done releaseFile
- self.chunkGenerator = None
- # now everything goes through the subscription, and they don't get to
- # pause anymore
-
- def logChunk(self, build, step, logfile, channel, chunk):
- if self.consumer:
- self.consumer.writeChunk((channel, chunk))
-
- def logfileFinished(self, logfile):
- self.done()
- if self.consumer:
- self.consumer.unregisterProducer()
- self.consumer.finish()
- self.consumer = None
-
-class LogFile:
- """
- A LogFile keeps all of its contents on disk, in a non-pickle format to
- which new entries can easily be appended. The file on disk has a name like
- 12-log-compile-output, under the Builder's directory. The actual filename
- is generated (before the LogFile is created) by
- L{BuildStatus.generateLogfileName}.
-
- @ivar length: length of the data in the logfile (sum of chunk sizes; not
- the length of the on-disk encoding)
- """
-
- implements(interfaces.IStatusLog, interfaces.ILogFile)
-
- finished = False
- length = 0
- nonHeaderLength = 0
- tailLength = 0
- chunkSize = 10*1000
- runLength = 0
- # No max size by default
- # Don't keep a tail buffer by default
- logMaxTailSize = None
- maxLengthExceeded = False
- runEntries = [] # provided so old pickled builds will getChunks() ok
- entries = None
- BUFFERSIZE = 2048
- filename = None # relative to the Builder's basedir
- openfile = None
-
- def __init__(self, parent, name, logfilename):
- """
- @type parent: L{BuildStepStatus}
- @param parent: the Step that this log is a part of
- @type name: string
- @param name: the name of this log, typically 'output'
- @type logfilename: string
- @param logfilename: the Builder-relative pathname for the saved entries
- """
- self.step = parent
- self.master = parent.build.builder.master
- self.name = name
- self.filename = logfilename
- fn = self.getFilename()
- if os.path.exists(fn):
- # the buildmaster was probably stopped abruptly, before the
- # BuilderStatus could be saved, so BuilderStatus.nextBuildNumber
- # is out of date, and we're overlapping with earlier builds now.
- # Warn about it, but then overwrite the old pickle file
- log.msg("Warning: Overwriting old serialized Build at %s" % fn)
- dirname = os.path.dirname(fn)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
- self.openfile = open(fn, "w+")
- self.runEntries = []
- self.watchers = []
- self.finishedWatchers = []
- self.tailBuffer = []
-
- def getFilename(self):
- """
- Get the base (uncompressed) filename for this log file.
-
- @returns: filename
- """
- return os.path.join(self.step.build.builder.basedir, self.filename)
-
- def hasContents(self):
- """
- Return true if this logfile's contents are available. For a newly
- created logfile, this is always true, but for a L{LogFile} instance
- that has been persisted, the logfiles themselves may have been deleted,
- in which case this method will return False.
-
- @returns: boolean
- """
- return os.path.exists(self.getFilename() + '.bz2') or \
- os.path.exists(self.getFilename() + '.gz') or \
- os.path.exists(self.getFilename())
-
- def getName(self):
- """
- Get this logfile's name
-
- @returns: string
- """
- return self.name
-
- def getStep(self):
- """
- Get the L{BuildStepStatus} instance containing this logfile
-
- @returns: L{BuildStepStatus} instance
- """
- return self.step
-
- def isFinished(self):
- """
- Return true if this logfile is finished (that is, if it will not
- receive any additional data
-
- @returns: boolean
- """
-
- return self.finished
-
- def waitUntilFinished(self):
- """
- Return a Deferred that will fire when this logfile is finished, or will
- fire immediately if the logfile is already finished.
- """
- if self.finished:
- d = defer.succeed(self)
- else:
- d = defer.Deferred()
- self.finishedWatchers.append(d)
- return d
-
- def getFile(self):
- """
- Get an open file object for this log. The file may also be in use for
- writing, so it should not be closed by the caller, and the caller
- should not rely on its file position remaining constant between
- asynchronous code segments.
-
- @returns: file object
- """
- if self.openfile:
- # this is the filehandle we're using to write to the log, so
- # don't close it!
- return self.openfile
- # otherwise they get their own read-only handle
- # try a compressed log first
- try:
- return BZ2File(self.getFilename() + ".bz2", "r")
- except IOError:
- pass
- try:
- return GzipFile(self.getFilename() + ".gz", "r")
- except IOError:
- pass
- return open(self.getFilename(), "r")
-
- def getText(self):
- # this produces one ginormous string
- return "".join(self.getChunks([STDOUT, STDERR], onlyText=True))
-
- def getTextWithHeaders(self):
- return "".join(self.getChunks(onlyText=True))
-
- def getChunks(self, channels=[], onlyText=False):
- # generate chunks for everything that was logged at the time we were
- # first called, so remember how long the file was when we started.
- # Don't read beyond that point. The current contents of
- # self.runEntries will follow.
-
- # this returns an iterator, which means arbitrary things could happen
- # while we're yielding. This will faithfully deliver the log as it
- # existed when it was started, and not return anything after that
- # point. To use this in subscribe(catchup=True) without missing any
- # data, you must insure that nothing will be added to the log during
- # yield() calls.
-
- f = self.getFile()
- if not self.finished:
- offset = 0
- f.seek(0, 2)
- remaining = f.tell()
- else:
- offset = 0
- remaining = None
-
- leftover = None
- if self.runEntries and (not channels or
- (self.runEntries[0][0] in channels)):
- leftover = (self.runEntries[0][0],
- "".join([c[1] for c in self.runEntries]))
-
- # freeze the state of the LogFile by passing a lot of parameters into
- # a generator
- return self._generateChunks(f, offset, remaining, leftover,
- channels, onlyText)
-
- def _generateChunks(self, f, offset, remaining, leftover,
- channels, onlyText):
- chunks = []
- p = LogFileScanner(chunks.append, channels)
- f.seek(offset)
- if remaining is not None:
- data = f.read(min(remaining, self.BUFFERSIZE))
- remaining -= len(data)
- else:
- data = f.read(self.BUFFERSIZE)
-
- offset = f.tell()
- while data:
- p.dataReceived(data)
- while chunks:
- channel, text = chunks.pop(0)
- if onlyText:
- yield text
- else:
- yield (channel, text)
- f.seek(offset)
- if remaining is not None:
- data = f.read(min(remaining, self.BUFFERSIZE))
- remaining -= len(data)
- else:
- data = f.read(self.BUFFERSIZE)
- offset = f.tell()
- del f
-
- if leftover:
- if onlyText:
- yield leftover[1]
- else:
- yield leftover
-
- def readlines(self):
- """Return an iterator that produces newline-terminated lines,
- excluding header chunks."""
- alltext = "".join(self.getChunks([STDOUT], onlyText=True))
- io = StringIO(alltext)
- return io.readlines()
-
- def subscribe(self, receiver, catchup):
- if self.finished:
- return
- self.watchers.append(receiver)
- if catchup:
- for channel, text in self.getChunks():
- # TODO: add logChunks(), to send over everything at once?
- receiver.logChunk(self.step.build, self.step, self,
- channel, text)
-
- def unsubscribe(self, receiver):
- if receiver in self.watchers:
- self.watchers.remove(receiver)
-
- def subscribeConsumer(self, consumer):
- p = LogFileProducer(self, consumer)
- p.resumeProducing()
-
- # interface used by the build steps to add things to the log
-
- def _merge(self):
- # merge all .runEntries (which are all of the same type) into a
- # single chunk for .entries
- if not self.runEntries:
- return
- channel = self.runEntries[0][0]
- text = "".join([c[1] for c in self.runEntries])
- assert channel < 10, "channel number must be a single decimal digit"
- f = self.openfile
- f.seek(0, 2)
- offset = 0
- while offset < len(text):
- size = min(len(text)-offset, self.chunkSize)
- f.write("%d:%d" % (1 + size, channel))
- f.write(text[offset:offset+size])
- f.write(",")
- offset += size
- self.runEntries = []
- self.runLength = 0
-
- def addEntry(self, channel, text, _no_watchers=False):
- """
- Add an entry to the logfile. The C{channel} is one of L{STDOUT},
- L{STDERR}, or L{HEADER}. The C{text} is the text to add to the
- logfile, which can be a unicode string or a bytestring which is
- presumed to be encoded with utf-8.
-
- This method cannot be called after the logfile is finished.
-
- @param channel: channel to add a chunk for
- @param text: chunk of text
- @param _no_watchers: private
- """
-
- assert not self.finished, "logfile is already finished"
-
- if isinstance(text, unicode):
- text = text.encode('utf-8')
-
- # notify watchers first, before the chunk gets munged, so that they get
- # a complete picture of the actual log output
- # TODO: is this right, or should the watchers get a picture of the chunks?
- if not _no_watchers:
- for w in self.watchers:
- w.logChunk(self.step.build, self.step, self, channel, text)
-
- if channel != HEADER:
- # Truncate the log if it's more than logMaxSize bytes
- logMaxSize = self.master.config.logMaxSize
- logMaxTailSize = self.master.config.logMaxTailSize
- if logMaxSize:
- self.nonHeaderLength += len(text)
- if self.nonHeaderLength > logMaxSize:
- # Add a message about what's going on and truncate this
- # chunk if necessary
- if not self.maxLengthExceeded:
- if self.runEntries and channel != self.runEntries[0][0]:
- self._merge()
- i = -(self.nonHeaderLength - logMaxSize)
- trunc, text = text[:i], text[i:]
- self.runEntries.append((channel, trunc))
- self._merge()
- msg = ("\nOutput exceeded %i bytes, remaining output "
- "has been truncated\n" % logMaxSize)
- self.runEntries.append((HEADER, msg))
- self.maxLengthExceeded = True
-
- # and track the tail of the text
- if logMaxTailSize and text:
- # Update the tail buffer
- self.tailBuffer.append((channel, text))
- self.tailLength += len(text)
- while self.tailLength > logMaxTailSize:
- # Drop some stuff off the beginning of the buffer
- c,t = self.tailBuffer.pop(0)
- n = len(t)
- self.tailLength -= n
- assert self.tailLength >= 0
- return
-
- # we only add to .runEntries here. _merge() is responsible for adding
- # merged chunks to .entries
- if self.runEntries and channel != self.runEntries[0][0]:
- self._merge()
- self.runEntries.append((channel, text))
- self.runLength += len(text)
- if self.runLength >= self.chunkSize:
- self._merge()
-
- self.length += len(text)
-
- def addStdout(self, text):
- """
- Shortcut to add stdout text to the logfile
-
- @param text: text to add to the logfile
- """
- self.addEntry(STDOUT, text)
-
- def addStderr(self, text):
- """
- Shortcut to add stderr text to the logfile
-
- @param text: text to add to the logfile
- """
- self.addEntry(STDERR, text)
-
- def addHeader(self, text):
- """
- Shortcut to add header text to the logfile
-
- @param text: text to add to the logfile
- """
- self.addEntry(HEADER, text)
-
- def finish(self):
- """
- Finish the logfile, flushing any buffers and preventing any further
- writes to the log.
- """
- self._merge()
- if self.tailBuffer:
- msg = "\nFinal %i bytes follow below:\n" % self.tailLength
- tmp = self.runEntries
- self.runEntries = [(HEADER, msg)]
- self._merge()
- self.runEntries = self.tailBuffer
- self._merge()
- self.runEntries = tmp
- self._merge()
- self.tailBuffer = []
-
- if self.openfile:
- # we don't do an explicit close, because there might be readers
- # shareing the filehandle. As soon as they stop reading, the
- # filehandle will be released and automatically closed.
- self.openfile.flush()
- self.openfile = None
- self.finished = True
- watchers = self.finishedWatchers
- self.finishedWatchers = []
- for w in watchers:
- w.callback(self)
- self.watchers = []
-
-
- def compressLog(self):
- logCompressionMethod = self.master.config.logCompressionMethod
- # bail out if there's no compression support
- if logCompressionMethod == "bz2":
- compressed = self.getFilename() + ".bz2.tmp"
- elif logCompressionMethod == "gz":
- compressed = self.getFilename() + ".gz.tmp"
- else:
- return defer.succeed(None)
-
- def _compressLog():
- infile = self.getFile()
- if logCompressionMethod == "bz2":
- cf = BZ2File(compressed, 'w')
- elif logCompressionMethod == "gz":
- cf = GzipFile(compressed, 'w')
- bufsize = 1024*1024
- while True:
- buf = infile.read(bufsize)
- cf.write(buf)
- if len(buf) < bufsize:
- break
- cf.close()
- d = threads.deferToThread(_compressLog)
-
- def _renameCompressedLog(rv):
- if logCompressionMethod == "bz2":
- filename = self.getFilename() + '.bz2'
- else:
- filename = self.getFilename() + '.gz'
- if runtime.platformType == 'win32':
- # windows cannot rename a file on top of an existing one, so
- # fall back to delete-first. There are ways this can fail and
- # lose the builder's history, so we avoid using it in the
- # general (non-windows) case
- if os.path.exists(filename):
- os.unlink(filename)
- os.rename(compressed, filename)
- _tryremove(self.getFilename(), 1, 5)
- d.addCallback(_renameCompressedLog)
-
- def _cleanupFailedCompress(failure):
- log.msg("failed to compress %s" % self.getFilename())
- if os.path.exists(compressed):
- _tryremove(compressed, 1, 5)
- failure.trap() # reraise the failure
- d.addErrback(_cleanupFailedCompress)
- return d
-
-
- # persistence stuff
- def __getstate__(self):
- d = self.__dict__.copy()
- del d['step'] # filled in upon unpickling
- del d['watchers']
- del d['finishedWatchers']
- del d['master']
- d['entries'] = [] # let 0.6.4 tolerate the saved log. TODO: really?
- if d.has_key('finished'):
- del d['finished']
- if d.has_key('openfile'):
- del d['openfile']
- return d
-
- def __setstate__(self, d):
- self.__dict__ = d
- self.watchers = [] # probably not necessary
- self.finishedWatchers = [] # same
- # self.step must be filled in by our parent
- self.finished = True
-
-class HTMLLogFile:
- implements(interfaces.IStatusLog)
-
- filename = None
-
- def __init__(self, parent, name, logfilename, html):
- self.step = parent
- self.name = name
- self.filename = logfilename
- self.html = html
-
- def getName(self):
- return self.name # set in BuildStepStatus.addLog
- def getStep(self):
- return self.step
-
- def isFinished(self):
- return True
- def waitUntilFinished(self):
- return defer.succeed(self)
-
- def hasContents(self):
- return True
- def getText(self):
- return self.html # looks kinda like text
- def getTextWithHeaders(self):
- return self.html
- def getChunks(self):
- return [(STDERR, self.html)]
-
- def subscribe(self, receiver, catchup):
- pass
- def unsubscribe(self, receiver):
- pass
-
- def finish(self):
- pass
-
- def __getstate__(self):
- d = self.__dict__.copy()
- del d['step']
- if d.has_key('master'):
- del d['master']
- return d
-
-
-def _tryremove(filename, timeout, retries):
- """Try to remove a file, and if failed, try again in timeout.
- Increases the timeout by a factor of 4, and only keeps trying for
- another retries-amount of times.
-
- """
- try:
- os.unlink(filename)
- except OSError:
- if retries > 0:
- reactor.callLater(timeout, _tryremove, filename, timeout * 4,
- retries - 1)
- else:
- log.msg("giving up on removing %s after over %d seconds" %
- (filename, timeout))
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/mail.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/mail.py
deleted file mode 100644
index ef48d8e2..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/mail.py
+++ /dev/null
@@ -1,798 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import re
-import types
-from email.Message import Message
-from email.Utils import formatdate
-from email.MIMEText import MIMEText
-from email.MIMENonMultipart import MIMENonMultipart
-from email.MIMEMultipart import MIMEMultipart
-from StringIO import StringIO
-import urllib
-
-from zope.interface import implements
-from twisted.internet import defer, reactor
-from twisted.python import log as twlog
-
-try:
- from twisted.mail.smtp import ESMTPSenderFactory
- ESMTPSenderFactory = ESMTPSenderFactory # for pyflakes
-except ImportError:
- ESMTPSenderFactory = None
-
-have_ssl = True
-try:
- from twisted.internet import ssl
- from OpenSSL.SSL import SSLv3_METHOD
-except ImportError:
- have_ssl = False
-
-# this incantation teaches email to output utf-8 using 7- or 8-bit encoding,
-# although it has no effect before python-2.7.
-from email import Charset
-Charset.add_charset('utf-8', Charset.SHORTEST, None, 'utf-8')
-
-from buildbot import interfaces, util, config
-from buildbot.process.users import users
-from buildbot.status import base
-from buildbot.status.results import FAILURE, SUCCESS, WARNINGS, EXCEPTION, Results
-
-VALID_EMAIL = re.compile("[a-zA-Z0-9\.\_\%\-\+]+@[a-zA-Z0-9\.\_\%\-]+.[a-zA-Z]{2,6}")
-
-ENCODING = 'utf8'
-LOG_ENCODING = 'utf-8'
-
-class Domain(util.ComparableMixin):
- implements(interfaces.IEmailLookup)
- compare_attrs = ["domain"]
-
- def __init__(self, domain):
- assert "@" not in domain
- self.domain = domain
-
- def getAddress(self, name):
- """If name is already an email address, pass it through."""
- if '@' in name:
- return name
- return name + "@" + self.domain
-
-
-def defaultMessage(mode, name, build, results, master_status):
- """Generate a buildbot mail message and return a tuple of message text
- and type."""
- ss_list = build.getSourceStamps()
-
- prev = build.getPreviousBuild()
-
- text = ""
- if results == FAILURE:
- if "change" in mode and prev and prev.getResults() != results or \
- "problem" in mode and prev and prev.getResults() != FAILURE:
- text += "The Buildbot has detected a new failure"
- else:
- text += "The Buildbot has detected a failed build"
- elif results == WARNINGS:
- text += "The Buildbot has detected a problem in the build"
- elif results == SUCCESS:
- if "change" in mode and prev and prev.getResults() != results:
- text += "The Buildbot has detected a restored build"
- else:
- text += "The Buildbot has detected a passing build"
- elif results == EXCEPTION:
- text += "The Buildbot has detected a build exception"
-
- projects = []
- if ss_list:
- for ss in ss_list:
- if ss.project and ss.project not in projects:
- projects.append(ss.project)
- if not projects:
- projects = [master_status.getTitle()]
- text += " on builder %s while building %s.\n" % (name, ', '.join(projects))
-
- if master_status.getURLForThing(build):
- text += "Full details are available at:\n %s\n" % master_status.getURLForThing(build)
- text += "\n"
-
- if master_status.getBuildbotURL():
- text += "Buildbot URL: %s\n\n" % urllib.quote(master_status.getBuildbotURL(), '/:')
-
- text += "Buildslave for this Build: %s\n\n" % build.getSlavename()
- text += "Build Reason: %s\n" % build.getReason()
-
- for ss in ss_list:
- source = ""
- if ss and ss.branch:
- source += "[branch %s] " % ss.branch
- if ss and ss.revision:
- source += str(ss.revision)
- else:
- source += "HEAD"
- if ss and ss.patch:
- source += " (plus patch)"
-
- discriminator = ""
- if ss.codebase:
- discriminator = " '%s'" % ss.codebase
- text += "Build Source Stamp%s: %s\n" % (discriminator, source)
-
- text += "Blamelist: %s\n" % ",".join(build.getResponsibleUsers())
-
- text += "\n"
-
- t = build.getText()
- if t:
- t = ": " + " ".join(t)
- else:
- t = ""
-
- if results == SUCCESS:
- text += "Build succeeded!\n"
- elif results == WARNINGS:
- text += "Build Had Warnings%s\n" % t
- else:
- text += "BUILD FAILED%s\n" % t
-
- text += "\n"
- text += "sincerely,\n"
- text += " -The Buildbot\n"
- text += "\n"
- return { 'body' : text, 'type' : 'plain' }
-
-def defaultGetPreviousBuild(current_build):
- return current_build.getPreviousBuild()
-
-class MailNotifier(base.StatusReceiverMultiService):
- """This is a status notifier which sends email to a list of recipients
- upon the completion of each build. It can be configured to only send out
- mail for certain builds, and only send messages when the build fails, or
- when it transitions from success to failure. It can also be configured to
- include various build logs in each message.
-
- By default, the message will be sent to the Interested Users list, which
- includes all developers who made changes in the build. You can add
- additional recipients with the extraRecipients argument.
-
- To get a simple one-message-per-build (say, for a mailing list), use
- sendToInterestedUsers=False, extraRecipients=['listaddr@example.org']
-
- Each MailNotifier sends mail to a single set of recipients. To send
- different kinds of mail to different recipients, use multiple
- MailNotifiers.
- """
-
- implements(interfaces.IEmailSender)
-
- compare_attrs = ["extraRecipients", "lookup", "fromaddr", "mode",
- "categories", "builders", "addLogs", "relayhost",
- "subject", "sendToInterestedUsers", "customMesg",
- "messageFormatter", "extraHeaders"]
-
- possible_modes = ("change", "failing", "passing", "problem", "warnings", "exception")
-
- def __init__(self, fromaddr, mode=("failing", "passing", "warnings"),
- categories=None, builders=None, addLogs=False,
- relayhost="localhost", buildSetSummary=False,
- subject="buildbot %(result)s in %(title)s on %(builder)s",
- lookup=None, extraRecipients=[],
- sendToInterestedUsers=True, customMesg=None,
- messageFormatter=defaultMessage, extraHeaders=None,
- addPatch=True, useTls=False,
- smtpUser=None, smtpPassword=None, smtpPort=25,
- previousBuildGetter=defaultGetPreviousBuild):
- """
- @type fromaddr: string
- @param fromaddr: the email address to be used in the 'From' header.
- @type sendToInterestedUsers: boolean
- @param sendToInterestedUsers: if True (the default), send mail to all
- of the Interested Users. If False, only
- send mail to the extraRecipients list.
-
- @type extraRecipients: tuple of strings
- @param extraRecipients: a list of email addresses to which messages
- should be sent (in addition to the
- InterestedUsers list, which includes any
- developers who made Changes that went into this
- build). It is a good idea to create a small
- mailing list and deliver to that, then let
- subscribers come and go as they please. The
- addresses in this list are used literally (they
- are not processed by lookup).
-
- @type subject: string
- @param subject: a string to be used as the subject line of the message.
- %(builder)s will be replaced with the name of the
- builder which provoked the message.
-
- @type mode: list of strings
- @param mode: a list of MailNotifer.possible_modes:
- - "change": send mail about builds which change status
- - "failing": send mail about builds which fail
- - "passing": send mail about builds which succeed
- - "problem": send mail about a build which failed
- when the previous build passed
- - "warnings": send mail if a build contain warnings
- - "exception": send mail if a build fails due to an exception
- - "all": always send mail
- Defaults to ("failing", "passing", "warnings").
-
- @type builders: list of strings
- @param builders: a list of builder names for which mail should be
- sent. Defaults to None (send mail for all builds).
- Use either builders or categories, but not both.
-
- @type categories: list of strings
- @param categories: a list of category names to serve status
- information for. Defaults to None (all
- categories). Use either builders or categories,
- but not both.
-
- @type addLogs: boolean
- @param addLogs: if True, include all build logs as attachments to the
- messages. These can be quite large. This can also be
- set to a list of log names, to send a subset of the
- logs. Defaults to False.
-
- @type addPatch: boolean
- @param addPatch: if True, include the patch when the source stamp
- includes one.
-
- @type relayhost: string
- @param relayhost: the host to which the outbound SMTP connection
- should be made. Defaults to 'localhost'
-
- @type buildSetSummary: boolean
- @param buildSetSummary: if True, this notifier will only send a summary
- email when a buildset containing any of its
- watched builds completes
-
- @type lookup: implementor of {IEmailLookup}
- @param lookup: object which provides IEmailLookup, which is
- responsible for mapping User names for Interested
- Users (which come from the VC system) into valid
- email addresses. If not provided, the notifier will
- only be able to send mail to the addresses in the
- extraRecipients list. Most of the time you can use a
- simple Domain instance. As a shortcut, you can pass
- as string: this will be treated as if you had provided
- Domain(str). For example, lookup='twistedmatrix.com'
- will allow mail to be sent to all developers whose SVN
- usernames match their twistedmatrix.com account names.
-
- @type customMesg: func
- @param customMesg: (this function is deprecated)
-
- @type messageFormatter: func
- @param messageFormatter: function taking (mode, name, build, result,
- master_status) and returning a dictionary
- containing two required keys "body" and "type",
- with a third optional key, "subject". The
- "body" key gives a string that contains the
- complete text of the message. The "type" key
- is the message type ('plain' or 'html'). The
- 'html' type should be used when generating an
- HTML message. The optional "subject" key
- gives the subject for the email.
-
- @type extraHeaders: dict
- @param extraHeaders: A dict of extra headers to add to the mail. It's
- best to avoid putting 'To', 'From', 'Date',
- 'Subject', or 'CC' in here. Both the names and
- values may be WithProperties instances.
-
- @type useTls: boolean
- @param useTls: Send emails using TLS and authenticate with the
- smtp host. Defaults to False.
-
- @type smtpUser: string
- @param smtpUser: The user that will attempt to authenticate with the
- relayhost when useTls is True.
-
- @type smtpPassword: string
- @param smtpPassword: The password that smtpUser will use when
- authenticating with relayhost.
-
- @type smtpPort: int
- @param smtpPort: The port that will be used when connecting to the
- relayhost. Defaults to 25.
-
- @type previousBuildGetter: func
- @param previousBuildGetter: function taking a BuildStatus instance
- returning a BuildStatus of the build
- previous to the one passed in. This allows
- to implement a relative ordering between
- builds other than the default one, which is
- chronological.
- """
- base.StatusReceiverMultiService.__init__(self)
-
- if not isinstance(extraRecipients, (list, tuple)):
- config.error("extraRecipients must be a list or tuple")
- else:
- for r in extraRecipients:
- if not isinstance(r, str) or not VALID_EMAIL.search(r):
- config.error(
- "extra recipient %r is not a valid email" % (r,))
- self.extraRecipients = extraRecipients
- self.sendToInterestedUsers = sendToInterestedUsers
- self.fromaddr = fromaddr
- if isinstance(mode, basestring):
- if mode == "all":
- mode = ("failing", "passing", "warnings", "exception")
- elif mode == "warnings":
- mode = ("failing", "warnings")
- else:
- mode = (mode,)
- for m in mode:
- if m not in self.possible_modes:
- config.error(
- "mode %s is not a valid mode" % (m,))
- self.mode = mode
- self.categories = categories
- self.builders = builders
- self.addLogs = addLogs
- self.relayhost = relayhost
- if '\n' in subject:
- config.error(
- 'Newlines are not allowed in email subjects')
- self.subject = subject
- if lookup is not None:
- if type(lookup) is str:
- lookup = Domain(lookup)
- assert interfaces.IEmailLookup.providedBy(lookup)
- self.lookup = lookup
- self.customMesg = customMesg
- self.messageFormatter = messageFormatter
- if extraHeaders:
- if not isinstance(extraHeaders, dict):
- config.error("extraHeaders must be a dictionary")
- self.extraHeaders = extraHeaders
- self.addPatch = addPatch
- self.useTls = useTls
- self.smtpUser = smtpUser
- self.smtpPassword = smtpPassword
- self.smtpPort = smtpPort
- self.buildSetSummary = buildSetSummary
- self.buildSetSubscription = None
- self.getPreviousBuild = previousBuildGetter
- self.watched = []
- self.master_status = None
-
- # you should either limit on builders or categories, not both
- if self.builders != None and self.categories != None:
- config.error(
- "Please specify only builders or categories to include - " +
- "not both.")
-
- if customMesg:
- config.error(
- "customMesg is deprecated; use messageFormatter instead")
-
- def setServiceParent(self, parent):
- """
- @type parent: L{buildbot.master.BuildMaster}
- """
- base.StatusReceiverMultiService.setServiceParent(self, parent)
- self.master_status = self.parent
- self.master_status.subscribe(self)
- self.master = self.master_status.master
-
- def startService(self):
- if self.buildSetSummary:
- self.buildSetSubscription = \
- self.master.subscribeToBuildsetCompletions(self.buildsetFinished)
-
- base.StatusReceiverMultiService.startService(self)
-
- def stopService(self):
- if self.buildSetSubscription is not None:
- self.buildSetSubscription.unsubscribe()
- self.buildSetSubscription = None
-
- return base.StatusReceiverMultiService.stopService(self)
-
- def disownServiceParent(self):
- self.master_status.unsubscribe(self)
- self.master_status = None
- for w in self.watched:
- w.unsubscribe(self)
- return base.StatusReceiverMultiService.disownServiceParent(self)
-
- def builderAdded(self, name, builder):
- # only subscribe to builders we are interested in
- if self.categories != None and builder.category not in self.categories:
- return None
-
- self.watched.append(builder)
- return self # subscribe to this builder
-
- def builderRemoved(self, name):
- pass
-
- def builderChangedState(self, name, state):
- pass
-
- def buildStarted(self, name, build):
- pass
-
- def isMailNeeded(self, build, results):
- # here is where we actually do something.
- builder = build.getBuilder()
- if self.builders is not None and builder.name not in self.builders:
- return False # ignore this build
- if self.categories is not None and \
- builder.category not in self.categories:
- return False # ignore this build
-
- prev = self.getPreviousBuild(build)
- if "change" in self.mode:
- if prev and prev.getResults() != results:
- return True
- if "failing" in self.mode and results == FAILURE:
- return True
- if "passing" in self.mode and results == SUCCESS:
- return True
- if "problem" in self.mode and results == FAILURE:
- if prev and prev.getResults() != FAILURE:
- return True
- if "warnings" in self.mode and results == WARNINGS:
- return True
- if "exception" in self.mode and results == EXCEPTION:
- return True
-
- return False
-
- def buildFinished(self, name, build, results):
- if ( not self.buildSetSummary and
- self.isMailNeeded(build, results) ):
- # for testing purposes, buildMessage returns a Deferred that fires
- # when the mail has been sent. To help unit tests, we return that
- # Deferred here even though the normal IStatusReceiver.buildFinished
- # signature doesn't do anything with it. If that changes (if
- # .buildFinished's return value becomes significant), we need to
- # rearrange this.
- return self.buildMessage(name, [build], results)
- return None
-
- def _gotBuilds(self, res, buildset):
- builds = []
- for (builddictlist, builder) in res:
- for builddict in builddictlist:
- build = builder.getBuild(builddict['number'])
- if build is not None and self.isMailNeeded(build, build.results):
- builds.append(build)
-
- if builds:
- self.buildMessage("Buildset Complete: " + buildset['reason'], builds,
- buildset['results'])
-
- def _gotBuildRequests(self, breqs, buildset):
- dl = []
- for breq in breqs:
- buildername = breq['buildername']
- builder = self.master_status.getBuilder(buildername)
- d = self.master.db.builds.getBuildsForRequest(breq['brid'])
- d.addCallback(lambda builddictlist, builder=builder:
- (builddictlist, builder))
- dl.append(d)
- d = defer.gatherResults(dl)
- d.addCallback(self._gotBuilds, buildset)
-
- def _gotBuildSet(self, buildset, bsid):
- d = self.master.db.buildrequests.getBuildRequests(bsid=bsid)
- d.addCallback(self._gotBuildRequests, buildset)
-
- def buildsetFinished(self, bsid, result):
- d = self.master.db.buildsets.getBuildset(bsid=bsid)
- d.addCallback(self._gotBuildSet, bsid)
-
- return d
-
- def getCustomMesgData(self, mode, name, build, results, master_status):
- #
- # logs is a list of tuples that contain the log
- # name, log url, and the log contents as a list of strings.
- #
- logs = list()
- for logf in build.getLogs():
- logStep = logf.getStep()
- stepName = logStep.getName()
- logStatus, dummy = logStep.getResults()
- logName = logf.getName()
- logs.append(('%s.%s' % (stepName, logName),
- '%s/steps/%s/logs/%s' % (
- master_status.getURLForThing(build),
- stepName, logName),
- logf.getText().splitlines(),
- logStatus))
-
- attrs = {'builderName': name,
- 'title': master_status.getTitle(),
- 'mode': mode,
- 'result': Results[results],
- 'buildURL': master_status.getURLForThing(build),
- 'buildbotURL': master_status.getBuildbotURL(),
- 'buildText': build.getText(),
- 'buildProperties': build.getProperties(),
- 'slavename': build.getSlavename(),
- 'reason': build.getReason().replace('\n', ''),
- 'responsibleUsers': build.getResponsibleUsers(),
- 'branch': "",
- 'revision': "",
- 'patch': "",
- 'patch_info': "",
- 'changes': [],
- 'logs': logs}
-
- ss = None
- ss_list = build.getSourceStamps()
-
- if ss_list:
- if len(ss_list) == 1:
- ss = ss_list[0]
- if ss:
- attrs['branch'] = ss.branch
- attrs['revision'] = ss.revision
- attrs['patch'] = ss.patch
- attrs['patch_info'] = ss.patch_info
- attrs['changes'] = ss.changes[:]
- else:
- for key in ['branch', 'revision', 'patch', 'patch_info', 'changes']:
- attrs[key] = {}
- for ss in ss_list:
- attrs['branch'][ss.codebase] = ss.branch
- attrs['revision'][ss.codebase] = ss.revision
- attrs['patch'][ss.codebase] = ss.patch
- attrs['patch_info'][ss.codebase] = ss.patch_info
- attrs['changes'][ss.codebase] = ss.changes[:]
-
- return attrs
-
- def patch_to_attachment(self, patch, index):
- # patches don't come with an encoding. If the patch is valid utf-8,
- # we'll attach it as MIMEText; otherwise, it gets attached as a binary
- # file. This will suit the vast majority of cases, since utf8 is by
- # far the most common encoding.
- if type(patch[1]) != types.UnicodeType:
- try:
- unicode = patch[1].decode('utf8')
- except UnicodeDecodeError:
- unicode = None
- else:
- unicode = patch[1]
-
- if unicode:
- a = MIMEText(unicode.encode(ENCODING), _charset=ENCODING)
- else:
- # MIMEApplication is not present in Python-2.4 :(
- a = MIMENonMultipart('application', 'octet-stream')
- a.set_payload(patch[1])
- a.add_header('Content-Disposition', "attachment",
- filename="source patch " + str(index) )
- return a
-
- def createEmail(self, msgdict, builderName, title, results, builds=None,
- patches=None, logs=None):
- text = msgdict['body'].encode(ENCODING)
- type = msgdict['type']
- if 'subject' in msgdict:
- subject = msgdict['subject'].encode(ENCODING)
- else:
- subject = self.subject % { 'result': Results[results],
- 'projectName': title,
- 'title': title,
- 'builder': builderName,
- }
-
- assert '\n' not in subject, \
- "Subject cannot contain newlines"
-
- assert type in ('plain', 'html'), \
- "'%s' message type must be 'plain' or 'html'." % type
-
- if patches or logs:
- m = MIMEMultipart()
- m.attach(MIMEText(text, type, ENCODING))
- else:
- m = Message()
- m.set_payload(text, ENCODING)
- m.set_type("text/%s" % type)
-
- m['Date'] = formatdate(localtime=True)
- m['Subject'] = subject
- m['From'] = self.fromaddr
- # m['To'] is added later
-
- if patches:
- for (i, patch) in enumerate(patches):
- a = self.patch_to_attachment(patch, i)
- m.attach(a)
- if logs:
- for log in logs:
- name = "%s.%s" % (log.getStep().getName(),
- log.getName())
- if ( self._shouldAttachLog(log.getName()) or
- self._shouldAttachLog(name) ):
- text = log.getText()
- if not isinstance(text, unicode):
- # guess at the encoding, and use replacement symbols
- # for anything that's not in that encoding
- text = text.decode(LOG_ENCODING, 'replace')
- a = MIMEText(text.encode(ENCODING),
- _charset=ENCODING)
- a.add_header('Content-Disposition', "attachment",
- filename=name)
- m.attach(a)
-
- #@todo: is there a better way to do this?
- # Add any extra headers that were requested, doing WithProperties
- # interpolation if only one build was given
- if self.extraHeaders:
- if len(builds) == 1:
- d = builds[0].render(self.extraHeaders)
- else:
- d = defer.succeed(self.extraHeaders)
- @d.addCallback
- def addExtraHeaders(extraHeaders):
- for k,v in extraHeaders.items():
- if k in m:
- twlog.msg("Warning: Got header " + k +
- " in self.extraHeaders "
- "but it already exists in the Message - "
- "not adding it.")
- m[k] = v
- d.addCallback(lambda _: m)
- return d
-
- return defer.succeed(m)
-
- def buildMessageDict(self, name, build, results):
- if self.customMesg:
- # the customMesg stuff can be *huge*, so we prefer not to load it
- attrs = self.getCustomMesgData(self.mode, name, build, results,
- self.master_status)
- text, type = self.customMesg(attrs)
- msgdict = { 'body' : text, 'type' : type }
- else:
- msgdict = self.messageFormatter(self.mode, name, build, results,
- self.master_status)
-
- return msgdict
-
-
- def buildMessage(self, name, builds, results):
- patches = []
- logs = []
- msgdict = {"body":""}
-
- for build in builds:
- ss_list = build.getSourceStamps()
- if self.addPatch:
- for ss in ss_list:
- if ss.patch:
- patches.append(ss.patch)
- if self.addLogs:
- logs.extend(build.getLogs())
-
- tmp = self.buildMessageDict(name=build.getBuilder().name,
- build=build, results=build.results)
- msgdict['body'] += tmp['body']
- msgdict['body'] += '\n\n'
- msgdict['type'] = tmp['type']
- if "subject" in tmp:
- msgdict['subject'] = tmp['subject']
-
- d = self.createEmail(msgdict, name, self.master_status.getTitle(),
- results, builds, patches, logs)
-
- @d.addCallback
- def getRecipients(m):
- # now, who is this message going to?
- if self.sendToInterestedUsers:
- dl = []
- for build in builds:
- if self.lookup:
- d = self.useLookup(build)
- else:
- d = self.useUsers(build)
- dl.append(d)
- d = defer.gatherResults(dl)
- else:
- d = defer.succeed([])
- d.addCallback(self._gotRecipients, m)
- return d
-
- def useLookup(self, build):
- dl = []
- for u in build.getResponsibleUsers() + build.getInterestedUsers():
- d = defer.maybeDeferred(self.lookup.getAddress, u)
- dl.append(d)
- return defer.gatherResults(dl)
-
- def useUsers(self, build):
- return users.getBuildContacts(self.master, build, ['email'])
-
- def _shouldAttachLog(self, logname):
- if type(self.addLogs) is bool:
- return self.addLogs
- return logname in self.addLogs
-
- def _gotRecipients(self, rlist, m):
- to_recipients = set()
- cc_recipients = set()
-
- for r in reduce(list.__add__, rlist, []):
- if r is None: # getAddress didn't like this address
- continue
-
- # Git can give emails like 'User' <user@foo.com>@foo.com so check
- # for two @ and chop the last
- if r.count('@') > 1:
- r = r[:r.rindex('@')]
-
- if VALID_EMAIL.search(r):
- to_recipients.add(r)
- else:
- twlog.msg("INVALID EMAIL: %r" + r)
-
- # If we're sending to interested users put the extras in the
- # CC list so they can tell if they are also interested in the
- # change:
- if self.sendToInterestedUsers and to_recipients:
- cc_recipients.update(self.extraRecipients)
- else:
- to_recipients.update(self.extraRecipients)
-
- m['To'] = ", ".join(sorted(to_recipients))
- if cc_recipients:
- m['CC'] = ", ".join(sorted(cc_recipients))
-
- return self.sendMessage(m, list(to_recipients | cc_recipients))
-
- def sendmail(self, s, recipients):
- result = defer.Deferred()
-
- if have_ssl and self.useTls:
- client_factory = ssl.ClientContextFactory()
- client_factory.method = SSLv3_METHOD
- else:
- client_factory = None
-
- if self.smtpUser and self.smtpPassword:
- useAuth = True
- else:
- useAuth = False
-
- if not ESMTPSenderFactory:
- raise RuntimeError("twisted-mail is not installed - cannot "
- "send mail")
- sender_factory = ESMTPSenderFactory(
- self.smtpUser, self.smtpPassword,
- self.fromaddr, recipients, StringIO(s),
- result, contextFactory=client_factory,
- requireTransportSecurity=self.useTls,
- requireAuthentication=useAuth)
-
- reactor.connectTCP(self.relayhost, self.smtpPort, sender_factory)
-
- return result
-
- def sendMessage(self, m, recipients):
- s = m.as_string()
- twlog.msg("sending mail (%d bytes) to" % len(s), recipients)
- return self.sendmail(s, recipients)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/master.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/master.py
deleted file mode 100644
index 8d5b7e7d..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/master.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from __future__ import with_statement
-
-import os, urllib
-from cPickle import load
-from twisted.python import log
-from twisted.persisted import styles
-from twisted.internet import defer
-from twisted.application import service
-from zope.interface import implements
-from buildbot import config, interfaces, util
-from buildbot.util import bbcollections
-from buildbot.util.eventual import eventually
-from buildbot.changes import changes
-from buildbot.status import buildset, builder, buildrequest
-
-class Status(config.ReconfigurableServiceMixin, service.MultiService):
- implements(interfaces.IStatus)
-
- def __init__(self, master):
- service.MultiService.__init__(self)
- self.master = master
- self.botmaster = master.botmaster
- self.basedir = master.basedir
- self.watchers = []
- # No default limit to the log size
- self.logMaxSize = None
-
- self._builder_observers = bbcollections.KeyedSets()
- self._buildreq_observers = bbcollections.KeyedSets()
- self._buildset_finished_waiters = bbcollections.KeyedSets()
- self._buildset_completion_sub = None
- self._buildset_sub = None
- self._build_request_sub = None
- self._change_sub = None
-
- # service management
-
- def startService(self):
- # subscribe to the things we need to know about
- self._buildset_completion_sub = \
- self.master.subscribeToBuildsetCompletions(
- self._buildsetCompletionCallback)
- self._buildset_sub = \
- self.master.subscribeToBuildsets(
- self._buildsetCallback)
- self._build_request_sub = \
- self.master.subscribeToBuildRequests(
- self._buildRequestCallback)
- self._change_sub = \
- self.master.subscribeToChanges(
- self.changeAdded)
-
- return service.MultiService.startService(self)
-
- @defer.inlineCallbacks
- def reconfigService(self, new_config):
- # remove the old listeners, then add the new
- for sr in list(self):
- yield defer.maybeDeferred(lambda :
- sr.disownServiceParent())
-
- # WebStatus instances tend to "hang around" longer than we'd like -
- # if there's an ongoing HTTP request, or even a connection held
- # open by keepalive, then users may still be talking to an old
- # WebStatus. So WebStatus objects get to keep their `master`
- # attribute, but all other status objects lose theirs. And we want
- # to test this without importing WebStatus, so we use name
- if not sr.__class__.__name__.endswith('WebStatus'):
- sr.master = None
-
- for sr in new_config.status:
- sr.master = self.master
- sr.setServiceParent(self)
-
- # reconfig any newly-added change sources, as well as existing
- yield config.ReconfigurableServiceMixin.reconfigService(self,
- new_config)
-
- def stopService(self):
- if self._buildset_completion_sub:
- self._buildset_completion_sub.unsubscribe()
- self._buildset_completion_sub = None
- if self._buildset_sub:
- self._buildset_sub.unsubscribe()
- self._buildset_sub = None
- if self._build_request_sub:
- self._build_request_sub.unsubscribe()
- self._build_request_sub = None
- if self._change_sub:
- self._change_sub.unsubscribe()
- self._change_sub = None
-
- return service.MultiService.stopService(self)
-
- # clean shutdown
-
- @property
- def shuttingDown(self):
- return self.botmaster.shuttingDown
-
- def cleanShutdown(self):
- return self.botmaster.cleanShutdown()
-
- def cancelCleanShutdown(self):
- return self.botmaster.cancelCleanShutdown()
-
- # methods called by our clients
-
- def getTitle(self):
- return self.master.config.title
- def getTitleURL(self):
- return self.master.config.titleURL
- def getBuildbotURL(self):
- return self.master.config.buildbotURL
-
- def getStatus(self):
- # some listeners expect their .parent to be a BuildMaster object, and
- # use this method to get the Status object. This is documented, so for
- # now keep it working.
- return self
-
- def getMetrics(self):
- return self.master.metrics
-
- def getURLForBuild(self, builder_name, build_number):
- prefix = self.getBuildbotURL()
- import urlparse
- url_path = "builders/%s/builds/%d" % (
- urllib.quote(builder_name, safe=''),
- build_number)
- return(urlparse.urljoin(prefix,url_path))
-
- def getURLForThing(self, thing):
- prefix = self.getBuildbotURL()
- if not prefix:
- return None
- if interfaces.IStatus.providedBy(thing):
- return prefix
- if interfaces.ISchedulerStatus.providedBy(thing):
- pass
- if interfaces.IBuilderStatus.providedBy(thing):
- bldr = thing
- return prefix + "builders/%s" % (
- urllib.quote(bldr.getName(), safe=''),
- )
- if interfaces.IBuildStatus.providedBy(thing):
- build = thing
- bldr = build.getBuilder()
- return self.getURLForBuild(bldr.getName(), build.getNumber())
-
- if interfaces.IBuildStepStatus.providedBy(thing):
- step = thing
- build = step.getBuild()
- bldr = build.getBuilder()
- return prefix + "builders/%s/builds/%d/steps/%s" % (
- urllib.quote(bldr.getName(), safe=''),
- build.getNumber(),
- urllib.quote(step.getName(), safe=''))
- # IBuildSetStatus
- # IBuildRequestStatus
- # ISlaveStatus
- if interfaces.ISlaveStatus.providedBy(thing):
- slave = thing
- return prefix + "buildslaves/%s" % (
- urllib.quote(slave.getName(), safe=''),
- )
-
- # IStatusEvent
- if interfaces.IStatusEvent.providedBy(thing):
- # TODO: this is goofy, create IChange or something
- if isinstance(thing, changes.Change):
- change = thing
- return "%schanges/%d" % (prefix, change.number)
-
- if interfaces.IStatusLog.providedBy(thing):
- loog = thing
- step = loog.getStep()
- build = step.getBuild()
- bldr = build.getBuilder()
-
- logs = step.getLogs()
- for i in range(len(logs)):
- if loog is logs[i]:
- break
- else:
- return None
- return prefix + "builders/%s/builds/%d/steps/%s/logs/%s" % (
- urllib.quote(bldr.getName(), safe=''),
- build.getNumber(),
- urllib.quote(step.getName(), safe=''),
- urllib.quote(loog.getName(), safe=''))
-
- def getChangeSources(self):
- return list(self.master.change_svc)
-
- def getChange(self, number):
- """Get a Change object; returns a deferred"""
- d = self.master.db.changes.getChange(number)
- def chdict2change(chdict):
- if not chdict:
- return None
- return changes.Change.fromChdict(self.master, chdict)
- d.addCallback(chdict2change)
- return d
-
- def getSchedulers(self):
- return self.master.allSchedulers()
-
- def getBuilderNames(self, categories=None):
- if categories == None:
- # assume this is already sorted...
- return self.botmaster.builderNames
-
- l = []
- # respect addition order
- for name in self.botmaster.builderNames:
- bldr = self.botmaster.builders[name]
- if bldr.config.category in categories:
- l.append(name)
- return util.naturalSort(l)
-
- def getBuilder(self, name):
- """
- @rtype: L{BuilderStatus}
- """
- return self.botmaster.builders[name].builder_status
-
- def getSlaveNames(self):
- return self.botmaster.slaves.keys()
-
- def getSlave(self, slavename):
- return self.botmaster.slaves[slavename].slave_status
-
- def getBuildSets(self):
- d = self.master.db.buildsets.getBuildsets(complete=False)
- def make_status_objects(bsdicts):
- return [ buildset.BuildSetStatus(bsdict, self)
- for bsdict in bsdicts ]
- d.addCallback(make_status_objects)
- return d
-
- def generateFinishedBuilds(self, builders=[], branches=[],
- num_builds=None, finished_before=None,
- max_search=200):
-
- def want_builder(bn):
- if builders:
- return bn in builders
- return True
- builder_names = [bn
- for bn in self.getBuilderNames()
- if want_builder(bn)]
-
- # 'sources' is a list of generators, one for each Builder we're
- # using. When the generator is exhausted, it is replaced in this list
- # with None.
- sources = []
- for bn in builder_names:
- b = self.getBuilder(bn)
- g = b.generateFinishedBuilds(branches,
- finished_before=finished_before,
- max_search=max_search)
- sources.append(g)
-
- # next_build the next build from each source
- next_build = [None] * len(sources)
-
- def refill():
- for i,g in enumerate(sources):
- if next_build[i]:
- # already filled
- continue
- if not g:
- # already exhausted
- continue
- try:
- next_build[i] = g.next()
- except StopIteration:
- next_build[i] = None
- sources[i] = None
-
- got = 0
- while True:
- refill()
- # find the latest build among all the candidates
- candidates = [(i, b, b.getTimes()[1])
- for i,b in enumerate(next_build)
- if b is not None]
- candidates.sort(lambda x,y: cmp(x[2], y[2]))
- if not candidates:
- return
-
- # and remove it from the list
- i, build, finshed_time = candidates[-1]
- next_build[i] = None
- got += 1
- yield build
- if num_builds is not None:
- if got >= num_builds:
- return
-
- def subscribe(self, target):
- self.watchers.append(target)
- for name in self.botmaster.builderNames:
- self.announceNewBuilder(target, name, self.getBuilder(name))
- def unsubscribe(self, target):
- self.watchers.remove(target)
-
-
- # methods called by upstream objects
-
- def announceNewBuilder(self, target, name, builder_status):
- t = target.builderAdded(name, builder_status)
- if t:
- builder_status.subscribe(t)
-
- def builderAdded(self, name, basedir, category=None, description=None):
- """
- @rtype: L{BuilderStatus}
- """
- filename = os.path.join(self.basedir, basedir, "builder")
- log.msg("trying to load status pickle from %s" % filename)
- builder_status = None
- try:
- with open(filename, "rb") as f:
- builder_status = load(f)
- builder_status.master = self.master
-
- # (bug #1068) if we need to upgrade, we probably need to rewrite
- # this pickle, too. We determine this by looking at the list of
- # Versioned objects that have been unpickled, and (after doUpgrade)
- # checking to see if any of them set wasUpgraded. The Versioneds'
- # upgradeToVersionNN methods all set this.
- versioneds = styles.versionedsToUpgrade
- styles.doUpgrade()
- if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]:
- log.msg("re-writing upgraded builder pickle")
- builder_status.saveYourself()
-
- except IOError:
- log.msg("no saved status pickle, creating a new one")
- except:
- log.msg("error while loading status pickle, creating a new one")
- log.msg("error follows:")
- log.err()
- if not builder_status:
- builder_status = builder.BuilderStatus(name, category, self.master,
- description)
- builder_status.addPointEvent(["builder", "created"])
- log.msg("added builder %s in category %s" % (name, category))
- # an unpickled object might not have category set from before,
- # so set it here to make sure
- builder_status.category = category
- builder_status.description = description
- builder_status.master = self.master
- builder_status.basedir = os.path.join(self.basedir, basedir)
- builder_status.name = name # it might have been updated
- builder_status.status = self
-
- if not os.path.isdir(builder_status.basedir):
- os.makedirs(builder_status.basedir)
- builder_status.determineNextBuildNumber()
-
- builder_status.setBigState("offline")
-
- for t in self.watchers:
- self.announceNewBuilder(t, name, builder_status)
-
- return builder_status
-
- def builderRemoved(self, name):
- for t in self.watchers:
- if hasattr(t, 'builderRemoved'):
- t.builderRemoved(name)
-
- def slaveConnected(self, name):
- for t in self.watchers:
- if hasattr(t, 'slaveConnected'):
- t.slaveConnected(name)
-
- def slaveDisconnected(self, name):
- for t in self.watchers:
- if hasattr(t, 'slaveDisconnected'):
- t.slaveDisconnected(name)
-
- def changeAdded(self, change):
- for t in self.watchers:
- if hasattr(t, 'changeAdded'):
- t.changeAdded(change)
-
- def asDict(self):
- result = {}
- # Constant
- result['title'] = self.getTitle()
- result['titleURL'] = self.getTitleURL()
- result['buildbotURL'] = self.getBuildbotURL()
- # TODO: self.getSchedulers()
- # self.getChangeSources()
- return result
-
- def build_started(self, brid, buildername, build_status):
- if brid in self._buildreq_observers:
- for o in self._buildreq_observers[brid]:
- eventually(o, build_status)
-
- def _buildrequest_subscribe(self, brid, observer):
- self._buildreq_observers.add(brid, observer)
-
- def _buildrequest_unsubscribe(self, brid, observer):
- self._buildreq_observers.discard(brid, observer)
-
- def _buildset_waitUntilFinished(self, bsid):
- d = defer.Deferred()
- self._buildset_finished_waiters.add(bsid, d)
- self._maybeBuildsetFinished(bsid)
- return d
-
- def _maybeBuildsetFinished(self, bsid):
- # check bsid to see if it's successful or finished, and notify anyone
- # who cares
- if bsid not in self._buildset_finished_waiters:
- return
- d = self.master.db.buildsets.getBuildset(bsid)
- def do_notifies(bsdict):
- bss = buildset.BuildSetStatus(bsdict, self)
- if bss.isFinished():
- for d in self._buildset_finished_waiters.pop(bsid):
- eventually(d.callback, bss)
- d.addCallback(do_notifies)
- d.addErrback(log.err, 'while notifying for buildset finishes')
-
- def _builder_subscribe(self, buildername, watcher):
- # should get requestSubmitted and requestCancelled
- self._builder_observers.add(buildername, watcher)
-
- def _builder_unsubscribe(self, buildername, watcher):
- self._builder_observers.discard(buildername, watcher)
-
- def _buildsetCallback(self, **kwargs):
- bsid = kwargs['bsid']
- d = self.master.db.buildsets.getBuildset(bsid)
- def do_notifies(bsdict):
- bss = buildset.BuildSetStatus(bsdict, self)
- for t in self.watchers:
- if hasattr(t, 'buildsetSubmitted'):
- t.buildsetSubmitted(bss)
- d.addCallback(do_notifies)
- d.addErrback(log.err, 'while notifying buildsetSubmitted')
-
- def _buildsetCompletionCallback(self, bsid, result):
- self._maybeBuildsetFinished(bsid)
-
- def _buildRequestCallback(self, notif):
- buildername = notif['buildername']
- if buildername in self._builder_observers:
- brs = buildrequest.BuildRequestStatus(buildername,
- notif['brid'], self)
- for observer in self._builder_observers[buildername]:
- if hasattr(observer, 'requestSubmitted'):
- eventually(observer.requestSubmitted, brs)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/persistent_queue.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/persistent_queue.py
deleted file mode 100644
index 0106a210..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/persistent_queue.py
+++ /dev/null
@@ -1,382 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from __future__ import with_statement
-
-
-from collections import deque
-import os
-import cPickle as pickle
-
-from zope.interface import implements, Interface
-
-
-def ReadFile(path):
- with open(path, 'rb') as f:
- return f.read()
-
-
-def WriteFile(path, buf):
- with open(path, 'wb') as f:
- f.write(buf)
-
-
-class IQueue(Interface):
- """Abstraction of a queue."""
- def pushItem(item):
- """Adds an individual item to the end of the queue.
-
- Returns an item if it was overflowed."""
-
- def insertBackChunk(items):
- """Adds a list of items as the oldest entries.
-
- Normally called in case of failure to process the data, queue the data
- back so it can be retrieved at a later time.
-
- Returns a list of items if it was overflowed."""
-
- def popChunk(nbItems=None):
- """Pop many items at once. Defaults to self.maxItems()."""
-
- def save():
- """Save the queue to storage if implemented."""
-
- def items():
- """Returns items in the queue.
-
- Warning: Can be extremely slow for queue on disk."""
-
- def nbItems():
- """Returns the number of items in the queue."""
-
- def maxItems():
- """Returns the maximum number of items this queue can hold."""
-
-
-class MemoryQueue(object):
- """Simple length bounded queue using deque.
-
- list.pop(0) operation is O(n) so for a 10000 items list, it can start to
- be real slow. On the contrary, deque.popleft() is O(1) most of the time.
- See http://docs.python.org/library/collections.html for more
- information.
- """
- implements(IQueue)
-
- def __init__(self, maxItems=None):
- self._maxItems = maxItems
- if self._maxItems is None:
- self._maxItems = 10000
- self._items = deque()
-
- def pushItem(self, item):
- ret = None
- if len(self._items) == self._maxItems:
- ret = self._items.popleft()
- self._items.append(item)
- return ret
-
- def insertBackChunk(self, chunk):
- ret = None
- excess = len(self._items) + len(chunk) - self._maxItems
- if excess > 0:
- ret = chunk[0:excess]
- chunk = chunk[excess:]
- self._items.extendleft(reversed(chunk))
- return ret
-
- def popChunk(self, nbItems=None):
- if nbItems is None:
- nbItems = self._maxItems
- if nbItems > len(self._items):
- items = list(self._items)
- self._items = deque()
- else:
- items = []
- for i in range(nbItems):
- items.append(self._items.popleft())
- return items
-
- def save(self):
- pass
-
- def items(self):
- return list(self._items)
-
- def nbItems(self):
- return len(self._items)
-
- def maxItems(self):
- return self._maxItems
-
-
-class DiskQueue(object):
- """Keeps a list of abstract items and serializes it to the disk.
-
- Use pickle for serialization."""
- implements(IQueue)
-
- def __init__(self, path, maxItems=None, pickleFn=pickle.dumps,
- unpickleFn=pickle.loads):
- """
- @path: directory to save the items.
- @maxItems: maximum number of items to keep on disk, flush the
- older ones.
- @pickleFn: function used to pack the items to disk.
- @unpickleFn: function used to unpack items from disk.
- """
- self.path = path
- self._maxItems = maxItems
- if self._maxItems is None:
- self._maxItems = 100000
- if not os.path.isdir(self.path):
- os.mkdir(self.path)
- self.pickleFn = pickleFn
- self.unpickleFn = unpickleFn
-
- # Total number of items.
- self._nbItems = 0
- # The actual items id start at one.
- self.firstItemId = 0
- self.lastItemId = 0
- self._loadFromDisk()
-
- def pushItem(self, item):
- ret = None
- if self._nbItems == self._maxItems:
- id = self._findNext(self.firstItemId)
- path = os.path.join(self.path, str(id))
- ret = self.unpickleFn(ReadFile(path))
- os.remove(path)
- self.firstItemId = id + 1
- else:
- self._nbItems += 1
- self.lastItemId += 1
- path = os.path.join(self.path, str(self.lastItemId))
- if os.path.exists(path):
- raise IOError('%s already exists.' % path)
- WriteFile(path, self.pickleFn(item))
- return ret
-
- def insertBackChunk(self, chunk):
- ret = None
- excess = self._nbItems + len(chunk) - self._maxItems
- if excess > 0:
- ret = chunk[0:excess]
- chunk = chunk[excess:]
- for i in reversed(chunk):
- self.firstItemId -= 1
- path = os.path.join(self.path, str(self.firstItemId))
- if os.path.exists(path):
- raise IOError('%s already exists.' % path)
- WriteFile(path, self.pickleFn(i))
- self._nbItems += 1
- return ret
-
- def popChunk(self, nbItems=None):
- if nbItems is None:
- nbItems = self._maxItems
- ret = []
- for i in range(nbItems):
- if self._nbItems == 0:
- break
- id = self._findNext(self.firstItemId)
- path = os.path.join(self.path, str(id))
- ret.append(self.unpickleFn(ReadFile(path)))
- os.remove(path)
- self._nbItems -= 1
- self.firstItemId = id + 1
- return ret
-
- def save(self):
- pass
-
- def items(self):
- """Warning, very slow."""
- ret = []
- for id in range(self.firstItemId, self.lastItemId + 1):
- path = os.path.join(self.path, str(id))
- if os.path.exists(path):
- ret.append(self.unpickleFn(ReadFile(path)))
- return ret
-
- def nbItems(self):
- return self._nbItems
-
- def maxItems(self):
- return self._maxItems
-
- #### Protected functions
-
- def _findNext(self, id):
- while True:
- path = os.path.join(self.path, str(id))
- if os.path.isfile(path):
- return id
- id += 1
- return None
-
- def _loadFromDisk(self):
- """Loads the queue from disk upto self.maxMemoryItems items into
- self.items.
- """
- def SafeInt(item):
- try:
- return int(item)
- except ValueError:
- return None
-
- files = filter(None, [SafeInt(x) for x in os.listdir(self.path)])
- files.sort()
- self._nbItems = len(files)
- if self._nbItems:
- self.firstItemId = files[0]
- self.lastItemId = files[-1]
-
-
-class PersistentQueue(object):
- """Keeps a list of abstract items and serializes it to the disk.
-
- It has 2 layers of queue, normally an in-memory queue and an on-disk queue.
- When the number of items in the primary queue gets too large, the new items
- are automatically saved to the secondary queue. The older items are kept in
- the primary queue.
- """
- implements(IQueue)
-
- def __init__(self, primaryQueue=None, secondaryQueue=None, path=None):
- """
- @primaryQueue: memory queue to use before buffering to disk.
- @secondaryQueue: disk queue to use as permanent buffer.
- @path: path is a shortcut when using default DiskQueue settings.
- """
- self.primaryQueue = primaryQueue
- if self.primaryQueue is None:
- self.primaryQueue = MemoryQueue()
- self.secondaryQueue = secondaryQueue
- if self.secondaryQueue is None:
- self.secondaryQueue = DiskQueue(path)
- # Preload data from the secondary queue only if we know we won't start
- # using the secondary queue right away.
- if self.secondaryQueue.nbItems() < self.primaryQueue.maxItems():
- self.primaryQueue.insertBackChunk(
- self.secondaryQueue.popChunk(self.primaryQueue.maxItems()))
-
- def pushItem(self, item):
- # If there is already items in secondaryQueue, we'd need to pop them
- # all to start inserting them into primaryQueue so don't bother and
- # just push it in secondaryQueue.
- if (self.secondaryQueue.nbItems() or
- self.primaryQueue.nbItems() == self.primaryQueue.maxItems()):
- item = self.secondaryQueue.pushItem(item)
- if item is None:
- return item
- # If item is not None, secondaryQueue overflowed. We need to push it
- # back to primaryQueue so the oldest item is dumped.
- # Or everything fit in the primaryQueue.
- return self.primaryQueue.pushItem(item)
-
- def insertBackChunk(self, chunk):
- ret = None
- # Overall excess
- excess = self.nbItems() + len(chunk) - self.maxItems()
- if excess > 0:
- ret = chunk[0:excess]
- chunk = chunk[excess:]
- # Memory excess
- excess = (self.primaryQueue.nbItems() + len(chunk) -
- self.primaryQueue.maxItems())
- if excess > 0:
- chunk2 = []
- for i in range(excess):
- chunk2.append(self.primaryQueue.items().pop())
- chunk2.reverse()
- x = self.primaryQueue.insertBackChunk(chunk)
- assert x is None, "primaryQueue.insertBackChunk did not return None"
- if excess > 0:
- x = self.secondaryQueue.insertBackChunk(chunk2)
- assert x is None, ("secondaryQueue.insertBackChunk did not return "
- " None")
- return ret
-
- def popChunk(self, nbItems=None):
- if nbItems is None:
- nbItems = self.primaryQueue.maxItems()
- ret = self.primaryQueue.popChunk(nbItems)
- nbItems -= len(ret)
- if nbItems and self.secondaryQueue.nbItems():
- ret.extend(self.secondaryQueue.popChunk(nbItems))
- return ret
-
- def save(self):
- self.secondaryQueue.insertBackChunk(self.primaryQueue.popChunk())
-
- def items(self):
- return self.primaryQueue.items() + self.secondaryQueue.items()
-
- def nbItems(self):
- return self.primaryQueue.nbItems() + self.secondaryQueue.nbItems()
-
- def maxItems(self):
- return self.primaryQueue.maxItems() + self.secondaryQueue.maxItems()
-
-
-class IndexedQueue(object):
- """Adds functionality to a IQueue object to track its usage.
-
- Adds a new member function getIndex() and modify popChunk() and
- insertBackChunk() to keep a virtual pointer to the queue's first entry
- index."""
- implements(IQueue)
-
- def __init__(self, queue):
- # Copy all the member functions from the other object that this class
- # doesn't already define.
- assert IQueue.providedBy(queue)
- def Filter(m):
- return (m[0] != '_' and callable(getattr(queue, m))
- and not hasattr(self, m))
- for member in filter(Filter, dir(queue)):
- setattr(self, member, getattr(queue, member))
- self.queue = queue
- self._index = 0
-
- def getIndex(self):
- return self._index
-
- def popChunk(self, *args, **kwargs):
- items = self.queue.popChunk(*args, **kwargs)
- if items:
- self._index += len(items)
- return items
-
- def insertBackChunk(self, items):
- self._index -= len(items)
- ret = self.queue.insertBackChunk(items)
- if ret:
- self._index += len(ret)
- return ret
-
-
-def ToIndexedQueue(queue):
- """If the IQueue wasn't already a IndexedQueue, makes it an IndexedQueue."""
- if not IQueue.providedBy(queue):
- raise TypeError("queue doesn't implement IQueue", queue)
- if isinstance(queue, IndexedQueue):
- return queue
- return IndexedQueue(queue)
-
-# vim: set ts=4 sts=4 sw=4 et:
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/progress.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/progress.py
deleted file mode 100644
index 62aae317..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/progress.py
+++ /dev/null
@@ -1,324 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from twisted.internet import reactor
-from twisted.spread import pb
-from twisted.python import log
-from buildbot import util
-from collections import defaultdict
-
-class StepProgress:
- """I keep track of how much progress a single BuildStep has made.
-
- Progress is measured along various axes. Time consumed is one that is
- available for all steps. Amount of command output is another, and may be
- better quantified by scanning the output for markers to derive number of
- files compiled, directories walked, tests run, etc.
-
- I am created when the build begins, and given to a BuildProgress object
- so it can track the overall progress of the whole build.
-
- """
-
- startTime = None
- stopTime = None
- expectedTime = None
- buildProgress = None
- debug = False
-
- def __init__(self, name, metricNames):
- self.name = name
- self.progress = {}
- self.expectations = {}
- for m in metricNames:
- self.progress[m] = None
- self.expectations[m] = None
-
- def setBuildProgress(self, bp):
- self.buildProgress = bp
-
- def setExpectations(self, metrics):
- """The step can call this to explicitly set a target value for one
- of its metrics. E.g., ShellCommands knows how many commands it will
- execute, so it could set the 'commands' expectation."""
- for metric, value in metrics.items():
- self.expectations[metric] = value
- self.buildProgress.newExpectations()
-
- def setExpectedTime(self, seconds):
- self.expectedTime = seconds
- self.buildProgress.newExpectations()
-
- def start(self):
- if self.debug: print "StepProgress.start[%s]" % self.name
- self.startTime = util.now()
-
- def setProgress(self, metric, value):
- """The step calls this as progress is made along various axes."""
- if self.debug:
- print "setProgress[%s][%s] = %s" % (self.name, metric, value)
- self.progress[metric] = value
- if self.debug:
- r = self.remaining()
- print " step remaining:", r
- self.buildProgress.newProgress()
-
- def finish(self):
- """This stops the 'time' metric and marks the step as finished
- overall. It should be called after the last .setProgress has been
- done for each axis."""
- if self.debug: print "StepProgress.finish[%s]" % self.name
- self.stopTime = util.now()
- self.buildProgress.stepFinished(self.name)
-
- def totalTime(self):
- if self.startTime != None and self.stopTime != None:
- return self.stopTime - self.startTime
-
- def remaining(self):
- if self.startTime == None:
- return self.expectedTime
- if self.stopTime != None:
- return 0 # already finished
- # TODO: replace this with cleverness that graphs each metric vs.
- # time, then finds the inverse function. Will probably need to save
- # a timestamp with each setProgress update, when finished, go back
- # and find the 2% transition points, then save those 50 values in a
- # list. On the next build, do linear interpolation between the two
- # closest samples to come up with a percentage represented by that
- # metric.
-
- # TODO: If no other metrics are available, just go with elapsed
- # time. Given the non-time-uniformity of text output from most
- # steps, this would probably be better than the text-percentage
- # scheme currently implemented.
-
- percentages = []
- for metric, value in self.progress.items():
- expectation = self.expectations[metric]
- if value != None and expectation != None:
- p = 1.0 * value / expectation
- percentages.append(p)
- if percentages:
- avg = reduce(lambda x,y: x+y, percentages) / len(percentages)
- if avg > 1.0:
- # overdue
- avg = 1.0
- if avg < 0.0:
- avg = 0.0
- if percentages and self.expectedTime != None:
- return self.expectedTime - (avg * self.expectedTime)
- if self.expectedTime is not None:
- # fall back to pure time
- return self.expectedTime - (util.now() - self.startTime)
- return None # no idea
-
-
-class WatcherState:
- def __init__(self, interval):
- self.interval = interval
- self.timer = None
- self.needUpdate = 0
-
-class BuildProgress(pb.Referenceable):
- """I keep track of overall build progress. I hold a list of StepProgress
- objects.
- """
-
- def __init__(self, stepProgresses):
- self.steps = {}
- for s in stepProgresses:
- self.steps[s.name] = s
- s.setBuildProgress(self)
- self.finishedSteps = []
- self.watchers = {}
- self.debug = 0
-
- def setExpectationsFrom(self, exp):
- """Set our expectations from the builder's Expectations object."""
- for name, metrics in exp.steps.items():
- s = self.steps.get(name)
- if s:
- s.setExpectedTime(exp.times[name])
- s.setExpectations(exp.steps[name])
-
- def newExpectations(self):
- """Call this when one of the steps has changed its expectations.
- This should trigger us to update our ETA value and notify any
- subscribers."""
- pass # subscribers are not implemented: they just poll
-
- def stepFinished(self, stepname):
- assert(stepname not in self.finishedSteps)
- self.finishedSteps.append(stepname)
- if len(self.finishedSteps) == len(self.steps.keys()):
- self.sendLastUpdates()
-
- def newProgress(self):
- r = self.remaining()
- if self.debug:
- print " remaining:", r
- if r != None:
- self.sendAllUpdates()
-
- def remaining(self):
- # sum eta of all steps
- sum = 0
- for name, step in self.steps.items():
- rem = step.remaining()
- if rem == None:
- return None # not sure
- sum += rem
- return sum
- def eta(self):
- left = self.remaining()
- if left == None:
- return None # not sure
- done = util.now() + left
- return done
-
-
- def remote_subscribe(self, remote, interval=5):
- # [interval, timer, needUpdate]
- # don't send an update more than once per interval
- self.watchers[remote] = WatcherState(interval)
- remote.notifyOnDisconnect(self.removeWatcher)
- self.updateWatcher(remote)
- self.startTimer(remote)
- log.msg("BuildProgress.remote_subscribe(%s)" % remote)
- def remote_unsubscribe(self, remote):
- # TODO: this doesn't work. I think 'remote' will always be different
- # than the object that appeared in _subscribe.
- log.msg("BuildProgress.remote_unsubscribe(%s)" % remote)
- self.removeWatcher(remote)
- #remote.dontNotifyOnDisconnect(self.removeWatcher)
- def removeWatcher(self, remote):
- #log.msg("removeWatcher(%s)" % remote)
- try:
- timer = self.watchers[remote].timer
- if timer:
- timer.cancel()
- del self.watchers[remote]
- except KeyError:
- log.msg("Weird, removeWatcher on non-existent subscriber:",
- remote)
- def sendAllUpdates(self):
- for r in self.watchers.keys():
- self.updateWatcher(r)
- def updateWatcher(self, remote):
- # an update wants to go to this watcher. Send it if we can, otherwise
- # queue it for later
- w = self.watchers[remote]
- if not w.timer:
- # no timer, so send update now and start the timer
- self.sendUpdate(remote)
- self.startTimer(remote)
- else:
- # timer is running, just mark as needing an update
- w.needUpdate = 1
- def startTimer(self, remote):
- w = self.watchers[remote]
- timer = reactor.callLater(w.interval, self.watcherTimeout, remote)
- w.timer = timer
- def sendUpdate(self, remote, last=0):
- self.watchers[remote].needUpdate = 0
- #text = self.asText() # TODO: not text, duh
- try:
- remote.callRemote("progress", self.remaining())
- if last:
- remote.callRemote("finished", self)
- except:
- log.deferr()
- self.removeWatcher(remote)
-
- def watcherTimeout(self, remote):
- w = self.watchers.get(remote, None)
- if not w:
- return # went away
- w.timer = None
- if w.needUpdate:
- self.sendUpdate(remote)
- self.startTimer(remote)
- def sendLastUpdates(self):
- for remote in self.watchers.keys():
- self.sendUpdate(remote, 1)
- self.removeWatcher(remote)
-
-
-class Expectations:
- debug = False
- # decay=1.0 ignores all but the last build
- # 0.9 is short time constant. 0.1 is very long time constant
- # TODO: let decay be specified per-metric
- decay = 0.5
-
- def __init__(self, buildprogress):
- """Create us from a successful build. We will expect each step to
- take as long as it did in that build."""
-
- # .steps maps stepname to dict2
- # dict2 maps metricname to final end-of-step value
- self.steps = defaultdict(dict)
-
- # .times maps stepname to per-step elapsed time
- self.times = {}
-
- for name, step in buildprogress.steps.items():
- self.steps[name] = {}
- for metric, value in step.progress.items():
- self.steps[name][metric] = value
- self.times[name] = None
- if step.startTime is not None and step.stopTime is not None:
- self.times[name] = step.stopTime - step.startTime
-
- def wavg(self, old, current):
- if old is None:
- return current
- if current is None:
- return old
- else:
- return (current * self.decay) + (old * (1 - self.decay))
-
- def update(self, buildprogress):
- for name, stepprogress in buildprogress.steps.items():
- old = self.times.get(name)
- current = stepprogress.totalTime()
- if current == None:
- log.msg("Expectations.update: current[%s] was None!" % name)
- continue
- new = self.wavg(old, current)
- self.times[name] = new
- if self.debug:
- print "new expected time[%s] = %s, old %s, cur %s" % \
- (name, new, old, current)
-
- for metric, current in stepprogress.progress.items():
- old = self.steps[name].get(metric)
- new = self.wavg(old, current)
- if self.debug:
- print "new expectation[%s][%s] = %s, old %s, cur %s" % \
- (name, metric, new, old, current)
- self.steps[name][metric] = new
-
- def expectedBuildTime(self):
- if None in self.times.values():
- return None
- #return sum(self.times.values())
- # python-2.2 doesn't have 'sum'. TODO: drop python-2.2 support
- s = 0
- for v in self.times.values():
- s += v
- return s
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/results.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/results.py
deleted file mode 100644
index 2b012f0e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/results.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION, RETRY = range(6)
-Results = ["success", "warnings", "failure", "skipped", "exception", "retry"]
-
-def worst_status(a, b):
- # SUCCESS > WARNINGS > FAILURE > EXCEPTION > RETRY
- # Retry needs to be considered the worst so that conusmers don't have to
- # worry about other failures undermining the RETRY.
- for s in (RETRY, EXCEPTION, FAILURE, WARNINGS, SKIPPED, SUCCESS):
- if s in (a, b):
- return s
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/slave.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/slave.py
deleted file mode 100644
index a3c5b4ec..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/slave.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import time
-from zope.interface import implements
-from buildbot import interfaces
-from buildbot.util.eventual import eventually
-
-class SlaveStatus:
- implements(interfaces.ISlaveStatus)
-
- admin = None
- host = None
- access_uri = None
- version = None
- connected = False
- graceful_shutdown = False
- paused = False
-
- def __init__(self, name):
- self.name = name
- self._lastMessageReceived = 0
- self.runningBuilds = []
- self.graceful_callbacks = []
- self.connect_times = []
-
- def getName(self):
- return self.name
- def getAdmin(self):
- return self.admin
- def getHost(self):
- return self.host
- def getAccessURI(self):
- return self.access_uri
- def getVersion(self):
- return self.version
- def isConnected(self):
- return self.connected
- def isPaused(self):
- return self.paused
- def lastMessageReceived(self):
- return self._lastMessageReceived
- def getRunningBuilds(self):
- return self.runningBuilds
- def getConnectCount(self):
- then = time.time() - 3600
- return len([ t for t in self.connect_times if t > then ])
-
- def setAdmin(self, admin):
- self.admin = admin
- def setHost(self, host):
- self.host = host
- def setAccessURI(self, access_uri):
- self.access_uri = access_uri
- def setVersion(self, version):
- self.version = version
- def setConnected(self, isConnected):
- self.connected = isConnected
- def setLastMessageReceived(self, when):
- self._lastMessageReceived = when
- def setPaused(self, isPaused):
- self.paused = isPaused
-
- def recordConnectTime(self):
- # record this connnect, and keep data for the last hour
- now = time.time()
- self.connect_times = [ t for t in self.connect_times if t > now - 3600 ] + [ now ]
-
- def buildStarted(self, build):
- self.runningBuilds.append(build)
- def buildFinished(self, build):
- self.runningBuilds.remove(build)
-
- def getGraceful(self):
- """Return the graceful shutdown flag"""
- return self.graceful_shutdown
- def setGraceful(self, graceful):
- """Set the graceful shutdown flag, and notify all the watchers"""
- self.graceful_shutdown = graceful
- for cb in self.graceful_callbacks:
- eventually(cb, graceful)
- def addGracefulWatcher(self, watcher):
- """Add watcher to the list of watchers to be notified when the
- graceful shutdown flag is changed."""
- if not watcher in self.graceful_callbacks:
- self.graceful_callbacks.append(watcher)
- def removeGracefulWatcher(self, watcher):
- """Remove watcher from the list of watchers to be notified when the
- graceful shutdown flag is changed."""
- if watcher in self.graceful_callbacks:
- self.graceful_callbacks.remove(watcher)
-
- def asDict(self):
- result = {}
- # Constant
- result['name'] = self.getName()
- result['access_uri'] = self.getAccessURI()
-
- # Transient (since it changes when the slave reconnects)
- result['host'] = self.getHost()
- result['admin'] = self.getAdmin()
- result['version'] = self.getVersion()
- result['connected'] = self.isConnected()
- result['runningBuilds'] = [b.asDict() for b in self.getRunningBuilds()]
- return result
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_gerrit.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_gerrit.py
deleted file mode 100644
index b4925ccf..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_gerrit.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-"""Push events to gerrit
-
-."""
-
-from buildbot.status.base import StatusReceiverMultiService
-from buildbot.status.builder import Results, SUCCESS, RETRY
-from twisted.internet import reactor
-from twisted.internet.protocol import ProcessProtocol
-
-def defaultReviewCB(builderName, build, result, status, arg):
- if result == RETRY:
- return None, 0, 0
-
- message = "Buildbot finished compiling your patchset\n"
- message += "on configuration: %s\n" % builderName
- message += "The result is: %s\n" % Results[result].upper()
-
- # message, verified, reviewed
- return message, (result == SUCCESS or -1), 0
-
-class GerritStatusPush(StatusReceiverMultiService):
- """Event streamer to a gerrit ssh server."""
-
- def __init__(self, server, username, reviewCB=defaultReviewCB,
- startCB=None, port=29418, reviewArg=None,
- startArg=None, **kwargs):
- """
- @param server: Gerrit SSH server's address to use for push event notifications.
- @param username: Gerrit SSH server's username.
- @param reviewCB: Callback that is called each time a build is finished, and that is used
- to define the message and review approvals depending on the build result.
- @param startCB: Callback that is called each time a build is started.
- Used to define the message sent to Gerrit.
- @param port: Gerrit SSH server's port.
- @param reviewArg: Optional argument passed to the review callback.
- @param startArg: Optional argument passed to the start callback.
- """
- StatusReceiverMultiService.__init__(self)
- # Parameters.
- self.gerrit_server = server
- self.gerrit_username = username
- self.gerrit_port = port
- self.reviewCB = reviewCB
- self.reviewArg = reviewArg
- self.startCB = startCB
- self.startArg = startArg
-
- class LocalPP(ProcessProtocol):
- def __init__(self, status):
- self.status = status
-
- def outReceived(self, data):
- print "gerritout:", data
-
- def errReceived(self, data):
- print "gerriterr:", data
-
- def processEnded(self, status_object):
- if status_object.value.exitCode:
- print "gerrit status: ERROR:", status_object
- else:
- print "gerrit status: OK"
-
- def startService(self):
- print """Starting up."""
- StatusReceiverMultiService.startService(self)
- self.status = self.parent.getStatus()
- self.status.subscribe(self)
-
- def builderAdded(self, name, builder):
- return self # subscribe to this builder
-
- def buildStarted(self, builderName, build):
- if self.startCB is not None:
- message = self.startCB(builderName, build, self.startArg)
- self.sendCodeReviews(build, message)
-
- def buildFinished(self, builderName, build, result):
- """Do the SSH gerrit verify command to the server."""
- message, verified, reviewed = self.reviewCB(builderName, build, result, self.status, self.reviewArg)
- self.sendCodeReviews(build, message, verified, reviewed)
-
- def sendCodeReviews(self, build, message, verified=0, reviewed=0):
- if message is None:
- return
-
- # Gerrit + Repo
- downloads = build.getProperty("repo_downloads")
- downloaded = build.getProperty("repo_downloaded")
- if downloads is not None and downloaded is not None:
- downloaded = downloaded.split(" ")
- if downloads and 2 * len(downloads) == len(downloaded):
- for i in range(0, len(downloads)):
- try:
- project, change1 = downloads[i].split(" ")
- except ValueError:
- return # something is wrong, abort
- change2 = downloaded[2 * i]
- revision = downloaded[2 * i + 1]
- if change1 == change2:
- self.sendCodeReview(project, revision, message, verified, reviewed)
- else:
- return # something is wrong, abort
- return
-
- # Gerrit + Git
- if build.getProperty("gerrit_branch") is not None: # used only to verify Gerrit source
- project = build.getProperty("project")
- revision = build.getProperty("got_revision")
-
- # review doesn't really work with multiple revisions, so let's
- # just assume it's None there
- if isinstance(revision, dict):
- revision = None
-
- if project is not None and revision is not None:
- self.sendCodeReview(project, revision, message, verified, reviewed)
- return
-
- def sendCodeReview(self, project, revision, message=None, verified=0, reviewed=0):
- command = ["ssh", self.gerrit_username + "@" + self.gerrit_server, "-p %d" % self.gerrit_port,
- "gerrit", "review", "--project %s" % str(project)]
- if message:
- command.append("--message '%s'" % message.replace("'","\""))
- if verified:
- command.extend(["--verified %d" % int(verified)])
- if reviewed:
- command.extend(["--code-review %d" % int(reviewed)])
- command.append(str(revision))
- print command
- reactor.spawnProcess(self.LocalPP(self), "ssh", command)
-
-# vim: set ts=4 sts=4 sw=4 et:
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_push.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_push.py
deleted file mode 100644
index a3ecf5c0..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/status_push.py
+++ /dev/null
@@ -1,442 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from __future__ import with_statement
-
-
-"""Push events to an abstract receiver.
-
-Implements the HTTP receiver."""
-
-import datetime
-import os
-import urllib
-import urlparse
-
-try:
- import simplejson as json
- assert json
-except ImportError:
- import json
-
-from buildbot import config
-from buildbot.status.base import StatusReceiverMultiService
-from buildbot.status.persistent_queue import DiskQueue, IndexedQueue, \
- MemoryQueue, PersistentQueue
-from buildbot.status.web.status_json import FilterOut
-from twisted.internet import defer, reactor
-from twisted.python import log
-from twisted.web import client
-
-
-
-class StatusPush(StatusReceiverMultiService):
- """Event streamer to a abstract channel.
-
- It uses IQueue to batch push requests and queue the data when
- the receiver is down.
- When a PersistentQueue object is used, the items are saved to disk on master
- shutdown so they can be pushed back when the master is restarted.
- """
-
- def __init__(self, serverPushCb, queue=None, path=None, filter=True,
- bufferDelay=1, retryDelay=5, blackList=None):
- """
- @serverPushCb: callback to be used. It receives 'self' as parameter. It
- should call self.queueNextServerPush() when it's done to queue the next
- push. It is guaranteed that the queue is not empty when this function is
- called.
- @queue: a item queue that implements IQueue.
- @path: path to save config.
- @filter: when True (default), removes all "", None, False, [] or {}
- entries.
- @bufferDelay: amount of time events are queued before sending, to
- reduce the number of push requests rate. This is the delay between the
- end of a request to initializing a new one.
- @retryDelay: amount of time between retries when no items were pushed on
- last serverPushCb call.
- @blackList: events that shouldn't be sent.
- """
- StatusReceiverMultiService.__init__(self)
-
- # Parameters.
- self.queue = queue
- if self.queue is None:
- self.queue = MemoryQueue()
- self.queue = IndexedQueue(self.queue)
- self.path = path
- self.filter = filter
- self.bufferDelay = bufferDelay
- self.retryDelay = retryDelay
- if not callable(serverPushCb):
- raise NotImplementedError('Please pass serverPushCb parameter.')
- def hookPushCb():
- # Update the index so we know if the next push succeed or not, don't
- # update the value when the queue is empty.
- if not self.queue.nbItems():
- return
- self.lastIndex = self.queue.getIndex()
- return serverPushCb(self)
- self.serverPushCb = hookPushCb
- self.blackList = blackList
-
- # Other defaults.
- # IDelayedCall object that represents the next queued push.
- self.task = None
- self.stopped = False
- self.lastIndex = -1
- self.state = {}
- self.state['started'] = str(datetime.datetime.utcnow())
- self.state['next_id'] = 1
- self.state['last_id_pushed'] = 0
- # Try to load back the state.
- if self.path and os.path.isdir(self.path):
- state_path = os.path.join(self.path, 'state')
- if os.path.isfile(state_path):
- with open(state_path, 'r') as f:
- self.state.update(json.load(f))
-
- if self.queue.nbItems():
- # Last shutdown was not clean, don't wait to send events.
- self.queueNextServerPush()
-
- def startService(self):
- """Starting up."""
- StatusReceiverMultiService.startService(self)
- self.status = self.parent.getStatus()
- self.status.subscribe(self)
- self.initialPush()
-
- def wasLastPushSuccessful(self):
- """Returns if the "virtual pointer" in the queue advanced."""
- return self.lastIndex <= self.queue.getIndex()
-
- def queueNextServerPush(self):
- """Queue the next push or call it immediately.
-
- Called to signal new items are available to be sent or on shutdown.
- A timer should be queued to trigger a network request or the callback
- should be called immediately. If a status push is already queued, ignore
- the current call."""
- # Determine the delay.
- if self.wasLastPushSuccessful():
- if self.stopped:
- # Shutting down.
- delay = 0
- else:
- # Normal case.
- delay = self.bufferDelay
- else:
- if self.stopped:
- # Too bad, we can't do anything now, we're shutting down and the
- # receiver is also down. We'll just save the objects to disk.
- return
- else:
- # The server is inaccessible, retry less often.
- delay = self.retryDelay
-
- # Cleanup a previously queued task if necessary.
- if self.task:
- # Warning: we could be running inside the task.
- if self.task.active():
- # There was already a task queue, don't requeue it, just let it
- # go.
- return
- else:
- if self.task.active():
- # There was a task queued but it is requested to call it
- # *right now* so cancel it.
- self.task.cancel()
- # Otherwise, it was just a stray object.
- self.task = None
-
- # Do the queue/direct call.
- if delay:
- # Call in delay seconds.
- self.task = reactor.callLater(delay, self.serverPushCb)
- elif self.stopped:
- if not self.queue.nbItems():
- return
- # Call right now, we're shutting down.
- @defer.inlineCallbacks
- def BlockForEverythingBeingSent():
- yield self.serverPushCb()
- return BlockForEverythingBeingSent()
- else:
- # delay should never be 0. That can cause Buildbot to spin tightly
- # trying to push events that may not be received well by a status
- # listener.
- log.err('Did not expect delay to be 0, but it is.')
- return
-
- def stopService(self):
- """Shutting down."""
- self.finalPush()
- self.stopped = True
- if (self.task and self.task.active()):
- # We don't have time to wait, force an immediate call.
- self.task.cancel()
- self.task = None
- d = self.queueNextServerPush()
- elif self.wasLastPushSuccessful():
- d = self.queueNextServerPush()
- else:
- d = defer.succeed(None)
-
- # We're dying, make sure we save the results.
- self.queue.save()
- if self.path and os.path.isdir(self.path):
- state_path = os.path.join(self.path, 'state')
- with open(state_path, 'w') as f:
- json.dump(self.state, f, sort_keys=True,
- indent=2)
- # Make sure all Deferreds are called on time and in a sane order.
- defers = filter(None, [d, StatusReceiverMultiService.stopService(self)])
- return defer.DeferredList(defers)
-
- def push(self, event, **objs):
- """Push a new event.
-
- The new event will be either:
- - Queued in memory to reduce network usage
- - Queued to disk when the sink server is down
- - Pushed (along the other queued items) to the server
- """
- if self.blackList and event in self.blackList:
- return
- # First, generate the packet.
- packet = {}
- packet['id'] = self.state['next_id']
- self.state['next_id'] += 1
- packet['timestamp'] = str(datetime.datetime.utcnow())
- packet['project'] = self.status.getTitle()
- packet['started'] = self.state['started']
- packet['event'] = event
- packet['payload'] = {}
- for obj_name, obj in objs.items():
- if hasattr(obj, 'asDict'):
- obj = obj.asDict()
- if self.filter:
- obj = FilterOut(obj)
- packet['payload'][obj_name] = obj
- self.queue.pushItem(packet)
- if self.task is None or not self.task.active():
- # No task queued since it was probably idle, let's queue a task.
- return self.queueNextServerPush()
-
- #### Events
-
- def initialPush(self):
- # Push everything we want to push from the initial configuration.
- self.push('start', status=self.status)
-
- def finalPush(self):
- self.push('shutdown', status=self.status)
-
- def requestSubmitted(self, request):
- self.push('requestSubmitted', request=request)
-
- def requestCancelled(self, builder, request):
- self.push('requestCancelled', builder=builder, request=request)
-
- def buildsetSubmitted(self, buildset):
- self.push('buildsetSubmitted', buildset=buildset)
-
- def builderAdded(self, builderName, builder):
- self.push('builderAdded', builderName=builderName, builder=builder)
- return self
-
- def builderChangedState(self, builderName, state):
- self.push('builderChangedState', builderName=builderName, state=state)
-
- def buildStarted(self, builderName, build):
- self.push('buildStarted', build=build)
- return self
-
- def buildETAUpdate(self, build, ETA):
- self.push('buildETAUpdate', build=build, ETA=ETA)
-
- def stepStarted(self, build, step):
- self.push('stepStarted',
- properties=build.getProperties().asList(),
- step=step)
-
- def stepTextChanged(self, build, step, text):
- self.push('stepTextChanged',
- properties=build.getProperties().asList(),
- step=step,
- text=text)
-
- def stepText2Changed(self, build, step, text2):
- self.push('stepText2Changed',
- properties=build.getProperties().asList(),
- step=step,
- text2=text2)
-
- def stepETAUpdate(self, build, step, ETA, expectations):
- self.push('stepETAUpdate',
- properties=build.getProperties().asList(),
- step=step,
- ETA=ETA,
- expectations=expectations)
-
- def logStarted(self, build, step, log):
- self.push('logStarted',
- properties=build.getProperties().asList(),
- step=step)
-
- def logFinished(self, build, step, log):
- self.push('logFinished',
- properties=build.getProperties().asList(),
- step=step)
-
- def stepFinished(self, build, step, results):
- self.push('stepFinished',
- properties=build.getProperties().asList(),
- step=step)
-
- def buildFinished(self, builderName, build, results):
- self.push('buildFinished', build=build)
-
- def builderRemoved(self, builderName):
- self.push('buildedRemoved', builderName=builderName)
-
- def changeAdded(self, change):
- self.push('changeAdded', change=change)
-
- def slaveConnected(self, slavename):
- self.push('slaveConnected', slave=self.status.getSlave(slavename))
-
- def slaveDisconnected(self, slavename):
- self.push('slaveDisconnected', slavename=slavename)
-
-
-class HttpStatusPush(StatusPush):
- """Event streamer to a HTTP server."""
-
- def __init__(self, serverUrl, debug=None, maxMemoryItems=None,
- maxDiskItems=None, chunkSize=200, maxHttpRequestSize=2**20,
- extra_post_params=None, **kwargs):
- """
- @serverUrl: Base URL to be used to push events notifications.
- @maxMemoryItems: Maximum number of items to keep queued in memory.
- @maxDiskItems: Maximum number of items to buffer to disk, if 0, doesn't
- use disk at all.
- @debug: Save the json with nice formatting.
- @chunkSize: maximum number of items to send in each at each HTTP POST.
- @maxHttpRequestSize: limits the size of encoded data for AE, the default
- is 1MB.
- """
- if not serverUrl:
- raise config.ConfigErrors(['HttpStatusPush requires a serverUrl'])
-
- # Parameters.
- self.serverUrl = serverUrl
- self.extra_post_params = extra_post_params or {}
- self.debug = debug
- self.chunkSize = chunkSize
- self.lastPushWasSuccessful = True
- self.maxHttpRequestSize = maxHttpRequestSize
- if maxDiskItems != 0:
- # The queue directory is determined by the server url.
- path = ('events_' +
- urlparse.urlparse(self.serverUrl)[1].split(':')[0])
- queue = PersistentQueue(
- primaryQueue=MemoryQueue(maxItems=maxMemoryItems),
- secondaryQueue=DiskQueue(path, maxItems=maxDiskItems))
- else:
- path = None
- queue = MemoryQueue(maxItems=maxMemoryItems)
-
- # Use the unbounded method.
- StatusPush.__init__(self, serverPushCb=HttpStatusPush.pushHttp,
- queue=queue, path=path, **kwargs)
-
- def wasLastPushSuccessful(self):
- return self.lastPushWasSuccessful
-
- def popChunk(self):
- """Pops items from the pending list.
-
- They must be queued back on failure."""
- if self.wasLastPushSuccessful():
- chunkSize = self.chunkSize
- else:
- chunkSize = 1
-
- while True:
- items = self.queue.popChunk(chunkSize)
- newitems = []
- for item in items:
- if hasattr(item, 'asDict'):
- newitems.append(item.asDict())
- else:
- newitems.append(item)
- if self.debug:
- packets = json.dumps(newitems, indent=2, sort_keys=True)
- else:
- packets = json.dumps(newitems, separators=(',',':'))
- params = {'packets': packets}
- params.update(self.extra_post_params)
- data = urllib.urlencode(params)
- if (not self.maxHttpRequestSize or
- len(data) < self.maxHttpRequestSize):
- return (data, items)
-
- if chunkSize == 1:
- # This packet is just too large. Drop this packet.
- log.msg("ERROR: packet %s was dropped, too large: %d > %d" %
- (items[0]['id'], len(data), self.maxHttpRequestSize))
- chunkSize = self.chunkSize
- else:
- # Try with half the packets.
- chunkSize /= 2
- self.queue.insertBackChunk(items)
-
- def pushHttp(self):
- """Do the HTTP POST to the server."""
- (encoded_packets, items) = self.popChunk()
-
- def Success(result):
- """Queue up next push."""
- log.msg('Sent %d events to %s' % (len(items), self.serverUrl))
- self.lastPushWasSuccessful = True
- return self.queueNextServerPush()
-
- def Failure(result):
- """Insert back items not sent and queue up next push."""
- # Server is now down.
- log.msg('Failed to push %d events to %s: %s' %
- (len(items), self.serverUrl, str(result)))
- self.queue.insertBackChunk(items)
- if self.stopped:
- # Bad timing, was being called on shutdown and the server died
- # on us. Make sure the queue is saved since we just queued back
- # items.
- self.queue.save()
- self.lastPushWasSuccessful = False
- return self.queueNextServerPush()
-
- # Trigger the HTTP POST request.
- headers = {'Content-Type': 'application/x-www-form-urlencoded'}
- connection = client.getPage(self.serverUrl,
- method='POST',
- postdata=encoded_packets,
- headers=headers,
- agent='buildbot')
- connection.addCallbacks(Success, Failure)
- return connection
-
-# vim: set ts=4 sts=4 sw=4 et:
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/testresult.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/testresult.py
deleted file mode 100644
index 20002405..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/testresult.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from zope.interface import implements
-from buildbot import interfaces
-
-class TestResult:
- implements(interfaces.ITestResult)
-
- def __init__(self, name, results, text, logs):
- assert isinstance(name, tuple)
- self.name = name
- self.results = results
- self.text = text
- self.logs = logs
-
- def getName(self):
- return self.name
-
- def getResults(self):
- return self.results
-
- def getText(self):
- return self.text
-
- def getLogs(self):
- return self.logs
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/tinderbox.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/tinderbox.py
deleted file mode 100644
index 1694c243..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/tinderbox.py
+++ /dev/null
@@ -1,276 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from email.Message import Message
-from email.Utils import formatdate
-
-from zope.interface import implements
-from twisted.internet import defer
-
-from buildbot import interfaces
-from buildbot.status import mail
-from buildbot.status.results import SUCCESS, WARNINGS, EXCEPTION, RETRY
-from buildbot.steps.shell import WithProperties
-
-import gzip, bz2, base64, re, cStringIO
-
-# TODO: docs, maybe a test of some sort just to make sure it actually imports
-# and can format email without raising an exception.
-
-class TinderboxMailNotifier(mail.MailNotifier):
- """This is a Tinderbox status notifier. It can send e-mail to a number of
- different tinderboxes or people. E-mails are sent at the beginning and
- upon completion of each build. It can be configured to send out e-mails
- for only certain builds.
-
- The most basic usage is as follows::
- TinderboxMailNotifier(fromaddr="buildbot@localhost",
- tree="MyTinderboxTree",
- extraRecipients=["tinderboxdaemon@host.org"])
-
- The builder name (as specified in master.cfg) is used as the "build"
- tinderbox option.
-
- """
- implements(interfaces.IEmailSender)
-
- compare_attrs = ["extraRecipients", "fromaddr", "categories", "builders",
- "addLogs", "relayhost", "subject", "binaryURL", "tree",
- "logCompression", "errorparser", "columnName",
- "useChangeTime"]
-
- def __init__(self, fromaddr, tree, extraRecipients,
- categories=None, builders=None, relayhost="localhost",
- subject="buildbot %(result)s in %(builder)s", binaryURL="",
- logCompression="", errorparser="unix", columnName=None,
- useChangeTime=False):
- """
- @type fromaddr: string
- @param fromaddr: the email address to be used in the 'From' header.
-
- @type tree: string
- @param tree: The Tinderbox tree to post to.
- When tree is a WithProperties instance it will be
- interpolated as such. See WithProperties for more detail
-
- @type extraRecipients: tuple of string
- @param extraRecipients: E-mail addresses of recipients. This should at
- least include the tinderbox daemon.
-
- @type categories: list of strings
- @param categories: a list of category names to serve status
- information for. Defaults to None (all
- categories). Use either builders or categories,
- but not both.
-
- @type builders: list of strings
- @param builders: a list of builder names for which mail should be
- sent. Defaults to None (send mail for all builds).
- Use either builders or categories, but not both.
-
- @type relayhost: string
- @param relayhost: the host to which the outbound SMTP connection
- should be made. Defaults to 'localhost'
-
- @type subject: string
- @param subject: a string to be used as the subject line of the message.
- %(builder)s will be replaced with the name of the
- %builder which provoked the message.
- This parameter is not significant for the tinderbox
- daemon.
-
- @type binaryURL: string
- @param binaryURL: If specified, this should be the location where final
- binary for a build is located.
- (ie. http://www.myproject.org/nightly/08-08-2006.tgz)
- It will be posted to the Tinderbox.
-
- @type logCompression: string
- @param logCompression: The type of compression to use on the log.
- Valid options are"bzip2" and "gzip". gzip is
- only known to work on Python 2.4 and above.
-
- @type errorparser: string
- @param errorparser: The error parser that the Tinderbox server
- should use when scanning the log file.
- Default is "unix".
-
- @type columnName: string
- @param columnName: When columnName is None, use the buildername as
- the Tinderbox column name. When columnName is a
- string this exact string will be used for all
- builders that this TinderboxMailNotifier cares
- about (not recommended). When columnName is a
- WithProperties instance it will be interpolated
- as such. See WithProperties for more detail.
- @type useChangeTime: bool
- @param useChangeTime: When True, the time of the first Change for a
- build is used as the builddate. When False,
- the current time is used as the builddate.
- """
-
- mail.MailNotifier.__init__(self, fromaddr, categories=categories,
- builders=builders, relayhost=relayhost,
- subject=subject,
- extraRecipients=extraRecipients,
- sendToInterestedUsers=False)
- assert isinstance(tree, basestring) \
- or isinstance(tree, WithProperties), \
- "tree must be a string or a WithProperties instance"
- self.tree = tree
- self.binaryURL = binaryURL
- self.logCompression = logCompression
- self.errorparser = errorparser
- self.useChangeTime = useChangeTime
- assert columnName is None or type(columnName) is str \
- or isinstance(columnName, WithProperties), \
- "columnName must be None, a string, or a WithProperties instance"
- self.columnName = columnName
-
- def buildStarted(self, name, build):
- builder = build.getBuilder()
- if self.builders is not None and name not in self.builders:
- return # ignore this Build
- if self.categories is not None and \
- builder.category not in self.categories:
- return # ignore this build
- self.buildMessage(name, build, "building")
-
- @defer.inlineCallbacks
- def buildMessage(self, name, build, results):
- text = ""
- res = ""
- # shortform
- t = "tinderbox:"
-
- tree = yield build.render(self.tree)
- text += "%s tree: %s\n" % (t, tree)
-
- # the start time
- # getTimes() returns a fractioned time that tinderbox doesn't understand
- builddate = int(build.getTimes()[0])
- # attempt to pull a Change time from this Build's Changes.
- # if that doesn't work, fall back on the current time
- if self.useChangeTime:
- try:
- builddate = build.getChanges()[-1].when
- except:
- pass
- text += "%s builddate: %s\n" % (t, builddate)
- text += "%s status: " % t
-
- if results == "building":
- res = "building"
- text += res
- elif results == SUCCESS:
- res = "success"
- text += res
- elif results == WARNINGS:
- res = "testfailed"
- text += res
- elif results in (EXCEPTION, RETRY):
- res = "exception"
- text += res
- else:
- res += "busted"
- text += res
-
- text += "\n";
-
- if self.columnName is None:
- # use the builder name
- text += "%s build: %s\n" % (t, name)
- else:
- columnName = yield build.render(self.columnName)
- text += "%s build: %s\n" % (t, columnName)
- text += "%s errorparser: %s\n" % (t, self.errorparser)
-
- # if the build just started...
- if results == "building":
- text += "%s END\n" % t
- # if the build finished...
- else:
- text += "%s binaryurl: %s\n" % (t, self.binaryURL)
- text += "%s logcompression: %s\n" % (t, self.logCompression)
-
- # logs will always be appended
- logEncoding = ""
- tinderboxLogs = ""
- for bs in build.getSteps():
- # Make sure that shortText is a regular string, so that bad
- # data in the logs don't generate UnicodeDecodeErrors
- shortText = "%s\n" % ' '.join(bs.getText()).encode('ascii', 'replace')
-
- # ignore steps that haven't happened
- if not re.match(".*[^\s].*", shortText):
- continue
- # we ignore TinderboxPrint's here so we can do things like:
- # ShellCommand(command=['echo', 'TinderboxPrint:', ...])
- if re.match(".+TinderboxPrint.*", shortText):
- shortText = shortText.replace("TinderboxPrint",
- "Tinderbox Print")
- logs = bs.getLogs()
-
- tinderboxLogs += "======== BuildStep started ========\n"
- tinderboxLogs += shortText
- tinderboxLogs += "=== Output ===\n"
- for log in logs:
- logText = log.getTextWithHeaders()
- # Because we pull in the log headers here we have to ignore
- # some of them. Basically, if we're TinderboxPrint'ing in
- # a ShellCommand, the only valid one(s) are at the start
- # of a line. The others are prendeded by whitespace, quotes,
- # or brackets/parentheses
- for line in logText.splitlines():
- if re.match(".+TinderboxPrint.*", line):
- line = line.replace("TinderboxPrint",
- "Tinderbox Print")
- tinderboxLogs += line + "\n"
-
- tinderboxLogs += "=== Output ended ===\n"
- tinderboxLogs += "======== BuildStep ended ========\n"
-
- if self.logCompression == "bzip2":
- cLog = bz2.compress(tinderboxLogs)
- tinderboxLogs = base64.encodestring(cLog)
- logEncoding = "base64"
- elif self.logCompression == "gzip":
- cLog = cStringIO.StringIO()
- gz = gzip.GzipFile(mode="w", fileobj=cLog)
- gz.write(tinderboxLogs)
- gz.close()
- cLog = cLog.getvalue()
- tinderboxLogs = base64.encodestring(cLog)
- logEncoding = "base64"
-
- text += "%s logencoding: %s\n" % (t, logEncoding)
- text += "%s END\n\n" % t
- text += tinderboxLogs
- text += "\n"
-
- m = Message()
- m.set_payload(text)
-
- m['Date'] = formatdate(localtime=True)
- m['Subject'] = self.subject % { 'result': res,
- 'builder': name,
- }
- m['From'] = self.fromaddr
- # m['To'] is added later
-
- d = defer.DeferredList([])
- d.addCallback(self._gotRecipients, self.extraRecipients, m)
- defer.returnValue((yield d))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py
+++ /dev/null
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py
deleted file mode 100644
index 0a5e068b..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from buildbot.status.web.base import HtmlResource
-import buildbot
-import twisted
-import sys
-import jinja2
-
-class AboutBuildbot(HtmlResource):
- pageTitle = "About this Buildbot"
-
- def content(self, request, cxt):
- cxt.update(dict(buildbot=buildbot.version,
- twisted=twisted.__version__,
- jinja=jinja2.__version__,
- python=sys.version,
- platform=sys.platform))
-
- template = request.site.buildbot_service.templates.get_template("about.html")
- template.autoescape = True
- return template.render(**cxt)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py
deleted file mode 100644
index e9b168c9..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import os
-from zope.interface import Interface, Attribute, implements
-from buildbot.status.web.base import HtmlResource, ActionResource
-from buildbot.status.web.base import path_to_authfail
-
-from buildbot.process.users import users
-
-class IAuth(Interface):
- """
- Represent an authentication method.
-
- Note that each IAuth instance contains a link to the BuildMaster that
- will be set once the IAuth instance is initialized.
- """
-
- master = Attribute('master', "Link to BuildMaster, set when initialized")
-
- def authenticate(self, user, passwd):
- """Check whether C{user} / C{passwd} are valid."""
-
- def getUserInfo(self, user):
- """return dict with user info.
- dict( fullName="", email="", groups=[])
- """
-
- def errmsg(self):
- """Get the reason authentication failed."""
-
-class AuthBase:
- master = None # set in status.web.baseweb
- err = ""
-
- def errmsg(self):
- return self.err
-
- def getUserInfo(self, user):
- """default dummy impl"""
- return dict(userName=user, fullName=user, email=user+"@localhost", groups=[ user ])
-
-class BasicAuth(AuthBase):
- implements(IAuth)
- """Implement basic authentication against a list of user/passwd."""
-
- userpass = []
- """List of user/pass tuples."""
-
- def __init__(self, userpass):
- """C{userpass} is a list of (user, passwd)."""
- for item in userpass:
- assert isinstance(item, tuple) or isinstance(item, list)
- u, p = item
- assert isinstance(u, str)
- assert isinstance(p, str)
- self.userpass = userpass
-
- def authenticate(self, user, passwd):
- """Check that C{user}/C{passwd} is a valid user/pass tuple."""
- if not self.userpass:
- self.err = "Bad self.userpass data"
- return False
- for u, p in self.userpass:
- if user == u and passwd == p:
- self.err = ""
- return True
- self.err = "Invalid username or password"
- return False
-
-class HTPasswdAuth(AuthBase):
- implements(IAuth)
- """Implement authentication against an .htpasswd file."""
-
- file = ""
- """Path to the .htpasswd file to use."""
-
- def __init__(self, file):
- """C{file} is a path to an .htpasswd file."""
- assert os.path.exists(file)
- self.file = file
-
- def authenticate(self, user, passwd):
- """Authenticate C{user} and C{passwd} against an .htpasswd file"""
- if not os.path.exists(self.file):
- self.err = "No such file: " + self.file
- return False
- # Fetch each line from the .htpasswd file and split it into a
- # [user, passwd] array.
- lines = [l.rstrip().split(':', 1)
- for l in file(self.file).readlines()]
- # Keep only the line for this login
- lines = [l for l in lines if l[0] == user]
- if not lines:
- self.err = "Invalid user/passwd"
- return False
- hash = lines[0][1]
- res = self.validatePassword(passwd, hash)
- if res:
- self.err = ""
- else:
- self.err = "Invalid user/passwd"
- return res
-
- def validatePassword(self, passwd, hash):
- # This is the DES-hash of the password. The first two characters are
- # the salt used to introduce disorder in the DES algorithm.
- from crypt import crypt #@UnresolvedImport
- return hash == crypt(passwd, hash[0:2])
-
-
-class HTPasswdAprAuth(HTPasswdAuth):
- implements(IAuth)
- """Implement authentication against an .htpasswd file based on libaprutil"""
-
- file = ""
- """Path to the .htpasswd file to use."""
-
- def __init__(self, file):
- HTPasswdAuth.__init__(self, file)
-
- # Try to load libaprutil throug ctypes
- self.apr = None
- try:
- from ctypes import CDLL
- from ctypes.util import find_library
- lib = find_library("aprutil-1")
- if lib:
- self.apr = CDLL(lib)
- except:
- self.apr = None
-
- def validatePassword(self, passwd, hash):
- # Use apr_password_validate from libaprutil if libaprutil is available.
- # Fallback to DES only checking from HTPasswdAuth
- if self.apr:
- return self.apr.apr_password_validate(passwd, hash) == 0
- else:
- return HTPasswdAuth.validatePassword(self, passwd, hash)
-
-class UsersAuth(AuthBase):
- """Implement authentication against users in database"""
- implements(IAuth)
-
- def authenticate(self, user, passwd):
- """
- It checks for a matching uid in the database for the credentials
- and return True if a match is found, False otherwise.
-
- @param user: username portion of user credentials
- @type user: string
-
- @param passwd: password portion of user credentials
- @type passwd: string
-
- @returns: boolean via deferred.
- """
- d = self.master.db.users.getUserByUsername(user)
- def check_creds(user):
- if user:
- if users.check_passwd(passwd, user['bb_password']):
- return True
- self.err = "no user found with those credentials"
- return False
- d.addCallback(check_creds)
- return d
-
-class AuthFailResource(HtmlResource):
- pageTitle = "Authentication Failed"
-
- def content(self, request, cxt):
- templates =request.site.buildbot_service.templates
- template = templates.get_template("authfail.html")
- return template.render(**cxt)
-
-class AuthzFailResource(HtmlResource):
- pageTitle = "Authorization Failed"
-
- def content(self, request, cxt):
- templates =request.site.buildbot_service.templates
- template = templates.get_template("authzfail.html")
- return template.render(**cxt)
-
-class LoginResource(ActionResource):
-
- def performAction(self, request):
- authz = self.getAuthz(request)
- d = authz.login(request)
- def on_login(res):
- if res:
- status = request.site.buildbot_service.master.status
- root = status.getBuildbotURL()
- return request.requestHeaders.getRawHeaders('referer',
- [root])[0]
- else:
- return path_to_authfail(request)
- d.addBoth(on_login)
- return d
-
-class LogoutResource(ActionResource):
-
- def performAction(self, request):
- authz = self.getAuthz(request)
- authz.logout(request)
- status = request.site.buildbot_service.master.status
- root = status.getBuildbotURL()
- return request.requestHeaders.getRawHeaders('referer',[root])[0]
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py
deleted file mode 100644
index dace7f23..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py
+++ /dev/null
@@ -1,188 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from twisted.internet import defer
-from buildbot.status.web.auth import IAuth
-from buildbot.status.web.session import SessionManager
-
-COOKIE_KEY="BuildBotSession"
-class Authz(object):
- """Decide who can do what."""
-
- knownActions = [
- # If you add a new action here, be sure to also update the documentation
- # at docs/manual/cfg-statustargets.rst.
- 'view',
- 'gracefulShutdown',
- 'forceBuild',
- 'forceAllBuilds',
- 'pingBuilder',
- 'stopBuild',
- 'stopAllBuilds',
- 'cancelPendingBuild',
- 'cancelAllPendingBuilds',
- 'stopChange',
- 'cleanShutdown',
- 'showUsersPage',
- 'pauseSlave',
- ]
-
- def __init__(self,
- default_action=False,
- auth=None,
- useHttpHeader=False,
- httpLoginUrl=False,
- view=True,
- **kwargs):
- self.auth = auth
- if auth:
- assert IAuth.providedBy(auth)
-
- self.useHttpHeader = useHttpHeader
- self.httpLoginUrl = httpLoginUrl
-
- self.config = dict((a, default_action) for a in self.knownActions)
- self.config['view'] = view
- for act in self.knownActions:
- if act in kwargs:
- self.config[act] = kwargs[act]
- del kwargs[act]
-
- self.sessions = SessionManager()
- if kwargs:
- raise ValueError("unknown authorization action(s) " + ", ".join(kwargs.keys()))
-
- def session(self, request):
- if COOKIE_KEY in request.received_cookies:
- cookie = request.received_cookies[COOKIE_KEY]
- return self.sessions.get(cookie)
- return None
-
- def authenticated(self, request):
- if self.useHttpHeader:
- return request.getUser() != ''
- return self.session(request) is not None
-
- def getUserInfo(self, user):
- if self.useHttpHeader:
- return dict(userName=user, fullName=user, email=user, groups=[user])
- s = self.sessions.getUser(user)
- if s:
- return s.infos
-
- def getUsername(self, request):
- """Get the userid of the user"""
- if self.useHttpHeader:
- return request.getUser()
- s = self.session(request)
- if s:
- return s.user
- return request.args.get("username", ["<unknown>"])[0]
-
- def getUsernameHTML(self, request):
- """Get the user formatated in html (with possible link to email)"""
- if self.useHttpHeader:
- return request.getUser()
- s = self.session(request)
- if s:
- return s.userInfosHTML()
- return "not authenticated?!"
-
- def getUsernameFull(self, request):
- """Get the full username as fullname <email>"""
- if self.useHttpHeader:
- return request.getUser()
- s = self.session(request)
- if s:
- return "%(fullName)s <%(email)s>" % (s.infos)
- else:
- return request.args.get("username", ["<unknown>"])[0]
-
-
- def getPassword(self, request):
- if self.useHttpHeader:
- return request.getPassword()
- return request.args.get("passwd", ["<no-password>"])[0]
-
- def advertiseAction(self, action, request):
- """Should the web interface even show the form for ACTION?"""
- if action not in self.knownActions:
- raise KeyError("unknown action")
- cfg = self.config.get(action, False)
- if cfg:
- if cfg == 'auth' or callable(cfg):
- return self.authenticated(request)
- return cfg
-
- def actionAllowed(self, action, request, *args):
- """Is this ACTION allowed, given this http REQUEST?"""
- if action not in self.knownActions:
- raise KeyError("unknown action")
- cfg = self.config.get(action, False)
- if cfg:
- if cfg == 'auth' or callable(cfg):
- if not self.auth:
- return defer.succeed(False)
- def check_authenticate(res):
- if callable(cfg) and not cfg(self.getUsername(request), *args):
- return False
- return True
- # retain old behaviour, if people have scripts
- # without cookie support
- passwd = self.getPassword(request)
- if self.authenticated(request):
- return defer.succeed(check_authenticate(None))
- elif passwd != "<no-password>":
- def check_login(cookie):
- ret = False
- if isinstance(cookie, str):
- ret = check_authenticate(None)
- self.sessions.remove(cookie)
- return ret
- d = self.login(request)
- d.addBoth(check_login)
- return d
- else:
- return defer.succeed(False)
- return defer.succeed(cfg)
-
- def login(self, request):
- """Login one user, and return session cookie"""
- if self.authenticated(request):
- return defer.succeed(False)
-
- user = request.args.get("username", ["<unknown>"])[0]
- passwd = request.args.get("passwd", ["<no-password>"])[0]
- if user == "<unknown>" or passwd == "<no-password>":
- return defer.succeed(False)
- if not self.auth:
- return defer.succeed(False)
- d = defer.maybeDeferred(self.auth.authenticate, user, passwd)
-
- def check_authenticate(res):
- if res:
- cookie, s = self.sessions.new(user, self.auth.getUserInfo(user))
- request.addCookie(COOKIE_KEY, cookie, expires=s.getExpiration(), path="/")
- request.received_cookies = {COOKIE_KEY: cookie}
- return cookie
- else:
- return False
- d.addBoth(check_authenticate)
- return d
-
- def logout(self, request):
- if COOKIE_KEY in request.received_cookies:
- cookie = request.received_cookies[COOKIE_KEY]
- self.sessions.remove(cookie)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py
deleted file mode 100644
index 47a3f344..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py
+++ /dev/null
@@ -1,806 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import urlparse, urllib, time, re
-import os, cgi, sys, locale
-import jinja2
-from zope.interface import Interface
-from twisted.internet import defer
-from twisted.web import resource, static, server
-from twisted.python import log
-from buildbot.status import builder, buildstep, build
-from buildbot.status.results import SUCCESS, WARNINGS, FAILURE, SKIPPED
-from buildbot.status.results import EXCEPTION, RETRY
-from buildbot import version, util
-from buildbot.process.properties import Properties
-
-class ITopBox(Interface):
- """I represent a box in the top row of the waterfall display: the one
- which shows the status of the last build for each builder."""
- def getBox(self, request):
- """Return a Box instance, which can produce a <td> cell.
- """
-
-class ICurrentBox(Interface):
- """I represent the 'current activity' box, just above the builder name."""
- def getBox(self, status):
- """Return a Box instance, which can produce a <td> cell.
- """
-
-class IBox(Interface):
- """I represent a box in the waterfall display."""
- def getBox(self, request):
- """Return a Box instance, which wraps an Event and can produce a <td>
- cell.
- """
-
-class IHTMLLog(Interface):
- pass
-
-css_classes = {SUCCESS: "success",
- WARNINGS: "warnings",
- FAILURE: "failure",
- SKIPPED: "skipped",
- EXCEPTION: "exception",
- RETRY: "retry",
- None: "",
- }
-
-
-def getAndCheckProperties(req):
- """
- Fetch custom build properties from the HTTP request of a "Force build" or
- "Resubmit build" HTML form.
- Check the names for valid strings, and return None if a problem is found.
- Return a new Properties object containing each property found in req.
- """
- master = req.site.buildbot_service.master
- pname_validate = master.config.validation['property_name']
- pval_validate = master.config.validation['property_value']
- properties = Properties()
- i = 1
- while True:
- pname = req.args.get("property%dname" % i, [""])[0]
- pvalue = req.args.get("property%dvalue" % i, [""])[0]
- if not pname:
- break
- if not pname_validate.match(pname) \
- or not pval_validate.match(pvalue):
- log.msg("bad property name='%s', value='%s'" % (pname, pvalue))
- return None
- properties.setProperty(pname, pvalue, "Force Build Form")
- i = i + 1
-
- return properties
-
-def build_get_class(b):
- """
- Return the class to use for a finished build or buildstep,
- based on the result.
- """
- # FIXME: this getResults duplicity might need to be fixed
- result = b.getResults()
- if isinstance(b, build.BuildStatus):
- result = b.getResults()
- elif isinstance(b, buildstep.BuildStepStatus):
- result = b.getResults()[0]
- # after forcing a build, b.getResults() returns ((None, []), []), ugh
- if isinstance(result, tuple):
- result = result[0]
- else:
- raise TypeError, "%r is not a BuildStatus or BuildStepStatus" % b
-
- if result == None:
- # FIXME: this happens when a buildstep is running ?
- return "running"
- return builder.Results[result]
-
-def path_to_root(request):
- # /waterfall : ['waterfall'] -> './'
- # /somewhere/lower : ['somewhere', 'lower'] -> '../'
- # /somewhere/indexy/ : ['somewhere', 'indexy', ''] -> '../../'
- # / : [] -> './'
- if request.prepath:
- segs = len(request.prepath) - 1
- else:
- segs = 0
- root = "../" * segs if segs else './'
- return root
-
-def path_to_authfail(request):
- return path_to_root(request) + "authfail"
-
-def path_to_authzfail(request):
- return path_to_root(request) + "authzfail"
-
-def path_to_builder(request, builderstatus):
- return (path_to_root(request) +
- "builders/" +
- urllib.quote(builderstatus.getName(), safe=''))
-
-def path_to_build(request, buildstatus):
- return (path_to_builder(request, buildstatus.getBuilder()) +
- "/builds/%d" % buildstatus.getNumber())
-
-def path_to_step(request, stepstatus):
- return (path_to_build(request, stepstatus.getBuild()) +
- "/steps/%s" % urllib.quote(stepstatus.getName(), safe=''))
-
-def path_to_slave(request, slave):
- return (path_to_root(request) +
- "buildslaves/" +
- urllib.quote(slave.getName(), safe=''))
-
-def path_to_change(request, change):
- return (path_to_root(request) +
- "changes/%s" % change.number)
-
-class Box:
- # a Box wraps an Event. The Box has HTML <td> parameters that Events
- # lack, and it has a base URL to which each File's name is relative.
- # Events don't know about HTML.
- spacer = False
- def __init__(self, text=[], class_=None, urlbase=None,
- **parms):
- self.text = text
- self.class_ = class_
- self.urlbase = urlbase
- self.show_idle = 0
- if parms.has_key('show_idle'):
- del parms['show_idle']
- self.show_idle = 1
-
- self.parms = parms
- # parms is a dict of HTML parameters for the <td> element that will
- # represent this Event in the waterfall display.
-
- def td(self, **props):
- props.update(self.parms)
- text = self.text
- if not text and self.show_idle:
- text = ["[idle]"]
- props['class'] = self.class_
- props['text'] = text;
- return props
-
-
-class AccessorMixin(object):
- def getStatus(self, request):
- return request.site.buildbot_service.getStatus()
-
- def getPageTitle(self, request):
- return self.pageTitle
-
- def getAuthz(self, request):
- return request.site.buildbot_service.authz
-
- def getBuildmaster(self, request):
- return request.site.buildbot_service.master
-
-
-class ContextMixin(AccessorMixin):
- def getContext(self, request):
- status = self.getStatus(request)
- rootpath = path_to_root(request)
- locale_enc = locale.getdefaultlocale()[1]
- if locale_enc is not None:
- locale_tz = unicode(time.tzname[time.localtime()[-1]], locale_enc)
- else:
- locale_tz = unicode(time.tzname[time.localtime()[-1]])
- return dict(title_url = status.getTitleURL(),
- title = status.getTitle(),
- stylesheet = rootpath + 'default.css',
- path_to_root = rootpath,
- version = version,
- time = time.strftime("%a %d %b %Y %H:%M:%S",
- time.localtime(util.now())),
- tz = locale_tz,
- metatags = [],
- pageTitle = self.getPageTitle(request),
- welcomeurl = rootpath,
- authz = self.getAuthz(request),
- request = request,
- alert_msg = request.args.get("alert_msg", [""])[0],
- )
-
-
-class ActionResource(resource.Resource, AccessorMixin):
- """A resource that performs some action, then redirects to a new URL."""
-
- isLeaf = 1
-
- def getChild(self, name, request):
- return self
-
- def performAction(self, request):
- """
- Perform the action, and return the URL to redirect to
-
- @param request: the web request
- @returns: URL via Deferred
- can also return (URL, alert_msg) to display simple
- feedback to user in case of failure
- """
-
- def render(self, request):
- d = defer.maybeDeferred(lambda : self.performAction(request))
- def redirect(url):
- if isinstance(url, tuple):
- url, alert_msg = url
- if alert_msg:
- url += "?alert_msg="+urllib.quote(alert_msg, safe='')
- request.redirect(url)
- request.write("see <a href='%s'>%s</a>" % (url,url))
- try:
- request.finish()
- except RuntimeError:
- # this occurs when the client has already disconnected; ignore
- # it (see #2027)
- log.msg("http client disconnected before results were sent")
- d.addCallback(redirect)
-
- def fail(f):
- request.processingFailed(f)
- return None # processingFailed will log this for us
- d.addErrback(fail)
- return server.NOT_DONE_YET
-
-class HtmlResource(resource.Resource, ContextMixin):
- # this is a cheap sort of template thingy
- contentType = "text/html; charset=utf-8"
- pageTitle = "Buildbot"
- addSlash = False # adapted from Nevow
-
- def getChild(self, path, request):
- if self.addSlash and path == "" and len(request.postpath) == 0:
- return self
- return resource.Resource.getChild(self, path, request)
-
-
- def content(self, req, context):
- """
- Generate content using the standard layout and the result of the C{body}
- method.
-
- This is suitable for the case where a resource just wants to generate
- the body of a page. It depends on another method, C{body}, being
- defined to accept the request object and return a C{str}. C{render}
- will call this method and to generate the response body.
- """
- body = self.body(req)
- context['content'] = body
- template = req.site.buildbot_service.templates.get_template(
- "empty.html")
- return template.render(**context)
-
-
- def render(self, request):
- # tell the WebStatus about the HTTPChannel that got opened, so they
- # can close it if we get reconfigured and the WebStatus goes away.
- # They keep a weakref to this, since chances are good that it will be
- # closed by the browser or by us before we get reconfigured. See
- # ticket #102 for details.
- if hasattr(request, "channel"):
- # web.distrib.Request has no .channel
- request.site.buildbot_service.registerChannel(request.channel)
-
- # Our pages no longer require that their URL end in a slash. Instead,
- # they all use request.childLink() or some equivalent which takes the
- # last path component into account. This clause is left here for
- # historical and educational purposes.
- if False and self.addSlash and request.prepath[-1] != '':
- # this is intended to behave like request.URLPath().child('')
- # but we need a relative URL, since we might be living behind a
- # reverse proxy
- #
- # note that the Location: header (as used in redirects) are
- # required to have absolute URIs, and my attempt to handle
- # reverse-proxies gracefully violates rfc2616. This frequently
- # works, but single-component paths sometimes break. The best
- # strategy is to avoid these redirects whenever possible by using
- # HREFs with trailing slashes, and only use the redirects for
- # manually entered URLs.
- url = request.prePathURL()
- scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
- new_url = request.prepath[-1] + "/"
- if query:
- new_url += "?" + query
- request.redirect(new_url)
- return ''
-
- ctx = self.getContext(request)
-
- d = defer.maybeDeferred(lambda : self.content(request, ctx))
- def handle(data):
- request.setHeader("X-Clacks-Overhead", 'GNU N%C3%B3ir%C3%ADn Plunkett')
- if isinstance(data, unicode):
- data = data.encode("utf-8")
- request.setHeader("content-type", self.contentType)
- if request.method == "HEAD":
- request.setHeader("content-length", len(data))
- return ''
- return data
- d.addCallback(handle)
- def ok(data):
- request.write(data)
- try:
- request.finish()
- except RuntimeError:
- # this occurs when the client has already disconnected; ignore
- # it (see #2027)
- log.msg("http client disconnected before results were sent")
- def fail(f):
- request.processingFailed(f)
- return None # processingFailed will log this for us
- d.addCallbacks(ok, fail)
- return server.NOT_DONE_YET
-
-class StaticHTML(HtmlResource):
- def __init__(self, body, pageTitle):
- HtmlResource.__init__(self)
- self.bodyHTML = body
- self.pageTitle = pageTitle
- def content(self, request, cxt):
- cxt['content'] = self.bodyHTML
- cxt['pageTitle'] = self.pageTitle
- template = request.site.buildbot_service.templates.get_template("empty.html")
- return template.render(**cxt)
-
-class DirectoryLister(static.DirectoryLister, ContextMixin):
- """This variant of the static.DirectoryLister uses a template
- for rendering."""
-
- pageTitle = 'BuildBot'
-
- def render(self, request):
- cxt = self.getContext(request)
-
- if self.dirs is None:
- directory = os.listdir(self.path)
- directory.sort()
- else:
- directory = self.dirs
-
- dirs, files = self._getFilesAndDirectories(directory)
-
- cxt['path'] = cgi.escape(urllib.unquote(request.uri))
- cxt['directories'] = dirs
- cxt['files'] = files
- template = request.site.buildbot_service.templates.get_template("directory.html")
- data = template.render(**cxt)
- if isinstance(data, unicode):
- data = data.encode("utf-8")
- return data
-
-class StaticFile(static.File):
- """This class adds support for templated directory
- views."""
-
- def directoryListing(self):
- return DirectoryLister(self.path,
- self.listNames(),
- self.contentTypes,
- self.contentEncodings,
- self.defaultType)
-
-
-MINUTE = 60
-HOUR = 60*MINUTE
-DAY = 24*HOUR
-WEEK = 7*DAY
-MONTH = 30*DAY
-
-def plural(word, words, num):
- if int(num) == 1:
- return "%d %s" % (num, word)
- else:
- return "%d %s" % (num, words)
-
-def abbreviate_age(age):
- if age <= 90:
- return "%s ago" % plural("second", "seconds", age)
- if age < 90*MINUTE:
- return "about %s ago" % plural("minute", "minutes", age / MINUTE)
- if age < DAY:
- return "about %s ago" % plural("hour", "hours", age / HOUR)
- if age < 2*WEEK:
- return "about %s ago" % plural("day", "days", age / DAY)
- if age < 2*MONTH:
- return "about %s ago" % plural("week", "weeks", age / WEEK)
- return "a long time ago"
-
-
-class BuildLineMixin:
- LINE_TIME_FORMAT = "%b %d %H:%M"
-
- def get_line_values(self, req, build, include_builder=True):
- '''
- Collect the data needed for each line display
- '''
- builder_name = build.getBuilder().getName()
- results = build.getResults()
- text = build.getText()
- all_got_revision = build.getAllGotRevisions()
- css_class = css_classes.get(results, "")
- ss_list = build.getSourceStamps()
- if ss_list:
- repo = ss_list[0].repository
- if all_got_revision:
- if len(ss_list) == 1:
- rev = all_got_revision.get(ss_list[0].codebase, "??")
- else:
- rev = "multiple rev."
- else:
- rev = "??"
- else:
- repo = 'unknown, no information in build'
- rev = 'unknown'
-
- if type(text) == list:
- text = " ".join(text)
-
- values = {'class': css_class,
- 'builder_name': builder_name,
- 'buildnum': build.getNumber(),
- 'results': css_class,
- 'text': " ".join(build.getText()),
- 'buildurl': path_to_build(req, build),
- 'builderurl': path_to_builder(req, build.getBuilder()),
- 'rev': rev,
- 'rev_repo' : repo,
- 'time': time.strftime(self.LINE_TIME_FORMAT,
- time.localtime(build.getTimes()[0])),
- 'text': text,
- 'include_builder': include_builder
- }
- return values
-
-def map_branches(branches):
- # when the query args say "trunk", present that to things like
- # IBuilderStatus.generateFinishedBuilds as None, since that's the
- # convention in use. But also include 'trunk', because some VC systems
- # refer to it that way. In the long run we should clean this up better,
- # maybe with Branch objects or something.
- if "trunk" in branches:
- return branches + [None]
- return branches
-
-
-# jinja utilities
-
-def createJinjaEnv(revlink=None, changecommentlink=None,
- repositories=None, projects=None, jinja_loaders=None):
- ''' Create a jinja environment changecommentlink is used to
- render HTML in the WebStatus and for mail changes
-
- @type changecommentlink: C{None}, tuple (2 or 3 strings), dict (string -> 2- or 3-tuple) or callable
- @param changecommentlink: see changelinkfilter()
-
- @type revlink: C{None}, format-string, dict (repository -> format string) or callable
- @param revlink: see revlinkfilter()
-
- @type repositories: C{None} or dict (string -> url)
- @param repositories: an (optinal) mapping from repository identifiers
- (as given by Change sources) to URLs. Is used to create a link
- on every place where a repository is listed in the WebStatus.
-
- @type projects: C{None} or dict (string -> url)
- @param projects: similar to repositories, but for projects.
- '''
-
- # See http://buildbot.net/trac/ticket/658
- assert not hasattr(sys, "frozen"), 'Frozen config not supported with jinja (yet)'
-
- all_loaders = [jinja2.FileSystemLoader(os.path.join(os.getcwd(), 'templates'))]
- if jinja_loaders:
- all_loaders.extend(jinja_loaders)
- all_loaders.append(jinja2.PackageLoader('buildbot.status.web', 'templates'))
- loader = jinja2.ChoiceLoader(all_loaders)
-
- env = jinja2.Environment(loader=loader,
- extensions=['jinja2.ext.i18n'],
- trim_blocks=True,
- undefined=AlmostStrictUndefined)
-
- env.install_null_translations() # needed until we have a proper i18n backend
-
- env.tests['mapping'] = lambda obj : isinstance(obj, dict)
-
- env.filters.update(dict(
- urlencode = urllib.quote,
- email = emailfilter,
- user = userfilter,
- shortrev = shortrevfilter(revlink, env),
- revlink = revlinkfilter(revlink, env),
- changecomment = changelinkfilter(changecommentlink),
- repolink = dictlinkfilter(repositories),
- projectlink = dictlinkfilter(projects)
- ))
-
- return env
-
-def emailfilter(value):
- ''' Escape & obfuscate e-mail addresses
-
- replacing @ with <span style="display:none> reportedly works well against web-spiders
- and the next level is to use rot-13 (or something) and decode in javascript '''
-
- user = jinja2.escape(value)
- obfuscator = jinja2.Markup('<span style="display:none">ohnoyoudont</span>@')
- output = user.replace('@', obfuscator)
- return output
-
-
-def userfilter(value):
- ''' Hide e-mail address from user name when viewing changes
-
- We still include the (obfuscated) e-mail so that we can show
- it on mouse-over or similar etc
- '''
- r = re.compile('(.*) +<(.*)>')
- m = r.search(value)
- if m:
- user = jinja2.escape(m.group(1))
- email = emailfilter(m.group(2))
- return jinja2.Markup('<div class="user">%s<div class="email">%s</div></div>' % (user, email))
- else:
- return emailfilter(value) # filter for emails here for safety
-
-def _revlinkcfg(replace, templates):
- '''Helper function that returns suitable macros and functions
- for building revision links depending on replacement mechanism
-'''
-
- assert not replace or callable(replace) or isinstance(replace, dict) or \
- isinstance(replace, str) or isinstance(replace, unicode)
-
- if not replace:
- return lambda rev, repo: None
- else:
- if callable(replace):
- return lambda rev, repo: replace(rev, repo)
- elif isinstance(replace, dict): # TODO: test for [] instead
- def filter(rev, repo):
- url = replace.get(repo)
- if url:
- return url % urllib.quote(rev)
- else:
- return None
-
- return filter
- else:
- return lambda rev, repo: replace % urllib.quote(rev)
-
- assert False, '_replace has a bad type, but we should never get here'
-
-
-def _revlinkmacros(replace, templates):
- '''return macros for use with revision links, depending
- on whether revlinks are configured or not'''
-
- macros = templates.get_template("revmacros.html").module
-
- if not replace:
- id = macros.id
- short = macros.shorten
- else:
- id = macros.id_replace
- short = macros.shorten_replace
-
- return (id, short)
-
-
-def shortrevfilter(replace, templates):
- ''' Returns a function which shortens the revisison string
- to 12-chars (chosen as this is the Mercurial short-id length)
- and add link if replacement string is set.
-
- (The full id is still visible in HTML, for mouse-over events etc.)
-
- @param replace: see revlinkfilter()
- @param templates: a jinja2 environment
- '''
-
- url_f = _revlinkcfg(replace, templates)
-
- def filter(rev, repo):
- if not rev:
- return u''
-
- id_html, short_html = _revlinkmacros(replace, templates)
- rev = unicode(rev)
- url = url_f(rev, repo)
- rev = jinja2.escape(rev)
- shortrev = rev[:12] # TODO: customize this depending on vc type
-
- if shortrev == rev:
- if url:
- return id_html(rev=rev, url=url)
- else:
- return rev
- else:
- if url:
- return short_html(short=shortrev, rev=rev, url=url)
- else:
- return shortrev + '...'
-
- return filter
-
-
-def revlinkfilter(replace, templates):
- ''' Returns a function which adds an url link to a
- revision identifiers.
-
- Takes same params as shortrevfilter()
-
- @param replace: either a python format string with an %s,
- or a dict mapping repositories to format strings,
- or a callable taking (revision, repository) arguments
- and return an URL (or None, if no URL is available),
- or None, in which case revisions do not get decorated
- with links
-
- @param templates: a jinja2 environment
- '''
-
- url_f = _revlinkcfg(replace, templates)
-
- def filter(rev, repo):
- if not rev:
- return u''
-
- rev = unicode(rev)
- url = url_f(rev, repo)
- if url:
- id_html, _ = _revlinkmacros(replace, templates)
- return id_html(rev=rev, url=url)
- else:
- return jinja2.escape(rev)
-
- return filter
-
-
-def changelinkfilter(changelink):
- ''' Returns function that does regex search/replace in
- comments to add links to bug ids and similar.
-
- @param changelink:
- Either C{None}
- or: a tuple (2 or 3 elements)
- 1. a regex to match what we look for
- 2. an url with regex refs (\g<0>, \1, \2, etc) that becomes the 'href' attribute
- 3. (optional) an title string with regex ref regex
- or: a dict mapping projects to above tuples
- (no links will be added if the project isn't found)
- or: a callable taking (changehtml, project) args
- (where the changetext is HTML escaped in the
- form of a jinja2.Markup instance) and
- returning another jinja2.Markup instance with
- the same change text plus any HTML tags added to it.
- '''
-
- assert not changelink or isinstance(changelink, dict) or \
- isinstance(changelink, tuple) or callable(changelink)
-
- def replace_from_tuple(t):
- search, url_replace = t[:2]
- if len(t) == 3:
- title_replace = t[2]
- else:
- title_replace = ''
-
- search_re = re.compile(search)
-
- def replacement_unmatched(text):
- return jinja2.escape(text)
- def replacement_matched(mo):
- # expand things *after* application of the regular expressions
- url = jinja2.escape(mo.expand(url_replace))
- title = jinja2.escape(mo.expand(title_replace))
- body = jinja2.escape(mo.group())
- if title:
- return '<a href="%s" title="%s">%s</a>' % (url, title, body)
- else:
- return '<a href="%s">%s</a>' % (url, body)
-
- def filter(text, project):
- # now, we need to split the string into matched and unmatched portions,
- # quoting the unmatched portions directly and quoting the components of
- # the 'a' element for the matched portions. We can't use re.split here,
- # because the user-supplied patterns may have multiple groups.
- html = []
- last_idx = 0
- for mo in search_re.finditer(text):
- html.append(replacement_unmatched(text[last_idx:mo.start()]))
- html.append(replacement_matched(mo))
- last_idx = mo.end()
- html.append(replacement_unmatched(text[last_idx:]))
- return jinja2.Markup(''.join(html))
-
- return filter
-
- if not changelink:
- return lambda text, project: jinja2.escape(text)
-
- elif isinstance(changelink, dict):
- def dict_filter(text, project):
- # TODO: Optimize and cache return value from replace_from_tuple so
- # we only compile regex once per project, not per view
-
- t = changelink.get(project)
- if t:
- return replace_from_tuple(t)(text, project)
- else:
- return cgi.escape(text)
-
- return dict_filter
-
- elif isinstance(changelink, tuple):
- return replace_from_tuple(changelink)
-
- elif callable(changelink):
- def callable_filter(text, project):
- text = jinja2.escape(text)
- return changelink(text, project)
-
- return callable_filter
-
- assert False, 'changelink has unsupported type, but that is checked before'
-
-
-def dictlinkfilter(links):
- '''A filter that encloses the given value in a link tag
- given that the value exists in the dictionary'''
-
- assert not links or callable(links) or isinstance(links, dict)
-
- if not links:
- return jinja2.escape
-
- def filter(key):
- if callable(links):
- url = links(key)
- else:
- url = links.get(key)
-
- safe_key = jinja2.escape(key)
-
- if url:
- return jinja2.Markup(r'<a href="%s">%s</a>' % (url, safe_key))
- else:
- return safe_key
-
- return filter
-
-class AlmostStrictUndefined(jinja2.StrictUndefined):
- ''' An undefined that allows boolean testing but
- fails properly on every other use.
-
- Much better than the default Undefined, but not
- fully as strict as StrictUndefined '''
- def __nonzero__(self):
- return False
-
-_charsetRe = re.compile('charset=([^;]*)', re.I)
-def getRequestCharset(req):
- """Get the charset for an x-www-form-urlencoded request"""
- # per http://stackoverflow.com/questions/708915/detecting-the-character-encoding-of-an-http-post-request
- hdr = req.getHeader('Content-Type')
- if hdr:
- mo = _charsetRe.search(hdr)
- if mo:
- return mo.group(1).strip()
- return 'utf-8' # reasonable guess, works for ascii
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py
deleted file mode 100644
index 9fe5e7fc..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py
+++ /dev/null
@@ -1,607 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import os, weakref
-
-from zope.interface import implements
-from twisted.python import log
-from twisted.application import strports, service
-from twisted.internet import defer
-from twisted.web import server, distrib, static
-from twisted.spread import pb
-from twisted.web.util import Redirect
-from buildbot import config
-from buildbot.interfaces import IStatusReceiver
-from buildbot.status.web.base import StaticFile, createJinjaEnv
-from buildbot.status.web.feeds import Rss20StatusResource, \
- Atom10StatusResource
-from buildbot.status.web.waterfall import WaterfallStatusResource
-from buildbot.status.web.console import ConsoleStatusResource
-from buildbot.status.web.olpb import OneLinePerBuild
-from buildbot.status.web.grid import GridStatusResource
-from buildbot.status.web.grid import TransposedGridStatusResource
-from buildbot.status.web.changes import ChangesResource
-from buildbot.status.web.builder import BuildersResource
-from buildbot.status.web.buildstatus import BuildStatusStatusResource
-from buildbot.status.web.slaves import BuildSlavesResource
-from buildbot.status.web.status_json import JsonStatusResource
-from buildbot.status.web.about import AboutBuildbot
-from buildbot.status.web.authz import Authz
-from buildbot.status.web.auth import AuthFailResource,AuthzFailResource, LoginResource, LogoutResource
-from buildbot.status.web.root import RootPage
-from buildbot.status.web.users import UsersResource
-from buildbot.status.web.change_hook import ChangeHookResource
-from twisted.cred.portal import IRealm, Portal
-from twisted.cred import strcred
-from twisted.cred.checkers import ICredentialsChecker
-from twisted.cred.credentials import IUsernamePassword
-from twisted.web import resource, guard
-
-# this class contains the WebStatus class. Basic utilities are in base.py,
-# and specific pages are each in their own module.
-
-class WebStatus(service.MultiService):
- implements(IStatusReceiver)
- # TODO: IStatusReceiver is really about things which subscribe to hear
- # about buildbot events. We need a different interface (perhaps a parent
- # of IStatusReceiver) for status targets that don't subscribe, like the
- # WebStatus class. buildbot.master.BuildMaster.loadConfig:737 asserts
- # that everything in c['status'] provides IStatusReceiver, but really it
- # should check that they provide IStatusTarget instead.
-
- """
- The webserver provided by this class has the following resources:
-
- /waterfall : the big time-oriented 'waterfall' display, with links
- to individual changes, builders, builds, steps, and logs.
- A number of query-arguments can be added to influence
- the display.
- /rss : a rss feed summarizing all failed builds. The same
- query-arguments used by 'waterfall' can be added to
- influence the feed output.
- /atom : an atom feed summarizing all failed builds. The same
- query-arguments used by 'waterfall' can be added to
- influence the feed output.
- /grid : another summary display that shows a grid of builds, with
- sourcestamps on the x axis, and builders on the y. Query
- arguments similar to those for the waterfall can be added.
- /tgrid : similar to the grid display, but the commits are down the
- left side, and the build hosts are across the top.
- /builders/BUILDERNAME: a page summarizing the builder. This includes
- references to the Schedulers that feed it,
- any builds currently in the queue, which
- buildslaves are designated or attached, and a
- summary of the build process it uses.
- /builders/BUILDERNAME/builds/NUM: a page describing a single Build
- /builders/BUILDERNAME/builds/NUM/steps/STEPNAME: describes a single step
- /builders/BUILDERNAME/builds/NUM/steps/STEPNAME/logs/LOGNAME: a StatusLog
- /builders/_all/{force,stop}: force a build/stop building on all builders.
- /buildstatus?builder=...&number=...: an embedded iframe for the console
- /changes : summarize all ChangeSources
- /changes/CHANGENUM: a page describing a single Change
- /buildslaves : list all BuildSlaves
- /buildslaves/SLAVENAME : describe a single BuildSlave
- /one_line_per_build : summarize the last few builds, one line each
- /one_line_per_build/BUILDERNAME : same, but only for a single builder
- /about : describe this buildmaster (Buildbot and support library versions)
- /change_hook[/DIALECT] : accepts changes from external sources, optionally
- choosing the dialect that will be permitted
- (i.e. github format, etc..)
-
- and more! see the manual.
-
-
- All URLs for pages which are not defined here are used to look
- for files in PUBLIC_HTML, which defaults to BASEDIR/public_html.
- This means that /robots.txt or /favicon.ico can be placed in
- that directory
-
- This webserver uses the jinja2 template system to generate the web pages
- (see http://jinja.pocoo.org/2/) and by default loads pages from the
- buildbot.status.web.templates package. Any file here can be overridden by placing
- a corresponding file in the master's 'templates' directory.
-
- The main customization points are layout.html which loads style sheet
- (css) and provides header and footer content, and root.html, which
- generates the root page.
-
- All of the resources provided by this service use relative URLs to reach
- each other. The only absolute links are the c['titleURL'] links at the
- top and bottom of the page, and the buildbot home-page link at the
- bottom.
-
- Buildbot uses some generic classes to identify the type of object, and
- some more specific classes for the various kinds of those types. It does
- this by specifying both in the class attributes where applicable,
- separated by a space. It is important that in your CSS you declare the
- more generic class styles above the more specific ones. For example,
- first define a style for .Event, and below that for .SUCCESS
-
- The following CSS class names are used:
- - Activity, Event, BuildStep, LastBuild: general classes
- - waiting, interlocked, building, offline, idle: Activity states
- - start, running, success, failure, warnings, skipped, exception:
- LastBuild and BuildStep states
- - Change: box with change
- - Builder: box for builder name (at top)
- - Project
- - Time
-
- """
-
- # we are not a ComparableMixin, and therefore the webserver will be
- # rebuilt every time we reconfig. This is because WebStatus.putChild()
- # makes it too difficult to tell whether two instances are the same or
- # not (we'd have to do a recursive traversal of all children to discover
- # all the changes).
-
- def __init__(self, http_port=None, distrib_port=None, allowForce=None,
- public_html="public_html", site=None, numbuilds=20,
- num_events=200, num_events_max=None, auth=None,
- order_console_by_time=False, changecommentlink=None,
- revlink=None, projects=None, repositories=None,
- authz=None, logRotateLength=None, maxRotatedFiles=None,
- change_hook_dialects = {}, provide_feeds=None, jinja_loaders=None,
- change_hook_auth=None):
- """Run a web server that provides Buildbot status.
-
- @type http_port: int or L{twisted.application.strports} string
- @param http_port: a strports specification describing which port the
- buildbot should use for its web server, with the
- Waterfall display as the root page. For backwards
- compatibility this can also be an int. Use
- 'tcp:8000' to listen on that port, or
- 'tcp:12345:interface=127.0.0.1' if you only want
- local processes to connect to it (perhaps because
- you are using an HTTP reverse proxy to make the
- buildbot available to the outside world, and do not
- want to make the raw port visible).
-
- @type distrib_port: int or L{twisted.application.strports} string
- @param distrib_port: Use this if you want to publish the Waterfall
- page using web.distrib instead. The most common
- case is to provide a string that is an absolute
- pathname to the unix socket on which the
- publisher should listen
- (C{os.path.expanduser(~/.twistd-web-pb)} will
- match the default settings of a standard
- twisted.web 'personal web server'). Another
- possibility is to pass an integer, which means
- the publisher should listen on a TCP socket,
- allowing the web server to be on a different
- machine entirely. Both forms are provided for
- backwards compatibility; the preferred form is a
- strports specification like
- 'unix:/home/buildbot/.twistd-web-pb'. Providing
- a non-absolute pathname will probably confuse
- the strports parser.
-
- @param allowForce: deprecated; use authz instead
- @param auth: deprecated; use with authz
-
- @param authz: a buildbot.status.web.authz.Authz instance giving the authorization
- parameters for this view
-
- @param public_html: the path to the public_html directory for this display,
- either absolute or relative to the basedir. The default
- is 'public_html', which selects BASEDIR/public_html.
-
- @type site: None or L{twisted.web.server.Site}
- @param site: Use this if you want to define your own object instead of
- using the default.`
-
- @type numbuilds: int
- @param numbuilds: Default number of entries in lists at the /one_line_per_build
- and /builders/FOO URLs. This default can be overriden both programatically ---
- by passing the equally named argument to constructors of OneLinePerBuildOneBuilder
- and OneLinePerBuild --- and via the UI, by tacking ?numbuilds=xy onto the URL.
-
- @type num_events: int
- @param num_events: Default number of events to show in the waterfall.
-
- @type num_events_max: int
- @param num_events_max: The maximum number of events that are allowed to be
- shown in the waterfall. The default value of C{None} will disable this
- check
-
- @type auth: a L{status.web.auth.IAuth} or C{None}
- @param auth: an object that performs authentication to restrict access
- to the C{allowForce} features. Ignored if C{allowForce}
- is not C{True}. If C{auth} is C{None}, people can force or
- stop builds without auth.
-
- @type order_console_by_time: bool
- @param order_console_by_time: Whether to order changes (commits) in the console
- view according to the time they were created (for VCS like Git) or
- according to their integer revision numbers (for VCS like SVN).
-
- @type changecommentlink: callable, dict, tuple (2 or 3 strings) or C{None}
- @param changecommentlink: adds links to ticket/bug ids in change comments,
- see buildbot.status.web.base.changecommentlink for details
-
- @type revlink: callable, dict, string or C{None}
- @param revlink: decorations revision ids with links to a web-view,
- see buildbot.status.web.base.revlink for details
-
- @type projects: callable, dict or c{None}
- @param projects: maps project identifiers to URLs, so that any project listed
- is automatically decorated with a link to it's front page.
- see buildbot.status.web.base.dictlink for details
-
- @type repositories: callable, dict or c{None}
- @param repositories: maps repository identifiers to URLs, so that any project listed
- is automatically decorated with a link to it's web view.
- see buildbot.status.web.base.dictlink for details
-
- @type logRotateLength: None or int
- @param logRotateLength: file size at which the http.log is rotated/reset.
- If not set, the value set in the buildbot.tac will be used,
- falling back to the BuildMaster's default value (1 Mb).
-
- @type maxRotatedFiles: None or int
- @param maxRotatedFiles: number of old http.log files to keep during log rotation.
- If not set, the value set in the buildbot.tac will be used,
- falling back to the BuildMaster's default value (10 files).
-
- @type change_hook_dialects: None or dict
- @param change_hook_dialects: If empty, disables change_hook support, otherwise
- whitelists valid dialects. In the format of
- {"dialect1": "Option1", "dialect2", None}
- Where the values are options that will be passed
- to the dialect
-
- To enable the DEFAULT handler, use a key of DEFAULT
-
-
-
-
- @type provide_feeds: None or list
- @param provide_feeds: If empty, provides atom, json, and rss feeds.
- Otherwise, a dictionary of strings of
- the type of feeds provided. Current
- possibilities are "atom", "json", and "rss"
-
- @type jinja_loaders: None or list
- @param jinja_loaders: If not empty, a list of additional Jinja2 loader
- objects to search for templates.
- """
-
- service.MultiService.__init__(self)
- if type(http_port) is int:
- http_port = "tcp:%d" % http_port
- self.http_port = http_port
- if distrib_port is not None:
- if type(distrib_port) is int:
- distrib_port = "tcp:%d" % distrib_port
- if distrib_port[0] in "/~.": # pathnames
- distrib_port = "unix:%s" % distrib_port
- self.distrib_port = distrib_port
- self.num_events = num_events
- if num_events_max:
- if num_events_max < num_events:
- config.error(
- "num_events_max must be greater than num_events")
- self.num_events_max = num_events_max
- self.public_html = public_html
-
- # make up an authz if allowForce was given
- if authz:
- if allowForce is not None:
- config.error(
- "cannot use both allowForce and authz parameters")
- if auth:
- config.error(
- "cannot use both auth and authz parameters (pass " +
- "auth as an Authz parameter)")
- else:
- # invent an authz
- if allowForce and auth:
- authz = Authz(auth=auth, default_action="auth")
- elif allowForce:
- authz = Authz(default_action=True)
- else:
- if auth:
- log.msg("Warning: Ignoring authentication. Search for 'authorization'"
- " in the manual")
- authz = Authz() # no authorization for anything
-
- self.authz = authz
-
- # check for correctness of HTTP auth parameters
- if change_hook_auth is not None:
- self.change_hook_auth = []
- for checker in change_hook_auth:
- if isinstance(checker, str):
- try:
- checker = strcred.makeChecker(checker)
- except Exception, error:
- config.error("Invalid change_hook checker description: %s" % (error,))
- continue
- elif not ICredentialsChecker.providedBy(checker):
- config.error("change_hook checker doesn't provide ICredentialChecker: %r" % (checker,))
- continue
-
- if IUsernamePassword not in checker.credentialInterfaces:
- config.error("change_hook checker doesn't support IUsernamePassword: %r" % (checker,))
- continue
-
- self.change_hook_auth.append(checker)
- else:
- self.change_hook_auth = None
-
- self.orderConsoleByTime = order_console_by_time
-
- # If we were given a site object, go ahead and use it. (if not, we add one later)
- self.site = site
-
- # keep track of our child services
- self.http_svc = None
- self.distrib_svc = None
-
- # store the log settings until we create the site object
- self.logRotateLength = logRotateLength
- self.maxRotatedFiles = maxRotatedFiles
-
- # create the web site page structure
- self.childrenToBeAdded = {}
- self.setupUsualPages(numbuilds=numbuilds, num_events=num_events,
- num_events_max=num_events_max)
-
- self.revlink = revlink
- self.changecommentlink = changecommentlink
- self.repositories = repositories
- self.projects = projects
-
- # keep track of cached connections so we can break them when we shut
- # down. See ticket #102 for more details.
- self.channels = weakref.WeakKeyDictionary()
-
- # do we want to allow change_hook
- self.change_hook_dialects = {}
- if change_hook_dialects:
- self.change_hook_dialects = change_hook_dialects
- resource_obj = ChangeHookResource(dialects=self.change_hook_dialects)
- if self.change_hook_auth is not None:
- resource_obj = self.setupProtectedResource(
- resource_obj, self.change_hook_auth)
- self.putChild("change_hook", resource_obj)
-
- # Set default feeds
- if provide_feeds is None:
- self.provide_feeds = ["atom", "json", "rss"]
- else:
- self.provide_feeds = provide_feeds
-
- self.jinja_loaders = jinja_loaders
-
- def setupProtectedResource(self, resource_obj, checkers):
- class SimpleRealm(object):
- """
- A realm which gives out L{ChangeHookResource} instances for authenticated
- users.
- """
- implements(IRealm)
-
- def requestAvatar(self, avatarId, mind, *interfaces):
- if resource.IResource in interfaces:
- return (resource.IResource, resource_obj, lambda: None)
- raise NotImplementedError()
-
- portal = Portal(SimpleRealm(), checkers)
- credentialFactory = guard.BasicCredentialFactory('Protected area')
- wrapper = guard.HTTPAuthSessionWrapper(portal, [credentialFactory])
- return wrapper
-
- def setupUsualPages(self, numbuilds, num_events, num_events_max):
- #self.putChild("", IndexOrWaterfallRedirection())
- self.putChild("waterfall", WaterfallStatusResource(num_events=num_events,
- num_events_max=num_events_max))
- self.putChild("grid", GridStatusResource())
- self.putChild("console", ConsoleStatusResource(
- orderByTime=self.orderConsoleByTime))
- self.putChild("tgrid", TransposedGridStatusResource())
- self.putChild("builders", BuildersResource(numbuilds=numbuilds)) # has builds/steps/logs
- self.putChild("one_box_per_builder", Redirect("builders"))
- self.putChild("changes", ChangesResource())
- self.putChild("buildslaves", BuildSlavesResource())
- self.putChild("buildstatus", BuildStatusStatusResource())
- self.putChild("one_line_per_build",
- OneLinePerBuild(numbuilds=numbuilds))
- self.putChild("about", AboutBuildbot())
- self.putChild("authfail", AuthFailResource())
- self.putChild("authzfail", AuthzFailResource())
- self.putChild("users", UsersResource())
- self.putChild("login", LoginResource())
- self.putChild("logout", LogoutResource())
-
- def __repr__(self):
- if self.http_port is None:
- return "<WebStatus on path %s at %s>" % (self.distrib_port,
- hex(id(self)))
- if self.distrib_port is None:
- return "<WebStatus on port %s at %s>" % (self.http_port,
- hex(id(self)))
- return ("<WebStatus on port %s and path %s at %s>" %
- (self.http_port, self.distrib_port, hex(id(self))))
-
- def setServiceParent(self, parent):
- # this class keeps a *separate* link to the buildmaster, rather than
- # just using self.parent, so that when we are "disowned" (and thus
- # parent=None), any remaining HTTP clients of this WebStatus will still
- # be able to get reasonable results.
- self.master = parent.master
-
- # set master in IAuth instance
- if self.authz.auth:
- self.authz.auth.master = self.master
-
- def either(a,b): # a if a else b for py2.4
- if a:
- return a
- else:
- return b
-
- rotateLength = either(self.logRotateLength, self.master.log_rotation.rotateLength)
- maxRotatedFiles = either(self.maxRotatedFiles, self.master.log_rotation.maxRotatedFiles)
-
- # Set up the jinja templating engine.
- if self.revlink:
- revlink = self.revlink
- else:
- revlink = self.master.config.revlink
- self.templates = createJinjaEnv(revlink, self.changecommentlink,
- self.repositories, self.projects, self.jinja_loaders)
-
- if not self.site:
-
- class RotateLogSite(server.Site):
- def _openLogFile(self, path):
- try:
- from twisted.python.logfile import LogFile
- log.msg("Setting up http.log rotating %s files of %s bytes each" %
- (maxRotatedFiles, rotateLength))
- if hasattr(LogFile, "fromFullPath"): # not present in Twisted-2.5.0
- return LogFile.fromFullPath(path, rotateLength=rotateLength, maxRotatedFiles=maxRotatedFiles)
- else:
- log.msg("WebStatus: rotated http logs are not supported on this version of Twisted")
- except ImportError, e:
- log.msg("WebStatus: Unable to set up rotating http.log: %s" % e)
-
- # if all else fails, just call the parent method
- return server.Site._openLogFile(self, path)
-
- # this will be replaced once we've been attached to a parent (and
- # thus have a basedir and can reference BASEDIR)
- root = static.Data("placeholder", "text/plain")
- httplog = os.path.abspath(os.path.join(self.master.basedir, "http.log"))
- self.site = RotateLogSite(root, logPath=httplog)
-
- # the following items are accessed by HtmlResource when it renders
- # each page.
- self.site.buildbot_service = self
-
- if self.http_port is not None:
- self.http_svc = s = strports.service(self.http_port, self.site)
- s.setServiceParent(self)
- if self.distrib_port is not None:
- f = pb.PBServerFactory(distrib.ResourcePublisher(self.site))
- self.distrib_svc = s = strports.service(self.distrib_port, f)
- s.setServiceParent(self)
-
- self.setupSite()
-
- service.MultiService.setServiceParent(self, parent)
-
- def setupSite(self):
- # this is responsible for creating the root resource. It isn't done
- # at __init__ time because we need to reference the parent's basedir.
- htmldir = os.path.abspath(os.path.join(self.master.basedir, self.public_html))
- if os.path.isdir(htmldir):
- log.msg("WebStatus using (%s)" % htmldir)
- else:
- log.msg("WebStatus: warning: %s is missing. Do you need to run"
- " 'buildbot upgrade-master' on this buildmaster?" % htmldir)
- # all static pages will get a 404 until upgrade-master is used to
- # populate this directory. Create the directory, though, since
- # otherwise we get internal server errors instead of 404s.
- os.mkdir(htmldir)
-
- root = StaticFile(htmldir)
- root_page = RootPage()
- root.putChild("", root_page)
- root.putChild("shutdown", root_page)
- root.putChild("cancel_shutdown", root_page)
-
- for name, child_resource in self.childrenToBeAdded.iteritems():
- root.putChild(name, child_resource)
-
- status = self.getStatus()
- if "rss" in self.provide_feeds:
- root.putChild("rss", Rss20StatusResource(status))
- if "atom" in self.provide_feeds:
- root.putChild("atom", Atom10StatusResource(status))
- if "json" in self.provide_feeds:
- root.putChild("json", JsonStatusResource(status))
-
- self.site.resource = root
-
- def putChild(self, name, child_resource):
- """This behaves a lot like root.putChild() . """
- self.childrenToBeAdded[name] = child_resource
-
- def registerChannel(self, channel):
- self.channels[channel] = 1 # weakrefs
-
- @defer.inlineCallbacks
- def stopService(self):
- for channel in self.channels:
- try:
- channel.transport.loseConnection()
- except:
- log.msg("WebStatus.stopService: error while disconnecting"
- " leftover clients")
- log.err()
- yield service.MultiService.stopService(self)
-
- # having shut them down, now remove our child services so they don't
- # start up again if we're re-started
- if self.http_svc:
- yield self.http_svc.disownServiceParent()
- self.http_svc = None
- if self.distrib_svc:
- yield self.distrib_svc.disownServiceParent()
- self.distrib_svc = None
-
- def getStatus(self):
- return self.master.getStatus()
-
- def getChangeSvc(self):
- return self.master.change_svc
-
- def getPortnum(self):
- # this is for the benefit of unit tests
- s = list(self)[0]
- return s._port.getHost().port
-
- # What happened to getControl?!
- #
- # instead of passing control objects all over the place in the web
- # code, at the few places where a control instance is required we
- # find the requisite object manually, starting at the buildmaster.
- # This is in preparation for removal of the IControl hierarchy
- # entirely.
-
- def checkConfig(self, otherStatusReceivers):
- duplicate_webstatus=0
- for osr in otherStatusReceivers:
- if isinstance(osr,WebStatus):
- if osr is self:
- continue
- # compare against myself and complain if the settings conflict
- if self.http_port == osr.http_port:
- if duplicate_webstatus == 0:
- duplicate_webstatus = 2
- else:
- duplicate_webstatus += 1
-
- if duplicate_webstatus:
- config.error(
- "%d Webstatus objects have same port: %s"
- % (duplicate_webstatus, self.http_port),
- )
-
-# resources can get access to the IStatus by calling
-# request.site.buildbot_service.getStatus()
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py
deleted file mode 100644
index 1cf7f92f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from twisted.web import html
-from twisted.internet import defer, reactor
-from twisted.web.util import Redirect, DeferredResource
-
-import urllib, time
-from twisted.python import log
-from buildbot.status.web.base import HtmlResource, \
- css_classes, path_to_build, path_to_builder, path_to_slave, \
- getAndCheckProperties, ActionResource, path_to_authzfail, \
- getRequestCharset
-from buildbot.schedulers.forcesched import ForceScheduler, TextParameter
-from buildbot.status.web.step import StepsResource
-from buildbot.status.web.tests import TestsResource
-from buildbot import util, interfaces
-
-class ForceBuildActionResource(ActionResource):
-
- def __init__(self, build_status, builder):
- self.build_status = build_status
- self.builder = builder
- self.action = "forceBuild"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- url = None
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed(self.action, req, self.builder)
-
- if not res:
- url = path_to_authzfail(req)
- else:
- # get a control object
- c = interfaces.IControl(self.getBuildmaster(req))
- bc = c.getBuilder(self.builder.getName())
-
- b = self.build_status
- builder_name = self.builder.getName()
- log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber()))
- name =authz.getUsernameFull(req)
- comments = req.args.get("comments", ["<no reason specified>"])[0]
- comments.decode(getRequestCharset(req))
- reason = ("The web-page 'rebuild' button was pressed by "
- "'%s': %s\n" % (name, comments))
- msg = ""
- extraProperties = getAndCheckProperties(req)
- if not bc or not b.isFinished() or extraProperties is None:
- msg = "could not rebuild: "
- if b.isFinished():
- msg += "build still not finished "
- if bc:
- msg += "could not get builder control"
- else:
- tup = yield bc.rebuildBuild(b, reason, extraProperties)
- # rebuildBuild returns None on error (?!)
- if not tup:
- msg = "rebuilding a build failed "+ str(tup)
- # we're at
- # http://localhost:8080/builders/NAME/builds/5/rebuild?[args]
- # Where should we send them?
- #
- # Ideally it would be to the per-build page that they just started,
- # but we don't know the build number for it yet (besides, it might
- # have to wait for a current build to finish). The next-most
- # preferred place is somewhere that the user can see tangible
- # evidence of their build starting (or to see the reason that it
- # didn't start). This should be the Builder page.
-
- url = path_to_builder(req, self.builder), msg
- defer.returnValue(url)
-
-
-class StopBuildActionResource(ActionResource):
-
- def __init__(self, build_status):
- self.build_status = build_status
- self.action = "stopBuild"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed(self.action, req, self.build_status)
-
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- b = self.build_status
- log.msg("web stopBuild of build %s:%s" % \
- (b.getBuilder().getName(), b.getNumber()))
- name = authz.getUsernameFull(req)
- comments = req.args.get("comments", ["<no reason specified>"])[0]
- comments.decode(getRequestCharset(req))
- # html-quote both the username and comments, just to be safe
- reason = ("The web-page 'stop build' button was pressed by "
- "'%s': %s\n" % (html.escape(name), html.escape(comments)))
-
- c = interfaces.IControl(self.getBuildmaster(req))
- bldrc = c.getBuilder(self.build_status.getBuilder().getName())
- if bldrc:
- bldc = bldrc.getBuild(self.build_status.getNumber())
- if bldc:
- bldc.stopBuild(reason)
-
- defer.returnValue(path_to_builder(req, self.build_status.getBuilder()))
-
-# /builders/$builder/builds/$buildnum
-class StatusResourceBuild(HtmlResource):
- addSlash = True
-
- def __init__(self, build_status):
- HtmlResource.__init__(self)
- self.build_status = build_status
-
- def getPageTitle(self, request):
- return ("Buildbot: %s Build #%d" %
- (self.build_status.getBuilder().getName(),
- self.build_status.getNumber()))
-
- def content(self, req, cxt):
- b = self.build_status
- status = self.getStatus(req)
- req.setHeader('Cache-Control', 'no-cache')
-
- cxt['b'] = b
- cxt['path_to_builder'] = path_to_builder(req, b.getBuilder())
-
- if not b.isFinished():
- step = b.getCurrentStep()
- if not step:
- cxt['current_step'] = "[waiting for Lock]"
- else:
- if step.isWaitingForLocks():
- cxt['current_step'] = "%s [waiting for Lock]" % step.getName()
- else:
- cxt['current_step'] = step.getName()
- when = b.getETA()
- if when is not None:
- cxt['when'] = util.formatInterval(when)
- cxt['when_time'] = time.strftime("%H:%M:%S",
- time.localtime(time.time() + when))
-
- else:
- cxt['result_css'] = css_classes[b.getResults()]
- if b.getTestResults():
- cxt['tests_link'] = req.childLink("tests")
-
- ssList = b.getSourceStamps()
- sourcestamps = cxt['sourcestamps'] = ssList
-
- all_got_revisions = b.getAllGotRevisions()
- cxt['got_revisions'] = all_got_revisions
-
- try:
- cxt['slave_url'] = path_to_slave(req, status.getSlave(b.getSlavename()))
- except KeyError:
- pass
-
- cxt['steps'] = []
-
- for s in b.getSteps():
- step = {'name': s.getName() }
-
- if s.isFinished():
- if s.isHidden():
- continue
-
- step['css_class'] = css_classes[s.getResults()[0]]
- (start, end) = s.getTimes()
- step['time_to_run'] = util.formatInterval(end - start)
- elif s.isStarted():
- if s.isWaitingForLocks():
- step['css_class'] = "waiting"
- step['time_to_run'] = "waiting for locks"
- else:
- start = s.getTimes()[0]
- step['css_class'] = "running"
- step['time_to_run'] = "running %s" % (util.formatInterval(util.now() - start))
- else:
- step['css_class'] = "not_started"
- step['time_to_run'] = ""
-
- cxt['steps'].append(step)
-
- step['link'] = req.childLink("steps/%s" %
- urllib.quote(s.getName(), safe=''))
- step['text'] = " ".join(s.getText())
- step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items())
-
- step['logs']= []
- for l in s.getLogs():
- logname = l.getName()
- step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" %
- (urllib.quote(s.getName(), safe=''),
- urllib.quote(logname, safe=''))),
- 'name': logname })
-
- scheduler = b.getProperty("scheduler", None)
- parameters = {}
- master = self.getBuildmaster(req)
- for sch in master.allSchedulers():
- if isinstance(sch, ForceScheduler) and scheduler == sch.name:
- for p in sch.all_fields:
- parameters[p.name] = p
-
- ps = cxt['properties'] = []
- for name, value, source in b.getProperties().asList():
- if not isinstance(value, dict):
- cxt_value = unicode(value)
- else:
- cxt_value = value
- p = { 'name': name, 'value': cxt_value, 'source': source}
- if len(cxt_value) > 500:
- p['short_value'] = cxt_value[:500]
- if name in parameters:
- param = parameters[name]
- if isinstance(param, TextParameter):
- p['text'] = param.value_to_text(value)
- p['cols'] = param.cols
- p['rows'] = param.rows
- p['label'] = param.label
- ps.append(p)
-
-
- cxt['responsible_users'] = list(b.getResponsibleUsers())
-
- (start, end) = b.getTimes()
- cxt['start'] = time.ctime(start)
- if end:
- cxt['end'] = time.ctime(end)
- cxt['elapsed'] = util.formatInterval(end - start)
- else:
- now = util.now()
- cxt['elapsed'] = util.formatInterval(now - start)
-
- exactly = True
- has_changes = False
- for ss in sourcestamps:
- exactly = exactly and (ss.revision is not None)
- has_changes = has_changes or ss.changes
- cxt['exactly'] = (exactly) or b.getChanges()
- cxt['has_changes'] = has_changes
- cxt['build_url'] = path_to_build(req, b)
- cxt['authz'] = self.getAuthz(req)
-
- template = req.site.buildbot_service.templates.get_template("build.html")
- return template.render(**cxt)
-
- def stop(self, req, auth_ok=False):
- # check if this is allowed
- if not auth_ok:
- return StopBuildActionResource(self.build_status)
-
- b = self.build_status
- log.msg("web stopBuild of build %s:%s" % \
- (b.getBuilder().getName(), b.getNumber()))
-
- name = self.getAuthz(req).getUsernameFull(req)
- comments = req.args.get("comments", ["<no reason specified>"])[0]
- comments.decode(getRequestCharset(req))
- # html-quote both the username and comments, just to be safe
- reason = ("The web-page 'stop build' button was pressed by "
- "'%s': %s\n" % (html.escape(name), html.escape(comments)))
-
- c = interfaces.IControl(self.getBuildmaster(req))
- bldrc = c.getBuilder(self.build_status.getBuilder().getName())
- if bldrc:
- bldc = bldrc.getBuild(self.build_status.getNumber())
- if bldc:
- bldc.stopBuild(reason)
-
- # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and
- # we want to go to: http://localhost:8080/svn-hello
- r = Redirect(path_to_builder(req, self.build_status.getBuilder()))
- d = defer.Deferred()
- reactor.callLater(1, d.callback, r)
- return DeferredResource(d)
-
- def rebuild(self, req):
- return ForceBuildActionResource(self.build_status,
- self.build_status.getBuilder())
-
- def getChild(self, path, req):
- if path == "stop":
- return self.stop(req)
- if path == "rebuild":
- return self.rebuild(req)
- if path == "steps":
- return StepsResource(self.build_status)
- if path == "tests":
- return TestsResource(self.build_status)
-
- return HtmlResource.getChild(self, path, req)
-
-# /builders/$builder/builds
-class BuildsResource(HtmlResource):
- addSlash = True
-
- def __init__(self, builder_status):
- HtmlResource.__init__(self)
- self.builder_status = builder_status
-
- def content(self, req, cxt):
- return "subpages shows data for each build"
-
- def getChild(self, path, req):
- try:
- num = int(path)
- except ValueError:
- num = None
- if num is not None:
- build_status = self.builder_status.getBuild(num)
- if build_status:
- return StatusResourceBuild(build_status)
-
- return HtmlResource.getChild(self, path, req)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py
deleted file mode 100644
index b4d15233..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py
+++ /dev/null
@@ -1,632 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from twisted.web import html
-import urllib, time
-from twisted.python import log
-from twisted.internet import defer
-from buildbot import interfaces
-from buildbot.status.web.base import HtmlResource, BuildLineMixin, \
- path_to_build, path_to_slave, path_to_builder, path_to_change, \
- path_to_root, ICurrentBox, build_get_class, \
- map_branches, path_to_authzfail, ActionResource, \
- getRequestCharset
-from buildbot.schedulers.forcesched import ForceScheduler
-from buildbot.schedulers.forcesched import ValidationError
-from buildbot.status.web.build import BuildsResource, StatusResourceBuild
-from buildbot import util
-import collections
-
-class ForceAction(ActionResource):
- @defer.inlineCallbacks
- def force(self, req, builderNames):
- master = self.getBuildmaster(req)
- owner = self.getAuthz(req).getUsernameFull(req)
- schedulername = req.args.get("forcescheduler", ["<unknown>"])[0]
- if schedulername == "<unknown>":
- defer.returnValue((path_to_builder(req, self.builder_status),
- "forcescheduler arg not found"))
- return
-
- args = {}
- # decode all of the args
- encoding = getRequestCharset(req)
- for name, argl in req.args.iteritems():
- if name == "checkbox":
- # damn html's ungeneric checkbox implementation...
- for cb in argl:
- args[cb.decode(encoding)] = True
- else:
- args[name] = [ arg.decode(encoding) for arg in argl ]
-
- for sch in master.allSchedulers():
- if schedulername == sch.name:
- try:
- yield sch.force(owner, builderNames, **args)
- msg = ""
- except ValidationError, e:
- msg = html.escape(e.message.encode('ascii','ignore'))
- break
-
- # send the user back to the builder page
- defer.returnValue(msg)
-
-
-class ForceAllBuildsActionResource(ForceAction):
-
- def __init__(self, status, selectedOrAll):
- self.status = status
- self.selectedOrAll = selectedOrAll
- self.action = "forceAllBuilds"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed('forceAllBuilds', req)
-
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- if self.selectedOrAll == 'all':
- builderNames = None
- elif self.selectedOrAll == 'selected':
- builderNames = [b for b in req.args.get("selected", []) if b]
-
- msg = yield self.force(req, builderNames)
-
- # back to the welcome page
- defer.returnValue((path_to_root(req) + "builders", msg))
-
-class StopAllBuildsActionResource(ActionResource):
-
- def __init__(self, status, selectedOrAll):
- self.status = status
- self.selectedOrAll = selectedOrAll
- self.action = "stopAllBuilds"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed('stopAllBuilds', req)
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- builders = None
- if self.selectedOrAll == 'all':
- builders = self.status.getBuilderNames()
- elif self.selectedOrAll == 'selected':
- builders = [b for b in req.args.get("selected", []) if b]
-
- for bname in builders:
- builder_status = self.status.getBuilder(bname)
- (state, current_builds) = builder_status.getState()
- if state != "building":
- continue
- for b in current_builds:
- build_status = builder_status.getBuild(b.number)
- if not build_status:
- continue
- build = StatusResourceBuild(build_status)
- build.stop(req, auth_ok=True)
-
- # go back to the welcome page
- defer.returnValue(path_to_root(req))
-
-
-class CancelAllPendingBuildsActionResource(ActionResource):
-
- def __init__(self, status, selectedOrAll):
- self.status = status
- self.selectedOrAll = selectedOrAll
- self.action = 'cancelAllPendingBuilds'
-
- @defer.inlineCallbacks
- def performAction(self, req):
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed('cancelAllPendingBuilds', req)
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- builders = None
- if self.selectedOrAll == 'all':
- builders = self.status.getBuilderNames()
- elif self.selectedOrAll == 'selected':
- builders = [b for b in req.args.get("selected", []) if b]
-
- c = interfaces.IControl(self.getBuildmaster(req))
- for bname in builders:
- authz = self.getAuthz(req)
- builder_control = c.getBuilder(bname)
-
- brcontrols = yield builder_control.getPendingBuildRequestControls()
-
- for build_req in brcontrols:
- log.msg("Cancelling %s" % build_req)
- build_req.cancel()
-
- # go back to the welcome page
- defer.returnValue(path_to_root(req))
-
-
-class PingBuilderActionResource(ActionResource):
-
- def __init__(self, builder_status):
- self.builder_status = builder_status
- self.action = "pingBuilder"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- log.msg("web ping of builder '%s'" % self.builder_status.getName())
- res = yield self.getAuthz(req).actionAllowed('pingBuilder', req,
- self.builder_status)
- if not res:
- log.msg("..but not authorized")
- defer.returnValue(path_to_authzfail(req))
- return
-
- c = interfaces.IControl(self.getBuildmaster(req))
- bc = c.getBuilder(self.builder_status.getName())
- bc.ping()
- # send the user back to the builder page
- defer.returnValue(path_to_builder(req, self.builder_status))
-
-class ForceBuildActionResource(ForceAction):
-
- def __init__(self, builder_status):
- self.builder_status = builder_status
- self.action = "forceBuild"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- # check if this is allowed
- res = yield self.getAuthz(req).actionAllowed(self.action, req,
- self.builder_status)
- if not res:
- log.msg("..but not authorized")
- defer.returnValue(path_to_authzfail(req))
- return
-
- builderName = self.builder_status.getName()
-
- msg = yield self.force(req, [builderName])
-
- # send the user back to the builder page
- defer.returnValue((path_to_builder(req, self.builder_status), msg))
-
-def buildForceContextForField(req, default_props, sch, field, master, buildername):
- pname = "%s.%s"%(sch.name, field.fullName)
-
- default = field.default
-
- if "list" in field.type:
- choices = field.getChoices(master, sch, buildername)
- if choices:
- default = choices[0]
- default_props[pname+".choices"] = choices
-
- default = req.args.get(pname, [default])[0]
- if "bool" in field.type:
- default = "checked" if default else ""
- elif isinstance(default, unicode):
- # filter out unicode chars, and html stuff
- default = html.escape(default.encode('utf-8','ignore'))
-
- default_props[pname] = default
-
- if "nested" in field.type:
- for subfield in field.fields:
- buildForceContextForField(req, default_props, sch, subfield, master, buildername)
-
-def buildForceContext(cxt, req, master, buildername=None):
- force_schedulers = {}
- default_props = collections.defaultdict(str)
- for sch in master.allSchedulers():
- if isinstance(sch, ForceScheduler) and (buildername is None or(buildername in sch.builderNames)):
- force_schedulers[sch.name] = sch
- for field in sch.all_fields:
- buildForceContextForField(req, default_props, sch, field, master, buildername)
-
- cxt['force_schedulers'] = force_schedulers
- cxt['default_props'] = default_props
-
-# /builders/$builder
-class StatusResourceBuilder(HtmlResource, BuildLineMixin):
- addSlash = True
-
- def __init__(self, builder_status, numbuilds=20):
- HtmlResource.__init__(self)
- self.builder_status = builder_status
- self.numbuilds = numbuilds
-
- def getPageTitle(self, request):
- return "Buildbot: %s" % self.builder_status.getName()
-
- def builder(self, build, req):
- b = {}
-
- b['num'] = build.getNumber()
- b['link'] = path_to_build(req, build)
-
- when = build.getETA()
- if when is not None:
- b['when'] = util.formatInterval(when)
- b['when_time'] = time.strftime("%H:%M:%S",
- time.localtime(time.time() + when))
-
- step = build.getCurrentStep()
- # TODO: is this necessarily the case?
- if not step:
- b['current_step'] = "[waiting for Lock]"
- else:
- if step.isWaitingForLocks():
- b['current_step'] = "%s [waiting for Lock]" % step.getName()
- else:
- b['current_step'] = step.getName()
-
- b['stop_url'] = path_to_build(req, build) + '/stop'
-
- return b
-
- @defer.inlineCallbacks
- def content(self, req, cxt):
- b = self.builder_status
-
- cxt['name'] = b.getName()
- cxt['description'] = b.getDescription()
- req.setHeader('Cache-Control', 'no-cache')
- slaves = b.getSlaves()
- connected_slaves = [s for s in slaves if s.isConnected()]
-
- cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()]
-
- cxt['pending'] = []
- statuses = yield b.getPendingBuildRequestStatuses()
- for pb in statuses:
- changes = []
-
- source = yield pb.getSourceStamp()
- submitTime = yield pb.getSubmitTime()
- bsid = yield pb.getBsid()
-
- properties = yield \
- pb.master.db.buildsets.getBuildsetProperties(bsid)
-
- if source.changes:
- for c in source.changes:
- changes.append({ 'url' : path_to_change(req, c),
- 'who' : c.who,
- 'revision' : c.revision,
- 'repo' : c.repository })
-
- cxt['pending'].append({
- 'when': time.strftime("%b %d %H:%M:%S",
- time.localtime(submitTime)),
- 'delay': util.formatInterval(util.now() - submitTime),
- 'id': pb.brid,
- 'changes' : changes,
- 'num_changes' : len(changes),
- 'properties' : properties,
- })
-
- numbuilds = cxt['numbuilds'] = int(req.args.get('numbuilds', [self.numbuilds])[0])
- recent = cxt['recent'] = []
- for build in b.generateFinishedBuilds(num_builds=int(numbuilds)):
- recent.append(self.get_line_values(req, build, False))
-
- sl = cxt['slaves'] = []
- connected_slaves = 0
- for slave in slaves:
- s = {}
- sl.append(s)
- s['link'] = path_to_slave(req, slave)
- s['name'] = slave.getName()
- c = s['connected'] = slave.isConnected()
- s['paused'] = slave.isPaused()
- s['admin'] = unicode(slave.getAdmin() or '', 'utf-8')
- if c:
- connected_slaves += 1
- cxt['connected_slaves'] = connected_slaves
-
- cxt['authz'] = self.getAuthz(req)
- cxt['builder_url'] = path_to_builder(req, b)
- buildForceContext(cxt, req, self.getBuildmaster(req), b.getName())
- template = req.site.buildbot_service.templates.get_template("builder.html")
- defer.returnValue(template.render(**cxt))
-
- def ping(self, req):
- return PingBuilderActionResource(self.builder_status)
-
- def getChild(self, path, req):
- if path == "force":
- return ForceBuildActionResource(self.builder_status)
- if path == "ping":
- return self.ping(req)
- if path == "cancelbuild":
- return CancelChangeResource(self.builder_status)
- if path == "stopchange":
- return StopChangeResource(self.builder_status)
- if path == "builds":
- return BuildsResource(self.builder_status)
-
- return HtmlResource.getChild(self, path, req)
-
-class CancelChangeResource(ActionResource):
-
- def __init__(self, builder_status):
- ActionResource.__init__(self)
- self.builder_status = builder_status
-
- @defer.inlineCallbacks
- def performAction(self, req):
- try:
- request_id = req.args.get("id", [None])[0]
- if request_id == "all":
- cancel_all = True
- else:
- cancel_all = False
- request_id = int(request_id)
- except:
- request_id = None
-
- authz = self.getAuthz(req)
- if request_id:
- c = interfaces.IControl(self.getBuildmaster(req))
- builder_control = c.getBuilder(self.builder_status.getName())
-
- brcontrols = yield builder_control.getPendingBuildRequestControls()
-
- for build_req in brcontrols:
- if cancel_all or (build_req.brid == request_id):
- log.msg("Cancelling %s" % build_req)
- res = yield authz.actionAllowed('cancelPendingBuild', req,
- build_req)
- if res:
- build_req.cancel()
- else:
- defer.returnValue(path_to_authzfail(req))
- return
- if not cancel_all:
- break
-
- defer.returnValue(path_to_builder(req, self.builder_status))
-
-class StopChangeMixin(object):
-
- @defer.inlineCallbacks
- def stopChangeForBuilder(self, req, builder_status, auth_ok=False):
- try:
- request_change = req.args.get("change", [None])[0]
- request_change = int(request_change)
- except:
- request_change = None
-
- authz = self.getAuthz(req)
- if request_change:
- c = interfaces.IControl(self.getBuildmaster(req))
- builder_control = c.getBuilder(builder_status.getName())
-
- brcontrols = yield builder_control.getPendingBuildRequestControls()
- build_controls = dict((x.brid, x) for x in brcontrols)
-
- build_req_statuses = yield \
- builder_status.getPendingBuildRequestStatuses()
-
- for build_req in build_req_statuses:
- ss = yield build_req.getSourceStamp()
-
- if not ss.changes:
- continue
-
- for change in ss.changes:
- if change.number == request_change:
- control = build_controls[build_req.brid]
- log.msg("Cancelling %s" % control)
- res = yield authz.actionAllowed('stopChange', req, control)
- if (auth_ok or res):
- control.cancel()
- else:
- defer.returnValue(False)
- return
-
- defer.returnValue(True)
-
-
-class StopChangeResource(StopChangeMixin, ActionResource):
-
- def __init__(self, builder_status):
- ActionResource.__init__(self)
- self.builder_status = builder_status
-
- @defer.inlineCallbacks
- def performAction(self, req):
- """Cancel all pending builds that include a given numbered change."""
- success = yield self.stopChangeForBuilder(req, self.builder_status)
-
- if not success:
- defer.returnValue(path_to_authzfail(req))
- else:
- defer.returnValue(path_to_builder(req, self.builder_status))
-
-
-class StopChangeAllResource(StopChangeMixin, ActionResource):
-
- def __init__(self, status):
- ActionResource.__init__(self)
- self.status = status
-
- @defer.inlineCallbacks
- def performAction(self, req):
- """Cancel all pending builds that include a given numbered change."""
- authz = self.getAuthz(req)
- res = yield authz.actionAllowed('stopChange', req)
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- for bname in self.status.getBuilderNames():
- builder_status = self.status.getBuilder(bname)
- res = yield self.stopChangeForBuilder(req, builder_status, auth_ok=True)
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
-
- defer.returnValue(path_to_root(req))
-
-
-# /builders/_all
-class StatusResourceAllBuilders(HtmlResource, BuildLineMixin):
-
- def __init__(self, status):
- HtmlResource.__init__(self)
- self.status = status
-
- def getChild(self, path, req):
- if path == "forceall":
- return self.forceall(req)
- if path == "stopall":
- return self.stopall(req)
- if path == "stopchangeall":
- return StopChangeAllResource(self.status)
- if path == "cancelpendingall":
- return CancelAllPendingBuildsActionResource(self.status, 'all')
-
- return HtmlResource.getChild(self, path, req)
-
- def forceall(self, req):
- return ForceAllBuildsActionResource(self.status, 'all')
-
- def stopall(self, req):
- return StopAllBuildsActionResource(self.status, 'all')
-
-# /builders/_selected
-
-
-class StatusResourceSelectedBuilders(HtmlResource, BuildLineMixin):
-
- def __init__(self, status):
- HtmlResource.__init__(self)
- self.status = status
-
- def getChild(self, path, req):
- if path == "forceselected":
- return self.forceselected(req)
- if path == "stopselected":
- return self.stopselected(req)
- if path == "cancelpendingselected":
- return CancelAllPendingBuildsActionResource(self.status, 'selected')
-
- return HtmlResource.getChild(self, path, req)
-
- def forceselected(self, req):
- return ForceAllBuildsActionResource(self.status, 'selected')
-
- def stopselected(self, req):
- return StopAllBuildsActionResource(self.status, 'selected')
-
-# /builders
-
-
-class BuildersResource(HtmlResource):
- pageTitle = "Builders"
- addSlash = True
-
- def __init__(self, numbuilds=20):
- HtmlResource.__init__(self)
- self.numbuilds = numbuilds
-
- @defer.inlineCallbacks
- def content(self, req, cxt):
- status = self.getStatus(req)
- encoding = getRequestCharset(req)
-
- builders = req.args.get("builder", status.getBuilderNames())
- branches = [ b.decode(encoding)
- for b in req.args.get("branch", [])
- if b ]
-
- # get counts of pending builds for each builder
- brstatus_ds = []
- brcounts = {}
- def keep_count(statuses, builderName):
- brcounts[builderName] = len(statuses)
- for builderName in builders:
- builder_status = status.getBuilder(builderName)
- d = builder_status.getPendingBuildRequestStatuses()
- d.addCallback(keep_count, builderName)
- brstatus_ds.append(d)
- yield defer.gatherResults(brstatus_ds)
-
- cxt['branches'] = branches
- bs = cxt['builders'] = []
-
- building = 0
- online = 0
- base_builders_url = path_to_root(req) + "builders/"
- for bn in builders:
- bld = { 'link': base_builders_url + urllib.quote(bn, safe=''),
- 'name': bn }
- bs.append(bld)
-
- builder = status.getBuilder(bn)
- builds = list(builder.generateFinishedBuilds(map_branches(branches),
- num_builds=1))
- if builds:
- b = builds[0]
- bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber())
- label = None
- all_got_revisions = b.getAllGotRevisions()
- # If len = 1 then try if revision can be used as label.
- if len(all_got_revisions) == 1:
- label = all_got_revisions[all_got_revisions.keys()[0]]
- if not label or len(str(label)) > 20:
- label = "#%d" % b.getNumber()
-
- bld['build_label'] = label
- bld['build_text'] = " ".join(b.getText())
- bld['build_css_class'] = build_get_class(b)
-
- current_box = ICurrentBox(builder).getBox(status, brcounts)
- bld['current_box'] = current_box.td()
-
- builder_status = builder.getState()[0]
- if builder_status == "building":
- building += 1
- online += 1
- elif builder_status != "offline":
- online += 1
-
- cxt['authz'] = self.getAuthz(req)
- cxt['num_building'] = building
- cxt['num_online'] = online
- buildForceContext(cxt, req, self.getBuildmaster(req))
- template = req.site.buildbot_service.templates.get_template("builders.html")
- defer.returnValue(template.render(**cxt))
-
- def getChild(self, path, req):
- s = self.getStatus(req)
- if path in s.getBuilderNames():
- builder_status = s.getBuilder(path)
- return StatusResourceBuilder(builder_status, self.numbuilds)
- if path == "_all":
- return StatusResourceAllBuilders(self.getStatus(req))
- if path == "_selected":
- return StatusResourceSelectedBuilders(self.getStatus(req))
-
- return HtmlResource.getChild(self, path, req)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py
deleted file mode 100644
index 9dd57b6c..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from buildbot.status.web.base import HtmlResource, IBox
-
-class BuildStatusStatusResource(HtmlResource):
- def __init__(self, categories=None):
- HtmlResource.__init__(self)
-
- def content(self, request, ctx):
- """Display a build in the same format as the waterfall page.
- The HTTP GET parameters are the builder name and the build
- number."""
-
- status = self.getStatus(request)
- request.setHeader('Cache-Control', 'no-cache')
-
- # Get the parameters.
- name = request.args.get("builder", [None])[0]
- number = request.args.get("number", [None])[0]
- if not name or not number:
- return "builder and number parameter missing"
- number = int(number)
-
- # Check if the builder in parameter exists.
- try:
- builder = status.getBuilder(name)
- except:
- return "unknown builder"
-
- # Check if the build in parameter exists.
- build = builder.getBuild(int(number))
- if not build:
- return "unknown build %s" % number
-
- rows = ctx['rows'] = []
-
- # Display each step, starting by the last one.
- for i in range(len(build.getSteps()) - 1, -1, -1):
- step = build.getSteps()[i]
- if step.isStarted() and step.getText():
- rows.append(IBox(step).getBox(request).td(align="center"))
-
- # Display the bottom box with the build number in it.
- ctx['build'] = IBox(build).getBox(request).td(align="center")
-
- template = request.site.buildbot_service.templates.get_template("buildstatus.html")
- data = template.render(**ctx)
-
- # We want all links to display in a new tab/window instead of in the
- # current one.
- # TODO: Move to template
- data = data.replace('<a ', '<a target="_blank"')
- return data
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py
deleted file mode 100644
index cc53e34b..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-# code inspired/copied from contrib/github_buildbot
-# and inspired from code from the Chromium project
-# otherwise, Andrew Melo <andrew.melo@gmail.com> wrote the rest
-# but "the rest" is pretty minimal
-
-import re
-from twisted.web import resource, server
-from twisted.python.reflect import namedModule
-from twisted.python import log
-from twisted.internet import defer
-
-class ChangeHookResource(resource.Resource):
- # this is a cheap sort of template thingy
- contentType = "text/html; charset=utf-8"
- children = {}
- def __init__(self, dialects={}):
- """
- The keys of 'dialects' select a modules to load under
- master/buildbot/status/web/hooks/
- The value is passed to the module's getChanges function, providing
- configuration options to the dialect.
- """
- self.dialects = dialects
- self.request_dialect = None
-
- def getChild(self, name, request):
- return self
-
- def render_GET(self, request):
- """
- Reponds to events and starts the build process
- different implementations can decide on what methods they will accept
- """
- return self.render_POST(request)
-
- def render_POST(self, request):
- """
- Reponds to events and starts the build process
- different implementations can decide on what methods they will accept
-
- :arguments:
- request
- the http request object
- """
-
- try:
- changes, src = self.getChanges( request )
- except ValueError, err:
- request.setResponseCode(400, err.args[0])
- return err.args[0]
- except Exception, e:
- log.err(e, "processing changes from web hook")
- msg = "Error processing changes."
- request.setResponseCode(500, msg)
- return msg
-
- log.msg("Payload: " + str(request.args))
-
- if not changes:
- log.msg("No changes found")
- return "no changes found"
- d = self.submitChanges( changes, request, src )
- def ok(_):
- request.setResponseCode(202)
- request.finish()
- def err(why):
- log.err(why, "adding changes from web hook")
- request.setResponseCode(500)
- request.finish()
- d.addCallbacks(ok, err)
- return server.NOT_DONE_YET
-
-
- def getChanges(self, request):
- """
- Take the logic from the change hook, and then delegate it
- to the proper handler
- http://localhost/change_hook/DIALECT will load up
- buildmaster/status/web/hooks/DIALECT.py
-
- and call getChanges()
-
- the return value is a list of changes
-
- if DIALECT is unspecified, a sample implementation is provided
- """
- uriRE = re.search(r'^/change_hook/?([a-zA-Z0-9_]*)', request.uri)
-
- if not uriRE:
- log.msg("URI doesn't match change_hook regex: %s" % request.uri)
- raise ValueError("URI doesn't match change_hook regex: %s" % request.uri)
-
- changes = []
- src = None
-
- # Was there a dialect provided?
- if uriRE.group(1):
- dialect = uriRE.group(1)
- else:
- dialect = 'base'
-
- if dialect in self.dialects.keys():
- log.msg("Attempting to load module buildbot.status.web.hooks." + dialect)
- tempModule = namedModule('buildbot.status.web.hooks.' + dialect)
- changes, src = tempModule.getChanges(request,self.dialects[dialect])
- log.msg("Got the following changes %s" % changes)
- self.request_dialect = dialect
- else:
- m = "The dialect specified, '%s', wasn't whitelisted in change_hook" % dialect
- log.msg(m)
- log.msg("Note: if dialect is 'base' then it's possible your URL is malformed and we didn't regex it properly")
- raise ValueError(m)
-
- return (changes, src)
-
- @defer.inlineCallbacks
- def submitChanges(self, changes, request, src):
- master = request.site.buildbot_service.master
- for chdict in changes:
- change = yield master.addChange(src=src, **chdict)
- log.msg("injected change %s" % change)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py
deleted file mode 100644
index e579669e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from zope.interface import implements
-from twisted.python import components
-from twisted.web.resource import NoResource
-
-from buildbot.changes.changes import Change
-from buildbot.status.web.base import HtmlResource, IBox, Box
-
-class ChangeResource(HtmlResource):
- def __init__(self, changeid):
- self.changeid = changeid
- self.pageTitle = "Change #%d" % changeid
-
- def content(self, req, cxt):
- d = self.getStatus(req).getChange(self.changeid)
- def cb(change):
- if not change:
- return "No change number %d" % self.changeid
- templates = req.site.buildbot_service.templates
- cxt['c'] = change.asDict()
- template = templates.get_template("change.html")
- data = template.render(cxt)
- return data
- d.addCallback(cb)
- return d
-
-# /changes/NN
-class ChangesResource(HtmlResource):
-
- def content(self, req, cxt):
- cxt['sources'] = self.getStatus(req).getChangeSources()
- template = req.site.buildbot_service.templates.get_template("change_sources.html")
- return template.render(**cxt)
-
- def getChild(self, path, req):
- try:
- changeid = int(path)
- except ValueError:
- return NoResource("Expected a change number")
-
- return ChangeResource(changeid)
-
-class ChangeBox(components.Adapter):
- implements(IBox)
-
- def getBox(self, req):
- url = req.childLink("../changes/%d" % self.original.number)
- template = req.site.buildbot_service.templates.get_template("change_macros.html")
- text = template.module.box_contents(url=url,
- who=self.original.getShortAuthor(),
- pageTitle=self.original.comments,
- revision=self.original.revision,
- project=self.original.project)
- return Box([text], class_="Change")
-components.registerAdapter(ChangeBox, Change, IBox)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py
deleted file mode 100644
index 60eb67c0..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py
+++ /dev/null
@@ -1,744 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import time
-import operator
-import re
-import urllib
-from twisted.internet import defer
-from buildbot import util
-from buildbot.status import builder
-from buildbot.status.web.base import HtmlResource
-from buildbot.changes import changes
-
-class DoesNotPassFilter(Exception): pass # Used for filtering revs
-
-def getResultsClass(results, prevResults, inProgress):
- """Given the current and past results, return the class that will be used
- by the css to display the right color for a box."""
-
- if inProgress:
- return "running"
-
- if results is None:
- return "notstarted"
-
- if results == builder.SUCCESS:
- return "success"
-
- if results == builder.WARNINGS:
- return "warnings"
-
- if results == builder.FAILURE:
- if not prevResults:
- # This is the bottom box. We don't know if the previous one failed
- # or not. We assume it did not.
- return "failure"
-
- if prevResults != builder.FAILURE:
- # This is a new failure.
- return "failure"
- else:
- # The previous build also failed.
- return "failure-again"
-
- # Any other results? Like EXCEPTION?
- return "exception"
-
-class ANYBRANCH: pass # a flag value, used below
-
-class DevRevision:
- """Helper class that contains all the information we need for a revision."""
-
- def __init__(self, change):
- self.revision = change.revision
- self.comments = change.comments
- self.who = change.who
- self.date = change.getTime()
- self.revlink = getattr(change, 'revlink', None)
- self.when = change.when
- self.repository = change.repository
- self.project = change.project
-
-
-class DevBuild:
- """Helper class that contains all the information we need for a build."""
-
- def __init__(self, revision, build, details):
- self.revision = revision
- self.results = build.getResults()
- self.number = build.getNumber()
- self.isFinished = build.isFinished()
- self.text = build.getText()
- self.eta = build.getETA()
- self.details = details
- self.when = build.getTimes()[0]
- #TODO: support multiple sourcestamps
- self.source = build.getSourceStamps()[0]
-
-
-class ConsoleStatusResource(HtmlResource):
- """Main console class. It displays a user-oriented status page.
- Every change is a line in the page, and it shows the result of the first
- build with this change for each slave."""
-
- def __init__(self, orderByTime=False):
- HtmlResource.__init__(self)
-
- self.status = None
-
- if orderByTime:
- self.comparator = TimeRevisionComparator()
- else:
- self.comparator = IntegerRevisionComparator()
-
- def getPageTitle(self, request):
- status = self.getStatus(request)
- title = status.getTitle()
- if title:
- return "BuildBot: %s" % title
- else:
- return "BuildBot"
-
- def getChangeManager(self, request):
- return request.site.buildbot_service.parent.change_svc
-
- ##
- ## Data gathering functions
- ##
-
- def getHeadBuild(self, builder):
- """Get the most recent build for the given builder.
- """
- build = builder.getBuild(-1)
-
- # HACK: Work around #601, the head build may be None if it is
- # locked.
- if build is None:
- build = builder.getBuild(-2)
-
- return build
-
- def fetchChangesFromHistory(self, status, max_depth, max_builds, debugInfo):
- """Look at the history of the builders and try to fetch as many changes
- as possible. We need this when the main source does not contain enough
- sourcestamps.
-
- max_depth defines how many builds we will parse for a given builder.
- max_builds defines how many builds total we want to parse. This is to
- limit the amount of time we spend in this function.
-
- This function is sub-optimal, but the information returned by this
- function is cached, so this function won't be called more than once.
- """
-
- allChanges = list()
- build_count = 0
- for builderName in status.getBuilderNames()[:]:
- if build_count > max_builds:
- break
-
- builder = status.getBuilder(builderName)
- build = self.getHeadBuild(builder)
- depth = 0
- while build and depth < max_depth and build_count < max_builds:
- depth += 1
- build_count += 1
- sourcestamp = build.getSourceStamps()[0]
- allChanges.extend(sourcestamp.changes[:])
- build = build.getPreviousBuild()
-
- debugInfo["source_fetch_len"] = len(allChanges)
- return allChanges
-
- @defer.inlineCallbacks
- def getAllChanges(self, request, status, debugInfo):
- master = request.site.buildbot_service.master
-
- chdicts = yield master.db.changes.getRecentChanges(25)
-
- # convert those to Change instances
- allChanges = yield defer.gatherResults([
- changes.Change.fromChdict(master, chdict)
- for chdict in chdicts ])
-
- allChanges.sort(key=self.comparator.getSortingKey())
-
- # Remove the dups
- prevChange = None
- newChanges = []
- for change in allChanges:
- rev = change.revision
- if not prevChange or rev != prevChange.revision:
- newChanges.append(change)
- prevChange = change
- allChanges = newChanges
-
- defer.returnValue(allChanges)
-
- def getBuildDetails(self, request, builderName, build):
- """Returns an HTML list of failures for a given build."""
- details = {}
- if not build.getLogs():
- return details
-
- for step in build.getSteps():
- (result, reason) = step.getResults()
- if result == builder.FAILURE:
- name = step.getName()
-
- # Remove html tags from the error text.
- stripHtml = re.compile(r'<.*?>')
- strippedDetails = stripHtml.sub('', ' '.join(step.getText()))
-
- details['buildername'] = builderName
- details['status'] = strippedDetails
- details['reason'] = reason
- logs = details['logs'] = []
-
- if step.getLogs():
- for log in step.getLogs():
- logname = log.getName()
- logurl = request.childLink(
- "../builders/%s/builds/%s/steps/%s/logs/%s" %
- (urllib.quote(builderName),
- build.getNumber(),
- urllib.quote(name),
- urllib.quote(logname)))
- logs.append(dict(url=logurl, name=logname))
- return details
-
- def getBuildsForRevision(self, request, builder, builderName, codebase,
- lastRevision, numBuilds, debugInfo):
- """Return the list of all the builds for a given builder that we will
- need to be able to display the console page. We start by the most recent
- build, and we go down until we find a build that was built prior to the
- last change we are interested in."""
-
- revision = lastRevision
-
- builds = []
- build = self.getHeadBuild(builder)
- number = 0
- while build and number < numBuilds:
- debugInfo["builds_scanned"] += 1
-
- got_rev = None
- sourceStamps = build.getSourceStamps(absolute=True)
-
- # The console page cannot handle builds that have more than 1 revision
- if codebase is not None:
- # Get the last revision in this build for this codebase.
- for ss in sourceStamps:
- if ss.codebase == codebase:
- got_rev = ss.revision
- break
- elif len(sourceStamps) == 1:
- ss = sourceStamps[0]
- # Get the last revision in this build.
- got_rev = ss.revision
-
- # We ignore all builds that don't have last revisions.
- # TODO(nsylvain): If the build is over, maybe it was a problem
- # with the update source step. We need to find a way to tell the
- # user that his change might have broken the source update.
- if got_rev is not None:
- number += 1
- details = self.getBuildDetails(request, builderName, build)
- devBuild = DevBuild(got_rev, build, details)
- builds.append(devBuild)
-
- # Now break if we have enough builds.
- current_revision = self.getChangeForBuild(
- build, revision)
- if self.comparator.isRevisionEarlier(
- devBuild, current_revision):
- break
-
- build = build.getPreviousBuild()
-
- return builds
-
- def getChangeForBuild(self, build, revision):
- if not build or not build.getChanges(): # Forced build
- return DevBuild(revision, build, None)
-
- for change in build.getChanges():
- if change.revision == revision:
- return change
-
- # No matching change, return the last change in build.
- changes = list(build.getChanges())
- changes.sort(key=self.comparator.getSortingKey())
- return changes[-1]
-
- def getAllBuildsForRevision(self, status, request, codebase, lastRevision,
- numBuilds, categories, builders, debugInfo):
- """Returns a dictionary of builds we need to inspect to be able to
- display the console page. The key is the builder name, and the value is
- an array of build we care about. We also returns a dictionary of
- builders we care about. The key is it's category.
-
- codebase is the codebase to get revisions from
- lastRevision is the last revision we want to display in the page.
- categories is a list of categories to display. It is coming from the
- HTTP GET parameters.
- builders is a list of builders to display. It is coming from the HTTP
- GET parameters.
- """
-
- allBuilds = dict()
-
- # List of all builders in the dictionary.
- builderList = dict()
-
- debugInfo["builds_scanned"] = 0
- # Get all the builders.
- builderNames = status.getBuilderNames()[:]
- for builderName in builderNames:
- builder = status.getBuilder(builderName)
-
- # Make sure we are interested in this builder.
- if categories and builder.category not in categories:
- continue
- if builders and builderName not in builders:
- continue
-
- # We want to display this builder.
- category = builder.category or "default"
- # Strip the category to keep only the text before the first |.
- # This is a hack to support the chromium usecase where they have
- # multiple categories for each slave. We use only the first one.
- # TODO(nsylvain): Create another way to specify "display category"
- # in master.cfg.
- category = category.split('|')[0]
- if not builderList.get(category):
- builderList[category] = []
-
- # Append this builder to the dictionary of builders.
- builderList[category].append(builderName)
- # Set the list of builds for this builder.
- allBuilds[builderName] = self.getBuildsForRevision(request,
- builder,
- builderName,
- codebase,
- lastRevision,
- numBuilds,
- debugInfo)
-
- return (builderList, allBuilds)
-
-
- ##
- ## Display functions
- ##
-
- def displayCategories(self, builderList, debugInfo):
- """Display the top category line."""
-
- count = 0
- for category in builderList:
- count += len(builderList[category])
-
- categories = builderList.keys()
- categories.sort()
-
- cs = []
-
- for category in categories:
- c = {}
-
- c["name"] = category
-
- # To be able to align the table correctly, we need to know
- # what percentage of space this category will be taking. This is
- # (#Builders in Category) / (#Builders Total) * 100.
- c["size"] = (len(builderList[category]) * 100) / count
- cs.append(c)
-
- return cs
-
- def displaySlaveLine(self, status, builderList, debugInfo):
- """Display a line the shows the current status for all the builders we
- care about."""
-
- nbSlaves = 0
-
- # Get the number of builders.
- for category in builderList:
- nbSlaves += len(builderList[category])
-
- # Get the categories, and order them alphabetically.
- categories = builderList.keys()
- categories.sort()
-
- slaves = {}
-
- # For each category, we display each builder.
- for category in categories:
- slaves[category] = []
- # For each builder in this category, we set the build info and we
- # display the box.
- for builder in builderList[category]:
- s = {}
- s["color"] = "notstarted"
- s["pageTitle"] = builder
- s["url"] = "./builders/%s" % urllib.quote(builder)
- state, builds = status.getBuilder(builder).getState()
- # Check if it's offline, if so, the box is purple.
- if state == "offline":
- s["color"] = "offline"
- else:
- # If not offline, then display the result of the last
- # finished build.
- build = self.getHeadBuild(status.getBuilder(builder))
- while build and not build.isFinished():
- build = build.getPreviousBuild()
-
- if build:
- s["color"] = getResultsClass(build.getResults(), None,
- False)
-
- slaves[category].append(s)
-
- return slaves
-
- def displayStatusLine(self, builderList, allBuilds, revision, debugInfo):
- """Display the boxes that represent the status of each builder in the
- first build "revision" was in. Returns an HTML list of errors that
- happened during these builds."""
-
- details = []
- nbSlaves = 0
- for category in builderList:
- nbSlaves += len(builderList[category])
-
- # Sort the categories.
- categories = builderList.keys()
- categories.sort()
-
- builds = {}
-
- # Display the boxes by category group.
- for category in categories:
-
- builds[category] = []
-
- # Display the boxes for each builder in this category.
- for builder in builderList[category]:
- introducedIn = None
- firstNotIn = None
-
- # Find the first build that does not include the revision.
- for build in allBuilds[builder]:
- if self.comparator.isRevisionEarlier(build, revision):
- firstNotIn = build
- break
- else:
- introducedIn = build
-
- # Get the results of the first build with the revision, and the
- # first build that does not include the revision.
- results = None
- previousResults = None
- if introducedIn:
- results = introducedIn.results
- if firstNotIn:
- previousResults = firstNotIn.results
-
- isRunning = False
- if introducedIn and not introducedIn.isFinished:
- isRunning = True
-
- url = "./waterfall"
- pageTitle = builder
- tag = ""
- current_details = {}
- if introducedIn:
- current_details = introducedIn.details or ""
- url = "./buildstatus?builder=%s&number=%s" % (urllib.quote(builder),
- introducedIn.number)
- pageTitle += " "
- pageTitle += urllib.quote(' '.join(introducedIn.text), ' \n\\/:')
-
- builderStrip = builder.replace(' ', '')
- builderStrip = builderStrip.replace('(', '')
- builderStrip = builderStrip.replace(')', '')
- builderStrip = builderStrip.replace('.', '')
- tag = "Tag%s%s" % (builderStrip, introducedIn.number)
-
- if isRunning:
- pageTitle += ' ETA: %ds' % (introducedIn.eta or 0)
-
- resultsClass = getResultsClass(results, previousResults, isRunning)
-
- b = {}
- b["url"] = url
- b["pageTitle"] = pageTitle
- b["color"] = resultsClass
- b["tag"] = tag
-
- builds[category].append(b)
-
- # If the box is red, we add the explaination in the details
- # section.
- if current_details and resultsClass == "failure":
- details.append(current_details)
-
- return (builds, details)
-
- def filterRevisions(self, revisions, filter=None, max_revs=None):
- """Filter a set of revisions based on any number of filter criteria.
- If specified, filter should be a dict with keys corresponding to
- revision attributes, and values of 1+ strings"""
- if not filter:
- if max_revs is None:
- for rev in reversed(revisions):
- yield DevRevision(rev)
- else:
- for index,rev in enumerate(reversed(revisions)):
- if index >= max_revs:
- break
- yield DevRevision(rev)
- else:
- for index, rev in enumerate(reversed(revisions)):
- if max_revs and index >= max_revs:
- break
- try:
- for field,acceptable in filter.iteritems():
- if not hasattr(rev, field):
- raise DoesNotPassFilter
- if type(acceptable) in (str, unicode):
- if getattr(rev, field) != acceptable:
- raise DoesNotPassFilter
- elif type(acceptable) in (list, tuple, set):
- if getattr(rev, field) not in acceptable:
- raise DoesNotPassFilter
- yield DevRevision(rev)
- except DoesNotPassFilter:
- pass
-
- def displayPage(self, request, status, builderList, allBuilds, codebase,
- revisions, categories, repository, project, branch,
- debugInfo):
- """Display the console page."""
- # Build the main template directory with all the informations we have.
- subs = dict()
- subs["branch"] = branch or 'trunk'
- subs["repository"] = repository
- subs["project"] = project
- subs["codebase"] = codebase
- if categories:
- subs["categories"] = ' '.join(categories)
- subs["time"] = time.strftime("%a %d %b %Y %H:%M:%S",
- time.localtime(util.now()))
- subs["debugInfo"] = debugInfo
- subs["ANYBRANCH"] = ANYBRANCH
-
- if builderList:
- subs["categories"] = self.displayCategories(builderList, debugInfo)
- subs['slaves'] = self.displaySlaveLine(status, builderList, debugInfo)
- else:
- subs["categories"] = []
-
- subs['revisions'] = []
-
- # For each revision we show one line
- for revision in revisions:
- r = {}
-
- # Fill the dictionary with this new information
- r['id'] = revision.revision
- r['link'] = revision.revlink
- r['who'] = revision.who
- r['date'] = revision.date
- r['comments'] = revision.comments
- r['repository'] = revision.repository
- r['project'] = revision.project
-
- # Display the status for all builders.
- (builds, details) = self.displayStatusLine(builderList,
- allBuilds,
- revision,
- debugInfo)
- r['builds'] = builds
- r['details'] = details
-
- # Calculate the td span for the comment and the details.
- r["span"] = len(builderList) + 2
-
- subs['revisions'].append(r)
-
- #
- # Display the footer of the page.
- #
- debugInfo["load_time"] = time.time() - debugInfo["load_time"]
- return subs
-
-
- def content(self, request, cxt):
- "This method builds the main console view display."
-
- reload_time = None
- # Check if there was an arg. Don't let people reload faster than
- # every 15 seconds. 0 means no reload.
- if "reload" in request.args:
- try:
- reload_time = int(request.args["reload"][0])
- if reload_time != 0:
- reload_time = max(reload_time, 15)
- except ValueError:
- pass
-
- request.setHeader('Cache-Control', 'no-cache')
-
- # Sets the default reload time to 60 seconds.
- if not reload_time:
- reload_time = 60
-
- # Append the tag to refresh the page.
- if reload_time is not None and reload_time != 0:
- cxt['refresh'] = reload_time
-
- # Debug information to display at the end of the page.
- debugInfo = cxt['debuginfo'] = dict()
- debugInfo["load_time"] = time.time()
-
- # get url parameters
- # Categories to show information for.
- categories = request.args.get("category", [])
- # List of all builders to show on the page.
- builders = request.args.get("builder", [])
- # Repo used to filter the changes shown.
- repository = request.args.get("repository", [None])[0]
- # Project used to filter the changes shown.
- project = request.args.get("project", [None])[0]
- # Branch used to filter the changes shown.
- branch = request.args.get("branch", [ANYBRANCH])[0]
- # Codebase used to filter the changes shown.
- codebase = request.args.get("codebase", [None])[0]
- # List of all the committers name to display on the page.
- devName = request.args.get("name", [])
-
- # and the data we want to render
- status = self.getStatus(request)
-
- # Keep only the revisions we care about.
- # By default we process the last 40 revisions.
- # If a dev name is passed, we look for the changes by this person in the
- # last 80 revisions.
- numRevs = int(request.args.get("revs", [40])[0])
- if devName:
- numRevs *= 2
- numBuilds = numRevs
-
- # Get all changes we can find. This is a DB operation, so it must use
- # a deferred.
- d = self.getAllChanges(request, status, debugInfo)
- def got_changes(allChanges):
- debugInfo["source_all"] = len(allChanges)
-
- revFilter = {}
- if branch != ANYBRANCH:
- revFilter['branch'] = branch
- if devName:
- revFilter['who'] = devName
- if repository:
- revFilter['repository'] = repository
- if project:
- revFilter['project'] = project
- if codebase is not None:
- revFilter['codebase'] = codebase
- revisions = list(self.filterRevisions(allChanges, max_revs=numRevs,
- filter=revFilter))
- debugInfo["revision_final"] = len(revisions)
-
- # Fetch all the builds for all builders until we get the next build
- # after lastRevision.
- builderList = None
- allBuilds = None
- if revisions:
- lastRevision = revisions[len(revisions) - 1].revision
- debugInfo["last_revision"] = lastRevision
-
- (builderList, allBuilds) = self.getAllBuildsForRevision(status,
- request,
- codebase,
- lastRevision,
- numBuilds,
- categories,
- builders,
- debugInfo)
-
- debugInfo["added_blocks"] = 0
-
- cxt.update(self.displayPage(request, status, builderList,
- allBuilds, codebase, revisions,
- categories, repository, project,
- branch, debugInfo))
-
- templates = request.site.buildbot_service.templates
- template = templates.get_template("console.html")
- data = template.render(cxt)
- return data
- d.addCallback(got_changes)
- return d
-
-class RevisionComparator(object):
- """Used for comparing between revisions, as some
- VCS use a plain counter for revisions (like SVN)
- while others use different concepts (see Git).
- """
-
- # TODO (avivby): Should this be a zope interface?
-
- def isRevisionEarlier(self, first_change, second_change):
- """Used for comparing 2 changes"""
- raise NotImplementedError
-
- def isValidRevision(self, revision):
- """Checks whether the revision seems like a VCS revision"""
- raise NotImplementedError
-
- def getSortingKey(self):
- raise NotImplementedError
-
-class TimeRevisionComparator(RevisionComparator):
- def isRevisionEarlier(self, first, second):
- return first.when < second.when
-
- def isValidRevision(self, revision):
- return True # No general way of determining
-
- def getSortingKey(self):
- return operator.attrgetter('when')
-
-class IntegerRevisionComparator(RevisionComparator):
- def isRevisionEarlier(self, first, second):
- try:
- return int(first.revision) < int(second.revision)
- except (TypeError, ValueError):
- return False
-
- def isValidRevision(self, revision):
- try:
- int(revision)
- return True
- except:
- return False
-
- def getSortingKey(self):
- return operator.attrgetter('revision')
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py
deleted file mode 100644
index f29a11ca..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py
+++ /dev/null
@@ -1,275 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-# This module enables ATOM and RSS feeds from webstatus.
-#
-# It is based on "feeder.py" which was part of the Buildbot
-# configuration for the Subversion project. The original file was
-# created by Lieven Gobaerts and later adjusted by API
-# (apinheiro@igalia.coma) and also here
-# http://code.google.com/p/pybots/source/browse/trunk/master/Feeder.py
-#
-# All subsequent changes to feeder.py where made by Chandan-Dutta
-# Chowdhury <chandan-dutta.chowdhury @ hp.com> and Gareth Armstrong
-# <gareth.armstrong @ hp.com>.
-#
-# Those modifications are as follows:
-# 1) the feeds are usable from baseweb.WebStatus
-# 2) feeds are fully validated ATOM 1.0 and RSS 2.0 feeds, verified
-# with code from http://feedvalidator.org
-# 3) nicer xml output
-# 4) feeds can be filtered as per the /waterfall display with the
-# builder and category filters
-# 5) cleaned up white space and imports
-#
-# Finally, the code was directly integrated into these two files,
-# buildbot/status/web/feeds.py (you're reading it, ;-)) and
-# buildbot/status/web/baseweb.py.
-
-import os
-import re
-import time
-from twisted.web import resource
-from buildbot.status import results
-
-class XmlResource(resource.Resource):
- contentType = "text/xml; charset=UTF-8"
- docType = ''
-
- def getChild(self, name, request):
- return self
-
- def render(self, request):
- data = self.content(request)
- request.setHeader("content-type", self.contentType)
- if request.method == "HEAD":
- request.setHeader("content-length", len(data))
- return ''
- return data
-
-_abbr_day = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
-_abbr_mon = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
- 'Sep', 'Oct', 'Nov', 'Dec']
-
-def rfc822_time(tstamp):
- res = time.strftime("%%s, %d %%s %Y %H:%M:%S GMT",
- tstamp)
- res = res % (_abbr_day[tstamp.tm_wday], _abbr_mon[tstamp.tm_mon])
- return res
-
-class FeedResource(XmlResource):
- pageTitle = None
- link = 'http://dummylink'
- language = 'en-us'
- description = 'Dummy rss'
- status = None
-
- def __init__(self, status, categories=None, pageTitle=None):
- self.status = status
- self.categories = categories
- self.pageTitle = pageTitle
- self.title = self.status.getTitle()
- self.link = self.status.getBuildbotURL()
- self.description = 'List of builds'
- self.pubdate = time.gmtime(int(time.time()))
- self.user = self.getEnv(['USER', 'USERNAME'], 'buildmaster')
- self.hostname = self.getEnv(['HOSTNAME', 'COMPUTERNAME'],
- 'buildmaster')
- self.children = {}
-
- def getEnv(self, keys, fallback):
- for key in keys:
- if key in os.environ:
- return os.environ[key]
- return fallback
-
- def getBuilds(self, request):
- builds = []
- # THIS is lifted straight from the WaterfallStatusResource Class in
- # status/web/waterfall.py
- #
- # we start with all Builders available to this Waterfall: this is
- # limited by the config-file -time categories= argument, and defaults
- # to all defined Builders.
- allBuilderNames = self.status.getBuilderNames(categories=self.categories)
- builders = [self.status.getBuilder(name) for name in allBuilderNames]
-
- # but if the URL has one or more builder= arguments (or the old show=
- # argument, which is still accepted for backwards compatibility), we
- # use that set of builders instead. We still don't show anything
- # outside the config-file time set limited by categories=.
- showBuilders = request.args.get("show", [])
- showBuilders.extend(request.args.get("builder", []))
- if showBuilders:
- builders = [b for b in builders if b.name in showBuilders]
-
- # now, if the URL has one or category= arguments, use them as a
- # filter: only show those builders which belong to one of the given
- # categories.
- showCategories = request.args.get("category", [])
- if showCategories:
- builders = [b for b in builders if b.category in showCategories]
-
- failures_only = request.args.get("failures_only", ["false"])
- failures_only = failures_only[0] not in ('false', '0', 'no', 'off')
-
- maxFeeds = 25
-
- # Copy all failed builds in a new list.
- # This could clearly be implemented much better if we had
- # access to a global list of builds.
- for b in builders:
- if failures_only:
- res = (results.FAILURE,)
- else:
- res = None
- builds.extend(b.generateFinishedBuilds(results=res, max_search=maxFeeds))
-
- # Sort build list by date, youngest first.
- # To keep compatibility with python < 2.4, use this for sorting instead:
- # We apply Decorate-Sort-Undecorate
- deco = [(build.getTimes(), build) for build in builds]
- deco.sort()
- deco.reverse()
- builds = [build for (b1, build) in deco]
-
- if builds:
- builds = builds[:min(len(builds), maxFeeds)]
- return builds
-
- def content(self, request):
- builds = self.getBuilds(request)
-
- build_cxts = []
-
- for build in builds:
- start, finished = build.getTimes()
- finishedTime = time.gmtime(int(finished))
- link = re.sub(r'index.html', "", self.status.getURLForThing(build))
-
- # title: trunk r22191 (plus patch) failed on
- # 'i686-debian-sarge1 shared gcc-3.3.5'
- ss_list = build.getSourceStamps()
- all_got_revisions = build.getAllGotRevisions()
- src_cxts = []
- for ss in ss_list:
- sc = {}
- sc['codebase'] = ss.codebase
- if (ss.branch is None and ss.revision is None and ss.patch is None
- and not ss.changes):
- sc['repository'] = None
- sc['branch'] = None
- sc['revision'] = "Latest revision"
- else:
- sc['repository'] = ss.repository
- sc['branch'] = ss.branch
- got_revision = all_got_revisions.get(ss.codebase, None)
- if got_revision:
- sc['revision'] = got_revision
- else:
- sc['revision'] = str(ss.revision)
- if ss.patch:
- sc['revision'] += " (plus patch)"
- if ss.changes:
- pass
- src_cxts.append(sc)
- res = build.getResults()
- pageTitle = ('Builder "%s": %s' %
- (build.getBuilder().getName(), results.Results[res]))
-
- # Add information about the failing steps.
- failed_steps = []
- log_lines = []
- for s in build.getSteps():
- res = s.getResults()[0]
- if res not in (results.SUCCESS, results.WARNINGS,
- results.SKIPPED):
- failed_steps.append(s.getName())
-
- # Add the last 30 lines of each log.
- for log in s.getLogs():
- log_lines.append('Last lines of build log "%s":' %
- log.getName())
- log_lines.append([])
- try:
- logdata = log.getText()
- except IOError:
- # Probably the log file has been removed
- logdata ='** log file not available **'
- unilist = list()
- for line in logdata.split('\n')[-30:]:
- unilist.append(unicode(line,'utf-8'))
- log_lines.extend(unilist)
-
- bc = {}
- bc['sources'] = src_cxts
- bc['date'] = rfc822_time(finishedTime)
- bc['summary_link'] = ('%sbuilders/%s' %
- (self.link,
- build.getBuilder().getName()))
- bc['name'] = build.getBuilder().getName()
- bc['number'] = build.getNumber()
- bc['responsible_users'] = build.getResponsibleUsers()
- bc['failed_steps'] = failed_steps
- bc['pageTitle'] = pageTitle
- bc['link'] = link
- bc['log_lines'] = log_lines
-
- if finishedTime is not None:
- bc['rfc822_pubdate'] = rfc822_time(finishedTime)
- bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
- finishedTime)
-
- # Every RSS/Atom item must have a globally unique ID
- guid = ('tag:%s@%s,%s:%s' %
- (self.user, self.hostname,
- time.strftime("%Y-%m-%d", finishedTime),
- time.strftime("%Y%m%d%H%M%S", finishedTime)))
- bc['guid'] = guid
-
- build_cxts.append(bc)
-
- pageTitle = self.pageTitle
- if not pageTitle:
- pageTitle = 'Build status of %s' % self.title
-
- cxt = {}
- cxt['pageTitle'] = pageTitle
- cxt['title_url'] = self.link
- cxt['title'] = self.title
- cxt['language'] = self.language
- cxt['description'] = self.description
- if self.pubdate is not None:
- cxt['rfc822_pubdate'] = rfc822_time( self.pubdate)
- cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ",
- self.pubdate)
-
- cxt['builds'] = build_cxts
- template = request.site.buildbot_service.templates.get_template(self.template_file)
- return template.render(**cxt).encode('utf-8').strip()
-
-class Rss20StatusResource(FeedResource):
- # contentType = 'application/rss+xml' (browser dependent)
- template_file = 'feed_rss20.xml'
-
- def __init__(self, status, categories=None, pageTitle=None):
- FeedResource.__init__(self, status, categories, pageTitle)
-
-class Atom10StatusResource(FeedResource):
- # contentType = 'application/atom+xml' (browser dependent)
- template_file = 'feed_atom10.xml'
-
- def __init__(self, status, categories=None, pageTitle=None):
- FeedResource.__init__(self, status, categories, pageTitle)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg
deleted file mode 100644
index 6c2e5ddf..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg
+++ /dev/null
Binary files differ
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css
deleted file mode 100644
index d769f73a..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css
+++ /dev/null
@@ -1,604 +0,0 @@
-body.interface {
- margin-left: 30px;
- margin-right: 30px;
- margin-top: 20px;
- margin-bottom: 50px;
- padding: 0;
- background: url(bg_gradient.jpg) repeat-x;
- font-family: Verdana, sans-serif;
- font-size: 10px;
- background-color: #fff;
- color: #333;
-}
-
-.auth {
-position:absolute;
-top:5px;
-right:40px;
-}
-
-.alert {
- color: #c30000;
- background-color: #f2dcdc;
- padding: 5px 5px 5px 25px;
- margin-bottom: 20px;
- border-top:1px solid #ccc;
- border-bottom:1px solid #ccc;
- border-color: #c30000;
- font-size: 20px;
-}
-a:link,a:visited,a:active {
- color: #444;
-}
-
-table {
- border-spacing: 1px 1px;
-}
-
-table td {
- padding: 3px 4px 3px 4px;
- text-align: center;
-}
-
-.Project {
- min-width: 6em;
-}
-
-.LastBuild,.Activity {
- padding: 0 0 0 4px;
-}
-
-.LastBuild,.Activity,.Builder,.BuildStep {
- min-width: 5em;
-}
-
-/* Chromium Specific styles */
-div.BuildResultInfo {
- color: #444;
-}
-
-div.Announcement {
- margin-bottom: 1em;
-}
-
-div.Announcement>a:hover {
- color: black;
-}
-
-div.Announcement>div.Notice {
- background-color: #afdaff;
- padding: 0.5em;
- font-size: 16px;
- text-align: center;
-}
-
-div.Announcement>div.Open {
- border: 3px solid #8fdf5f;
- padding: 0.5em;
- font-size: 16px;
- text-align: center;
-}
-
-div.Announcement>div.Closed {
- border: 5px solid #e98080;
- padding: 0.5em;
- font-size: 24px;
- font-weight: bold;
- text-align: center;
-}
-
-td.Time {
- color: #000;
- border-bottom: 1px solid #aaa;
- background-color: #eee;
-}
-
-td.Activity,td.Change,td.Builder {
- color: #333333;
- background-color: #CCCCCC;
-}
-
-td.Change {
- border-radius: 5px;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
-}
-
-td.Event {
- color: #777;
- background-color: #ddd;
- border-radius: 5px;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
-}
-
-td.Activity {
- border-top-left-radius: 10px;
- -webkit-border-top-left-radius: 10px;
- -moz-border-radius-topleft: 10px;
- min-height: 20px;
- padding: 2px 0 2px 0;
-}
-
-td.idle,td.waiting,td.offline,td.building {
- border-top-left-radius: 0px;
- -webkit-border-top-left-radius: 0px;
- -moz-border-radius-topleft: 0px;
-}
-
-.LastBuild {
- border-top-left-radius: 5px;
- -webkit-border-top-left-radius: 5px;
- -moz-border-radius-topleft: 5px;
- border-top-right-radius: 5px;
- -webkit-border-top-right-radius: 5px;
- -moz-border-radius-topright: 5px;
-}
-
-/* Console view styles */
-td.DevRev {
- padding: 4px 8px 4px 8px;
- color: #333333;
- border-top-left-radius: 5px;
- -webkit-border-top-left-radius: 5px;
- -moz-border-radius-topleft: 5px;
- background-color: #eee;
- width: 1%;
-}
-
-td.DevRevCollapse {
- border-bottom-left-radius: 5px;
- -webkit-border-bottom-left-radius: 5px;
- -moz-border-radius-bottomleft: 5px;
-}
-
-td.DevName {
- padding: 4px 8px 4px 8px;
- color: #333333;
- background-color: #eee;
- width: 1%;
- text-align: left;
-}
-
-td.DevStatus {
- padding: 4px 4px 4px 4px;
- color: #333333;
- background-color: #eee;
-}
-
-td.DevSlave {
- padding: 4px 4px 4px 4px;
- color: #333333;
- background-color: #eee;
-}
-
-td.first {
- border-top-left-radius: 5px;
- -webkit-border-top-left-radius: 5px;
- -moz-border-radius-topleft: 5px;
-}
-
-td.last {
- border-top-right-radius: 5px;
- -webkit-border-top-right-radius: 5px;
- -moz-border-radius-topright: 5px;
-}
-
-td.DevStatusCategory {
- border-radius: 5px;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
- border-width: 1px;
- border-style: solid;
-}
-
-td.DevStatusCollapse {
- border-bottom-right-radius: 5px;
- -webkit-border-bottom-right-radius: 5px;
- -moz-border-radius-bottomright: 5px;
-}
-
-td.DevDetails {
- font-weight: normal;
- padding: 8px 8px 8px 8px;
- color: #333333;
- background-color: #eee;
- text-align: left;
-}
-
-td.DevDetails li a {
- padding-right: 5px;
-}
-
-td.DevComment {
- font-weight: normal;
- padding: 8px 8px 8px 8px;
- color: #333333;
- background-color: #eee;
- text-align: left;
-}
-
-td.DevBottom {
- border-bottom-right-radius: 5px;
- -webkit-border-bottom-right-radius: 5px;
- -moz-border-radius-bottomright: 5px;
- border-bottom-left-radius: 5px;
- -webkit-border-bottom-left-radius: 5px;
- -moz-border-radius-bottomleft: 5px;
-}
-
-td.Alt {
- background-color: #ddd;
-}
-
-.legend {
- border-radius: 5px !important;
- -webkit-border-radius: 5px !important;
- -moz-border-radius: 5px !important;
- width: 100px;
- max-width: 100px;
- text-align: center;
- padding: 2px 2px 2px 2px;
- height: 14px;
- white-space: nowrap;
-}
-
-.DevStatusBox {
- text-align: center;
- height: 20px;
- padding: 0 2px;
- line-height: 0;
- white-space: nowrap;
-}
-
-.DevStatusBox a {
- opacity: 0.85;
- border-width: 1px;
- border-style: solid;
- border-radius: 4px;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- display: block;
- width: 90%;
- height: 20px;
- line-height: 20px;
- margin-left: auto;
- margin-right: auto;
-}
-
-.DevSlaveBox {
- text-align: center;
- height: 10px;
- padding: 0 2px;
- line-height: 0;
- white-space: nowrap;
-}
-
-.DevSlaveBox a {
- opacity: 0.85;
- border-width: 1px;
- border-style: solid;
- border-radius: 4px;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- display: block;
- width: 90%;
- height: 10px;
- line-height: 20px;
- margin-left: auto;
- margin-right: auto;
-}
-
-a.noround {
- border-radius: 0px;
- -webkit-border-radius: 0px;
- -moz-border-radius: 0px;
- position: relative;
- margin-top: -8px;
- margin-bottom: -8px;
- height: 36px;
- border-top-width: 0;
- border-bottom-width: 0;
-}
-
-a.begin {
- border-top-width: 1px;
- position: relative;
- margin-top: 0px;
- margin-bottom: -7px;
- height: 27px;
- border-top-left-radius: 4px;
- -webkit-border-top-left-radius: 4px;
- -moz-border-radius-topleft: 4px;
- border-top-right-radius: 4px;
- -webkit-border-top-right-radius: 4px;
- -moz-border-radius-topright: 4px;
-}
-
-a.end {
- border-bottom-width: 1px;
- position: relative;
- margin-top: -7px;
- margin-bottom: 0px;
- height: 27px;
- border-bottom-left-radius: 4px;
- -webkit-border-bottom-left-radius: 4px;
- -moz-border-radius-bottomleft: 4px;
- border-bottom-right-radius: 4px;
- -webkit-border-bottom-right-radius: 4px;
- -moz-border-radius-bottomright: 4px;
-}
-
-.center_align {
- text-align: center;
-}
-
-.right_align {
- text-align: right;
-}
-
-.left_align {
- text-align: left;
-}
-
-div.BuildWaterfall {
- border-radius: 7px;
- -webkit-border-radius: 7px;
- -moz-border-radius: 7px;
- position: absolute;
- left: 0px;
- top: 0px;
- background-color: #FFFFFF;
- padding: 4px 4px 4px 4px;
- float: left;
- display: none;
- border-width: 1px;
- border-style: solid;
-}
-
-/* LastBuild, BuildStep states */
-.success {
- color: #000;
- background-color: #8d4;
- border-color: #4F8530;
-}
-
-.failure {
- color: #000;
- background-color: #e88;
- border-color: #A77272;
-}
-
-.failure-again {
- color: #000;
- background-color: #eA9;
- border-color: #A77272;
-}
-
-.warnings {
- color: #FFFFFF;
- background-color: #fa3;
- border-color: #C29D46;
-}
-
-.skipped {
- color: #000;
- background: #AADDEE;
- border-color: #AADDEE;
-}
-
-.exception,.retry {
- color: #FFFFFF;
- background-color: #c6c;
- border-color: #ACA0B3;
-}
-
-.start {
- color: #000;
- background-color: #ccc;
- border-color: #ccc;
-}
-
-.running,.waiting,td.building {
- color: #000;
- background-color: #fd3;
- border-color: #C5C56D;
-}
-
-.paused {
- color: #FFFFFF;
- background-color: #8080FF;
- border-color: #dddddd;
-}
-
-.offline,td.offline {
- color: #FFFFFF;
- background-color: #777777;
- border-color: #dddddd;
-}
-
-
-.start {
- border-bottom-left-radius: 10px;
- -webkit-border-bottom-left-radius: 10px;
- -moz-border-radius-bottomleft: 10px;
- border-bottom-right-radius: 10px;
- -webkit-border-bottom-right-radius: 10px;
- -moz-border-radius-bottomright: 10px;
-}
-
-.notstarted {
- border-width: 1px;
- border-style: solid;
- border-color: #aaa;
- background-color: #fff;
-}
-
-.closed {
- background-color: #ff0000;
-}
-
-.closed .large {
- font-size: 1.5em;
- font-weight: bolder;
-}
-
-td.Project a:hover,td.start a:hover {
- color: #000;
-}
-
-.mini-box {
- text-align: center;
- height: 20px;
- padding: 0 2px;
- line-height: 0;
- white-space: nowrap;
-}
-
-.mini-box a {
- border-radius: 0;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- display: block;
- width: 100%;
- height: 20px;
- line-height: 20px;
- margin-top: -30px;
-}
-
-.mini-closed {
- -box-sizing: border-box;
- -webkit-box-sizing: border-box;
- border: 4px solid red;
-}
-
-/* grid styles */
-table.Grid {
- border-collapse: collapse;
-}
-
-table.Grid tr td {
- padding: 0.2em;
- margin: 0px;
- text-align: center;
-}
-
-table.Grid tr td.title {
- font-size: 90%;
- border-right: 1px gray solid;
- border-bottom: 1px gray solid;
-}
-
-table.Grid tr td.sourcestamp {
- font-size: 90%;
-}
-
-table.Grid tr td.builder {
- text-align: right;
- font-size: 90%;
-}
-
-table.Grid tr td.build {
- border: 1px gray solid;
-}
-
-/* column container */
-div.column {
- margin: 0 2em 2em 0;
- float: left;
-}
-
-/* info tables */
-table.info {
- border-spacing: 1px;
-}
-
-table.info td {
- padding: 0.1em 1em 0.1em 1em;
- text-align: center;
-}
-
-table.info th {
- padding: 0.2em 1.5em 0.2em 1.5em;
- text-align: center;
-}
-
-table.info td.left {
- text-align: left
-}
-
-.alt {
- background-color: #f6f6f6;
-}
-
-li {
- padding: 0.1em 1em 0.1em 1em;
-}
-
-.result {
- padding: 0.3em 1em 0.3em 1em;
-}
-
-/* log view */
-.log * {
- vlink: #800080;
- font-family: "Courier New", courier, monotype, monospace;
-}
-
-span.stdout {
- color: black;
-}
-
-span.stderr {
- color: red;
-}
-
-span.header {
- color: blue;
-}
-
-/* revision & email */
-.revision .full {
- display: none;
-}
-
-.user .email {
- display: none;
-}
-
-pre {
- white-space: pre-wrap;
-}
-
-/* change comments (use regular colors here) */
-pre.comments>a:link,pre.comments>a:visited {
- color: blue;
-}
-
-pre.comments>a:active {
- color: purple;
-}
-
-form.command_forcebuild {
- border-top: 1px solid black;
- padding: .5em;
- margin: .5em;
-}
-
-form.command_forcebuild > .row {
- border-top: 1px dotted gray;
- padding: .5em 0;
-}
-
-form.command_forcebuild .force-textarea > .label {
- display: block;
-}
-
-form.command_forcebuild .force-nested > .label {
- font-weight: bold;
- display: list-item;
-}
-
-form.command_forcebuild .force-any .force-text {
- display: inline;
-}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico
deleted file mode 100644
index b0b0845d..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt
deleted file mode 100644
index 7b5fc8da..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-User-agent: *
-Disallow: /waterfall
-Disallow: /builders
-Disallow: /changes
-Disallow: /buildslaves
-Disallow: /schedulers
-Disallow: /one_line_per_build
-Disallow: /builders
-Disallow: /grid
-Disallow: /tgrid
-Disallow: /json
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt
deleted file mode 100644
index 78201578..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is the directory to place customized templates for webstatus.
-
-You can find the sources for the templates used in:
-buildbot/status/web/templates
-
-You can copy any of those files to this directory, make changes, and buildbot will automatically
-use your modified templates.
-
-Also of note is that you will not need to restart/reconfig buildbot master to have these changes take effect.
-
-The syntax of the templates is Jinja2:
-http://jinja.pocoo.org/ \ No newline at end of file
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py
deleted file mode 100644
index dc4fbd62..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py
+++ /dev/null
@@ -1,341 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from twisted.internet import defer
-from buildbot.status.web.base import HtmlResource
-from buildbot.status.web.base import build_get_class, path_to_builder, path_to_build
-from buildbot.sourcestamp import SourceStamp
-
-class ANYBRANCH: pass # a flag value, used below
-
-class GridStatusMixin(object):
- def getPageTitle(self, request):
- status = self.getStatus(request)
- p = status.getTitle()
- if p:
- return "BuildBot: %s" % p
- else:
- return "BuildBot"
-
- # handle reloads through an http header
- # TODO: send this as a real header, rather than a tag
- def get_reload_time(self, request):
- if "reload" in request.args:
- try:
- reload_time = int(request.args["reload"][0])
- return max(reload_time, 15)
- except ValueError:
- pass
- return None
-
- def build_cxt(self, request, build):
- if not build:
- return {}
-
- if build.isFinished():
- # get the text and annotate the first line with a link
- text = build.getText()
- if not text: text = [ "(no information)" ]
- if text == [ "build", "successful" ]: text = [ "OK" ]
- else:
- text = [ 'building' ]
-
- name = build.getBuilder().getName()
-
- cxt = {}
- cxt['name'] = name
- cxt['got_revision'] = build.getProperty("got_revision")
- cxt['DEST'] = build.getProperty("DEST")
- cxt['url'] = path_to_build(request, build)
- cxt['text'] = text
- cxt['class'] = build_get_class(build)
-
- if build.getProperty("repourl_poky"):
- if build.getProperty("repourl_poky") == "git://git.yoctoproject.org/poky":
- cxt['repository'] = "poky"
- cxt['cgiturl'] = "http://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?h="
- elif "git://git.yoctoproject.org/poky-contrib" in build.getProperty("repourl_poky"):
- cxt['repository'] = "poky-contrib"
- cxt['cgiturl'] = "http://git.yoctoproject.org/cgit/cgit.cgi/poky-contrib/commit/?h="
- else:
- cxt['repository'] = build.getProperty("repourl_poky")
-
- if build.getProperty("branch_poky"):
- if build.getProperty("branch_poky") == "stage/master_under_test":
- cxt['branchshortname']="mut"
- else:
- cxt['branchshortname']=build.getProperty("branch_poky")
- cxt['branch'] = build.getProperty("branch_poky")
- if 'cgiturl' in cxt and 'got_revision' in cxt and cxt['cgiturl'] is not None and cxt['got_revision'] is not None:
- cxt['cgiturl'] = cxt['cgiturl'] + build.getProperty("branch_poky") + "&id=" + cxt['got_revision']
- if build.getProperty("custom_release_name_nightly"):
- cxt['release_name'] = build.getProperty("custom_release_name_nightly")
- else:
- cxt['commit_desc'] = build.getProperty("commit-description")
-
- return cxt
-
- @defer.inlineCallbacks
- def builder_cxt(self, request, builder):
- state, builds = builder.getState()
-
- # look for upcoming builds. We say the state is "waiting" if the
- # builder is otherwise idle and there is a scheduler which tells us a
- # build will be performed some time in the near future. TODO: this
- # functionality used to be in BuilderStatus.. maybe this code should
- # be merged back into it.
- upcoming = []
- builderName = builder.getName()
- for s in self.getStatus(request).getSchedulers():
- if builderName in s.listBuilderNames():
- upcoming.extend(s.getPendingBuildTimes())
- if state == "idle" and upcoming:
- state = "waiting"
-
- n_pending = len((yield builder.getPendingBuildRequestStatuses()))
-
- cxt = { 'url': path_to_builder(request, builder),
- 'name': builder.getName(),
- 'state': state,
- 'n_pending': n_pending }
-
- defer.returnValue(cxt)
-
- def getSourceStampKey(self, sourcestamps):
- """Given two source stamps, we want to assign them to the same row if
- they are the same version of code, even if they differ in minor detail.
-
- This function returns an appropriate comparison key for that.
- """
- # TODO: Maybe order sourcestamps in key by codebases names?
- return tuple([(ss.branch, ss.revision, ss.patch) for ss in sourcestamps])
-
- def clearRecentBuildsCache(self):
- self.__recentBuildsCache__ = {}
-
- def getRecentBuilds(self, builder, numBuilds, branch):
- cache = getattr(self, '__recentBuildsCache__', {})
- key = (builder.getName(), branch, numBuilds)
- try:
- return cache[key]
- except KeyError:
- # cache miss, get the value and store it in the cache
- result = [b for b in self.__getRecentBuilds(builder, numBuilds, branch)]
- cache[key] = result
- return result
-
- def __getRecentBuilds(self, builder, numBuilds, branch):
- """
- get a list of most recent builds on given builder
- """
- build = builder.getBuild(-1)
- num = 0
- while build and num < numBuilds:
- start = build.getTimes()[0]
- #TODO: support multiple sourcestamps
- ss = build.getSourceStamps(absolute=True)[0]
-
- okay_build = True
-
- # skip un-started builds
- if not start:
- okay_build = False
-
- # skip non-matching branches
- if branch != ANYBRANCH and ss.branch != branch:
- okay_build = False
-
- if okay_build:
- num += 1
- yield build
-
- build = build.getPreviousBuild()
- return
-
- def getRecentSourcestamps(self, status, numBuilds, categories, branch):
- """
- get a list of the most recent NUMBUILDS SourceStamp tuples, sorted
- by the earliest start we've seen for them
- """
- # TODO: use baseweb's getLastNBuilds?
- sourcestamps = { } # { ss-tuple : earliest time }
- for bn in status.getBuilderNames():
- builder = status.getBuilder(bn)
- if categories and builder.category not in categories:
- continue
- for build in self.getRecentBuilds(builder, numBuilds, branch):
- ss = build.getSourceStamps(absolute=True)
- key = self.getSourceStampKey(ss)
- start = min(x for x in build.getTimes() if x is not None)
- if key not in sourcestamps or sourcestamps[key][1] > start:
- sourcestamps[key] = (ss, start)
-
- # now sort those and take the NUMBUILDS most recent
- sourcestamps = sorted(sourcestamps.itervalues(), key = lambda stamp: stamp[1])
- sourcestamps = [stamp[0] for stamp in sourcestamps][-numBuilds:]
-
- return sourcestamps
-
-class GridStatusResource(HtmlResource, GridStatusMixin):
- # TODO: docs
- status = None
- changemaster = None
-
- @defer.inlineCallbacks
- def content(self, request, cxt):
- """This method builds the regular grid display.
- That is, build stamps across the top, build hosts down the left side
- """
-
- # get url parameters
- numBuilds = int(request.args.get("width", [5])[0])
- categories = request.args.get("category", [])
- branch = request.args.get("branch", [ANYBRANCH])[0]
- if branch == 'trunk': branch = None
-
- # and the data we want to render
- status = self.getStatus(request)
- stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch)
-
- cxt['refresh'] = self.get_reload_time(request)
-
- cxt.update({'categories': categories,
- 'branch': branch,
- 'ANYBRANCH': ANYBRANCH,
- 'stamps': [map(SourceStamp.asDict, sstamp) for sstamp in stamps],
- })
- sortedBuilderNames = sorted(status.getBuilderNames())
-
- cxt['builders'] = []
- cxt['build_triggers'] = build_triggers = []
- cxt['range'] = range(len(stamps))
-
- # For each sstamp we want to know the name of the builder which
- # triggered the builds and the buildid of that builder. We'll keep
- # that in a list of dicts which align with the stamps objects list.
- for _ in range(len(stamps)):
- build_triggers.append({'builder': '', 'id': ''})
-
- for bn in sortedBuilderNames:
- builds = [None] * len(stamps)
-
- builder = status.getBuilder(bn)
- if categories and builder.category not in categories:
- continue
-
- for build in self.getRecentBuilds(builder, numBuilds, branch):
- ss = build.getSourceStamps(absolute=True)
- key = self.getSourceStampKey(ss)
-
- for i, sstamp in enumerate(stamps):
- if key == self.getSourceStampKey(sstamp) and builds[i] is None:
- builds[i] = build
- if build_triggers[i].get('builder', None) != 'nightly':
- build_triggers[i]['builder'] = bn
- build_triggers[i]['id'] = str(build.getNumber())
-
- b = yield self.builder_cxt(request, builder)
-
- b['builds'] = []
- for build in builds:
- b['builds'].append(self.build_cxt(request, build))
-
- cxt['builders'].append(b)
-
- self.clearRecentBuildsCache()
- template = request.site.buildbot_service.templates.get_template("grid.html")
- defer.returnValue(template.render(**cxt))
-
-
-class TransposedGridStatusResource(HtmlResource, GridStatusMixin):
- # TODO: docs
- status = None
- changemaster = None
- default_rev_order = "desc"
-
- @defer.inlineCallbacks
- def content(self, request, cxt):
- """This method builds the transposed grid display.
- That is, build hosts across the top, build stamps down the left side
- """
-
- # get url parameters
- numBuilds = int(request.args.get("length", [5])[0])
- categories = request.args.get("category", [])
- branch = request.args.get("branch", [ANYBRANCH])[0]
- if branch == 'trunk': branch = None
-
- rev_order = request.args.get("rev_order", [self.default_rev_order])[0]
- if rev_order not in ["asc", "desc"]:
- rev_order = self.default_rev_order
-
- cxt['refresh'] = self.get_reload_time(request)
-
- # and the data we want to render
- status = self.getStatus(request)
- stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch)
-
- cxt.update({'categories': categories,
- 'branch': branch,
- 'ANYBRANCH': ANYBRANCH,
- 'stamps': [map(SourceStamp.asDict, sstamp) for sstamp in stamps],
- })
-
- sortedBuilderNames = sorted(status.getBuilderNames())
-
- cxt['sorted_builder_names'] = sortedBuilderNames
- cxt['builder_builds'] = builder_builds = []
- cxt['builders'] = builders = []
- cxt['build_triggers'] = build_triggers = []
- cxt['range'] = range(len(stamps))
- if rev_order == "desc":
- cxt['range'].reverse()
-
- # For each sstamp we want to know the name of the builder which
- # triggered the builds and the buildid of that builder. We'll keep
- # that in a list of dicts which align with the stamps objects list.
- for _ in range(len(stamps)):
- build_triggers.append({'builder': '', 'id': ''})
-
- for bn in sortedBuilderNames:
- builds = [None] * len(stamps)
-
- builder = status.getBuilder(bn)
- if categories and builder.category not in categories:
- continue
-
- for build in self.getRecentBuilds(builder, numBuilds, branch):
- #TODO: support multiple sourcestamps
- ss = build.getSourceStamps(absolute=True)
- key = self.getSourceStampKey(ss)
-
- for i, sstamp in enumerate(stamps):
- if key == self.getSourceStampKey(sstamp) and builds[i] is None:
- builds[i] = build
- # At this point we know that there's a build for the sstamp by this builder
- # update the corresponding dict in the build_triggers list with the builder
- # name and buildid unless 'nightly' is already set as the builder name.
- if build_triggers[i].get('builder', None) != 'nightly':
- build_triggers[i]['builder'] = bn
- build_triggers[i]['id'] = str(build.getNumber())
-
- b = yield self.builder_cxt(request, builder)
- builders.append(b)
-
- builder_builds.append(map(lambda b: self.build_cxt(request, b), builds))
-
- self.clearRecentBuildsCache()
- template = request.site.buildbot_service.templates.get_template('grid_transposed.html')
- defer.returnValue(template.render(**cxt))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py
deleted file mode 100644
index 00bcb6e3..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# test \ No newline at end of file
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py
deleted file mode 100644
index 3980e8f9..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-# code inspired/copied from contrib/github_buildbot
-# and inspired from code from the Chromium project
-# otherwise, Andrew Melo <andrew.melo@gmail.com> wrote the rest
-# but "the rest" is pretty minimal
-
-from buildbot.util import json
-
-def getChanges(request, options=None):
- """
- Consumes a naive build notification (the default for now)
- basically, set POST variables to match commit object parameters:
- revision, revlink, comments, branch, who, files, links
-
- files, links and properties will be de-json'd, the rest are interpreted as strings
- """
-
- def firstOrNothing( value ):
- """
- Small helper function to return the first value (if value is a list)
- or return the whole thing otherwise
- """
- if ( type(value) == type([])):
- return value[0]
- else:
- return value
-
- args = request.args
-
- # first, convert files, links and properties
- files = None
- if args.get('files'):
- files = json.loads( args.get('files')[0] )
- else:
- files = []
-
- properties = None
- if args.get('properties'):
- properties = json.loads( args.get('properties')[0] )
- else:
- properties = {}
-
- revision = firstOrNothing(args.get('revision'))
- when = firstOrNothing(args.get('when'))
- if when is not None:
- when = float(when)
- author = firstOrNothing(args.get('author'))
- if not author:
- author = firstOrNothing(args.get('who'))
- comments = firstOrNothing(args.get('comments'))
- isdir = firstOrNothing(args.get('isdir',0))
- branch = firstOrNothing(args.get('branch'))
- category = firstOrNothing(args.get('category'))
- revlink = firstOrNothing(args.get('revlink'))
- repository = firstOrNothing(args.get('repository'))
- project = firstOrNothing(args.get('project'))
-
- chdict = dict(author=author, files=files, comments=comments,
- isdir=isdir, revision=revision, when=when,
- branch=branch, category=category, revlink=revlink,
- properties=properties, repository=repository,
- project=project)
- return ([ chdict ], None)
-
-
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py
deleted file mode 100644
index 2ff05f12..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-#!/usr/bin/env python
-"""
-github_buildbot.py is based on git_buildbot.py
-
-github_buildbot.py will determine the repository information from the JSON
-HTTP POST it receives from github.com and build the appropriate repository.
-If your github repository is private, you must add a ssh key to the github
-repository for the user who initiated the build on the buildslave.
-
-"""
-
-import re
-import datetime
-from twisted.python import log
-import calendar
-
-try:
- import json
- assert json
-except ImportError:
- import simplejson as json
-
-# python is silly about how it handles timezones
-class fixedOffset(datetime.tzinfo):
- """
- fixed offset timezone
- """
- def __init__(self, minutes, hours, offsetSign = 1):
- self.minutes = int(minutes) * offsetSign
- self.hours = int(hours) * offsetSign
- self.offset = datetime.timedelta(minutes = self.minutes,
- hours = self.hours)
-
- def utcoffset(self, dt):
- return self.offset
-
- def dst(self, dt):
- return datetime.timedelta(0)
-
-def convertTime(myTestTimestamp):
- #"1970-01-01T00:00:00+00:00"
- matcher = re.compile(r'(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)([-+])(\d\d):(\d\d)')
- result = matcher.match(myTestTimestamp)
- (year, month, day, hour, minute, second, offsetsign, houroffset, minoffset) = \
- result.groups()
- if offsetsign == '+':
- offsetsign = 1
- else:
- offsetsign = -1
-
- offsetTimezone = fixedOffset( minoffset, houroffset, offsetsign )
- myDatetime = datetime.datetime( int(year),
- int(month),
- int(day),
- int(hour),
- int(minute),
- int(second),
- 0,
- offsetTimezone)
- return calendar.timegm( myDatetime.utctimetuple() )
-
-def getChanges(request, options = None):
- """
- Reponds only to POST events and starts the build process
-
- :arguments:
- request
- the http request object
- """
- payload = json.loads(request.args['payload'][0])
- user = payload['repository']['owner']['name']
- repo = payload['repository']['name']
- repo_url = payload['repository']['url']
- project = request.args.get('project', None)
- if project:
- project = project[0]
- elif project is None:
- project = ''
- # This field is unused:
- #private = payload['repository']['private']
- changes = process_change(payload, user, repo, repo_url, project)
- log.msg("Received %s changes from github" % len(changes))
- return (changes, 'git')
-
-def process_change(payload, user, repo, repo_url, project):
- """
- Consumes the JSON as a python object and actually starts the build.
-
- :arguments:
- payload
- Python Object that represents the JSON sent by GitHub Service
- Hook.
- """
- changes = []
- newrev = payload['after']
- refname = payload['ref']
-
- # We only care about regular heads, i.e. branches
- match = re.match(r"^refs\/heads\/(.+)$", refname)
- if not match:
- log.msg("Ignoring refname `%s': Not a branch" % refname)
- return []
-
- branch = match.group(1)
- if re.match(r"^0*$", newrev):
- log.msg("Branch `%s' deleted, ignoring" % branch)
- return []
- else:
- for commit in payload['commits']:
- files = []
- if 'added' in commit:
- files.extend(commit['added'])
- if 'modified' in commit:
- files.extend(commit['modified'])
- if 'removed' in commit:
- files.extend(commit['removed'])
- when = convertTime( commit['timestamp'])
- log.msg("New revision: %s" % commit['id'][:8])
- chdict = dict(
- who = commit['author']['name']
- + " <" + commit['author']['email'] + ">",
- files = files,
- comments = commit['message'],
- revision = commit['id'],
- when = when,
- branch = branch,
- revlink = commit['url'],
- repository = repo_url,
- project = project)
- changes.append(chdict)
- return changes
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py
deleted file mode 100644
index f40cf174..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2011, Louis Opter <kalessin@kalessin.fr>
-
-# Quite inspired from the github hook.
-
-import hmac
-from twisted.python import log
-from buildbot.util import json
-
-class GoogleCodeAuthFailed(Exception):
- pass
-
-class Payload(object):
- def __init__(self, headers, body, branch):
- self._auth_code = headers['Google-Code-Project-Hosting-Hook-Hmac']
- self._body = body # we need to save it if we want to authenticate it
- self._branch = branch
-
- payload = json.loads(body)
- self.project = payload['project_name']
- self.repository = payload['repository_path']
- self.revisions = payload['revisions']
- self.revision_count = payload['revision_count']
-
- def authenticate(self, secret_key):
- m = hmac.new(secret_key)
- m.update(self._body)
- digest = m.hexdigest()
- return digest == self._auth_code
-
- def changes(self):
- changes = []
-
- for r in self.revisions:
- files = set()
- files.update(r['added'])
- files.update(r['modified'])
- files.update(r['removed'])
- changes.append(dict(
- author=r['author'],
- files=list(files),
- comments=r['message'],
- revision=r['revision'],
- when=r['timestamp'],
- # Let's hope Google add the branch one day:
- branch=r.get('branch', self._branch),
- revlink=r['url'],
- repository=self.repository,
- project=self.project
- ))
-
- return changes
-
-def getChanges(request, options=None):
- headers = request.received_headers
- body = request.content.getvalue()
-
- # Instantiate a Payload object: this will parse the body, get the
- # authentication code from the headers and remember the branch picked
- # up by the user (Google Code doesn't send on which branch the changes
- # were made)
- payload = Payload(headers, body, options.get('branch', 'default'))
-
- if 'secret_key' in options:
- if not payload.authenticate(options['secret_key']):
- raise GoogleCodeAuthFailed()
- else:
- log.msg("Missing secret_key in the Google Code WebHook options: "
- "cannot authenticate the request!")
-
- log.msg('Received %d changes from Google Code' %
- (payload.revision_count,))
- changes = payload.changes()
-
- return changes, 'Google Code'
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py
deleted file mode 100644
index 1ac29a4f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-# This change hook allows GitHub or a hand crafted curl inovcation to "knock on
-# the door" and trigger a change source to poll.
-
-from buildbot.changes.base import PollingChangeSource
-
-
-def getChanges(req, options=None):
- change_svc = req.site.buildbot_service.master.change_svc
- poll_all = not "poller" in req.args
-
- allow_all = True
- allowed = []
- if isinstance(options, dict) and "allowed" in options:
- allow_all = False
- allowed = options["allowed"]
-
- pollers = []
-
- for source in change_svc:
- if not isinstance(source, PollingChangeSource):
- continue
- if not hasattr(source, "name"):
- continue
- if not poll_all and not source.name in req.args['poller']:
- continue
- if not allow_all and not source.name in allowed:
- continue
- pollers.append(source)
-
- if not poll_all:
- missing = set(req.args['poller']) - set(s.name for s in pollers)
- if missing:
- raise ValueError("Could not find pollers: %s" % ",".join(missing))
-
- for p in pollers:
- p.doPoll()
-
- return [], None
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py
deleted file mode 100644
index d7da8111..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from zope.interface import implements
-from twisted.python import components
-from twisted.spread import pb
-from twisted.web import server
-from twisted.web.resource import Resource, NoResource
-
-from buildbot import interfaces
-from buildbot.status import logfile
-from buildbot.status.web.base import IHTMLLog, HtmlResource, path_to_root
-
-class ChunkConsumer:
- implements(interfaces.IStatusLogConsumer)
-
- def __init__(self, original, textlog):
- self.original = original
- self.textlog = textlog
- def registerProducer(self, producer, streaming):
- self.producer = producer
- self.original.registerProducer(producer, streaming)
- def unregisterProducer(self):
- self.original.unregisterProducer()
- def writeChunk(self, chunk):
- formatted = self.textlog.content([chunk])
- try:
- if isinstance(formatted, unicode):
- formatted = formatted.encode('utf-8')
- self.original.write(formatted)
- except pb.DeadReferenceError:
- self.producing.stopProducing()
- def finish(self):
- self.textlog.finished()
-
-
-# /builders/$builder/builds/$buildnum/steps/$stepname/logs/$logname
-class TextLog(Resource):
- # a new instance of this Resource is created for each client who views
- # it, so we can afford to track the request in the Resource.
- implements(IHTMLLog)
-
- asText = False
- subscribed = False
-
- def __init__(self, original):
- Resource.__init__(self)
- self.original = original
-
- def getChild(self, path, req):
- if path == "text":
- self.asText = True
- return self
- return Resource.getChild(self, path, req)
-
- def content(self, entries):
- html_entries = []
- text_data = ''
- for type, entry in entries:
- if type >= len(logfile.ChunkTypes) or type < 0:
- # non-std channel, don't display
- continue
-
- is_header = type == logfile.HEADER
-
- if not self.asText:
- # jinja only works with unicode, or pure ascii, so assume utf-8 in logs
- if not isinstance(entry, unicode):
- entry = unicode(entry, 'utf-8', 'replace')
- html_entries.append(dict(type = logfile.ChunkTypes[type],
- text = entry,
- is_header = is_header))
- elif not is_header:
- text_data += entry
-
- if self.asText:
- return text_data
- else:
- return self.template.module.chunks(html_entries)
-
- def render_HEAD(self, req):
- self._setContentType(req)
-
- # vague approximation, ignores markup
- req.setHeader("content-length", self.original.length)
- return ''
-
- def render_GET(self, req):
- self._setContentType(req)
- self.req = req
-
- if self.original.isFinished():
- req.setHeader("Cache-Control", "max-age=604800")
- else:
- req.setHeader("Cache-Control", "no-cache")
-
- if not self.asText:
- self.template = req.site.buildbot_service.templates.get_template("logs.html")
-
- data = self.template.module.page_header(
- pageTitle = "Log File contents",
- texturl = req.childLink("text"),
- path_to_root = path_to_root(req))
- data = data.encode('utf-8')
- req.write(data)
-
- self.original.subscribeConsumer(ChunkConsumer(req, self))
- return server.NOT_DONE_YET
-
- def _setContentType(self, req):
- if self.asText:
- req.setHeader("content-type", "text/plain; charset=utf-8")
- else:
- req.setHeader("content-type", "text/html; charset=utf-8")
-
- def finished(self):
- if not self.req:
- return
- try:
- if not self.asText:
- data = self.template.module.page_footer()
- data = data.encode('utf-8')
- self.req.write(data)
- self.req.finish()
- except pb.DeadReferenceError:
- pass
- # break the cycle, the Request's .notifications list includes the
- # Deferred (from req.notifyFinish) that's pointing at us.
- self.req = None
-
- # release template
- self.template = None
-
-components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog)
-
-
-class HTMLLog(Resource):
- implements(IHTMLLog)
-
- def __init__(self, original):
- Resource.__init__(self)
- self.original = original
-
- def render(self, request):
- request.setHeader("content-type", "text/html")
- return self.original.html
-
-components.registerAdapter(HTMLLog, logfile.HTMLLogFile, IHTMLLog)
-
-
-class LogsResource(HtmlResource):
- addSlash = True
-
- def __init__(self, step_status):
- HtmlResource.__init__(self)
- self.step_status = step_status
-
- def getChild(self, path, req):
- for log in self.step_status.getLogs():
- if path == log.getName():
- if log.hasContents():
- return IHTMLLog(interfaces.IStatusLog(log))
- return NoResource("Empty Log '%s'" % path)
- return HtmlResource.getChild(self, path, req)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py
deleted file mode 100644
index 1bfd647c..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from buildbot.status.web.base import HtmlResource, BuildLineMixin, map_branches
-
-# /one_line_per_build
-# accepts builder=, branch=, numbuilds=, reload=
-class OneLinePerBuild(HtmlResource, BuildLineMixin):
- """This shows one line per build, combining all builders together. Useful
- query arguments:
-
- numbuilds=: how many lines to display
- builder=: show only builds for this builder. Multiple builder= arguments
- can be used to see builds from any builder in the set.
- reload=: reload the page after this many seconds
- """
-
- pageTitle = "Recent Builds"
-
- def __init__(self, numbuilds=20):
- HtmlResource.__init__(self)
- self.numbuilds = numbuilds
-
- def getChild(self, path, req):
- status = self.getStatus(req)
- builder = status.getBuilder(path)
- return OneLinePerBuildOneBuilder(builder, numbuilds=self.numbuilds)
-
- def get_reload_time(self, request):
- if "reload" in request.args:
- try:
- reload_time = int(request.args["reload"][0])
- return max(reload_time, 15)
- except ValueError:
- pass
- return None
-
- def content(self, req, cxt):
- status = self.getStatus(req)
- numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0])
- builders = req.args.get("builder", [])
- branches = [b for b in req.args.get("branch", []) if b]
-
- g = status.generateFinishedBuilds(builders, map_branches(branches),
- numbuilds, max_search=numbuilds)
-
- cxt['refresh'] = self.get_reload_time(req)
- cxt['num_builds'] = numbuilds
- cxt['branches'] = branches
- cxt['builders'] = builders
-
- builds = cxt['builds'] = []
- for build in g:
- builds.append(self.get_line_values(req, build))
-
- cxt['authz'] = self.getAuthz(req)
-
- # get information on the builders - mostly just a count
- building = 0
- online = 0
- for bn in builders:
- builder = status.getBuilder(bn)
- builder_status = builder.getState()[0]
- if builder_status == "building":
- building += 1
- online += 1
- elif builder_status != "offline":
- online += 1
-
- cxt['num_online'] = online
- cxt['num_building'] = building
-
- template = req.site.buildbot_service.templates.get_template('onelineperbuild.html')
- return template.render(**cxt)
-
-
-
-# /one_line_per_build/$BUILDERNAME
-# accepts branch=, numbuilds=
-
-class OneLinePerBuildOneBuilder(HtmlResource, BuildLineMixin):
- def __init__(self, builder, numbuilds=20):
- HtmlResource.__init__(self)
- self.builder = builder
- self.builder_name = builder.getName()
- self.numbuilds = numbuilds
- self.pageTitle = "Recent Builds of %s" % self.builder_name
-
- def content(self, req, cxt):
- numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0])
- branches = [b for b in req.args.get("branch", []) if b]
-
- # walk backwards through all builds of a single builder
- g = self.builder.generateFinishedBuilds(map_branches(branches),
- numbuilds)
-
- cxt['builds'] = map(lambda b: self.get_line_values(req, b), g)
- cxt.update(dict(num_builds=numbuilds,
- builder_name=self.builder_name,
- branches=branches))
-
- template = req.site.buildbot_service.templates.get_template('onelineperbuildonebuilder.html')
- return template.render(**cxt)
-
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py
deleted file mode 100644
index 01a926ed..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-from twisted.web.util import redirectTo
-from twisted.internet import defer
-
-from buildbot.status.web.base import HtmlResource, path_to_authzfail
-from buildbot.util.eventual import eventually
-
-class RootPage(HtmlResource):
- pageTitle = "Buildbot"
-
- @defer.inlineCallbacks
- def content(self, request, cxt):
- status = self.getStatus(request)
-
- res = yield self.getAuthz(request).actionAllowed("cleanShutdown",
- request)
-
- if request.path == '/shutdown':
- if res:
- eventually(status.cleanShutdown)
- defer.returnValue(redirectTo("/", request))
- return
- else:
- defer.returnValue(
- redirectTo(path_to_authzfail(request), request))
- return
- elif request.path == '/cancel_shutdown':
- if res:
- eventually(status.cancelCleanShutdown)
- defer.returnValue(redirectTo("/", request))
- return
- else:
- defer.returnValue(
- redirectTo(path_to_authzfail(request), request))
- return
-
- cxt.update(
- shutting_down = status.shuttingDown,
- shutdown_url = request.childLink("shutdown"),
- cancel_shutdown_url = request.childLink("cancel_shutdown"),
- )
- template = request.site.buildbot_service.templates.get_template("root.html")
- defer.returnValue(template.render(**cxt))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py
deleted file mode 100644
index 35c0ad24..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-#
-# Insipration, and some code, from:
-# :copyright: (c) 2011 by the Werkzeug Team, see Werkzeug's AUTHORS for more
-# details.
-
-try:
- from hashlib import sha1
- sha1 = sha1 # make pyflakes happy
-except ImportError:
- from sha import new as sha1
-from time import time
-from random import random
-from datetime import datetime, timedelta
-import os
-def _urandom():
- if hasattr(os, 'urandom'):
- return os.urandom(30)
- return random()
-
-def generate_cookie():
- return sha1('%s%s' % (time(), _urandom())).hexdigest()
-
-
-class Session(object):
- """I'm a user's session. Contains information about a user's session
- a user can have several session
- a session is associated with a cookie
- """
- user = ""
- infos = {}
- def __init__(self, user, infos):
- self.user = user
- self.infos = infos
- self.renew()
-
- def renew(self):
- # one day expiration. hardcoded for now...
- self.expiration = datetime.now()+ timedelta(1)
- return self.expiration
-
- def expired(self):
- return datetime.now() > self.expiration
-
- def userInfosHTML(self):
- return ('%(fullName)s [<a href="mailto:%(email)s">%(email)s</a>]' %
- (self.infos))
-
- def getExpiration(self):
- delim = '-'
- d = self.expiration.utctimetuple()
- return '%s, %02d%s%s%s%s %02d:%02d:%02d GMT' % (
- ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[d.tm_wday],
- d.tm_mday, delim,
- ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
- 'Oct', 'Nov', 'Dec')[d.tm_mon - 1],
- delim, str(d.tm_year), d.tm_hour, d.tm_min, d.tm_sec
- )
-
-class SessionManager(object):
- """I'm the session manager. Holding the current sessions
- managing cookies, and their expiration
-
- KISS version for the moment:
-
- The sessions are stored in RAM so that you have to relogin after buildbot
- reboot
-
- Old sessions are searched at every connection, which is not very good for
- scaling
-
- """
-
- # borg pattern (similar to singleton) not too loose sessions with reconfig
- __shared_state = dict(sessions={},users={})
-
- def __init__(self):
- self.__dict__ = self.__shared_state
-
- def new(self, user, infos):
- cookie = generate_cookie()
- user = infos["userName"]
- self.users[user] = self.sessions[cookie] = s = Session(user, infos)
- return cookie, s
-
- def gc(self):
- """remove old cookies"""
- expired = []
- for cookie in self.sessions:
- s = self.sessions[cookie]
- if s.expired():
- expired.append(cookie)
- for cookie in expired:
- del self.sessions[cookie]
-
- def get(self, cookie):
- self.gc()
- if cookie in self.sessions:
- return self.sessions[cookie]
- return None
-
- def remove(self, cookie):
- if cookie in self.sessions:
- del self.sessions[cookie]
-
- def getUser(self, user):
- return self.users.get(user)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py
deleted file mode 100644
index 323b5463..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import time, urllib
-from twisted.web import html
-from twisted.web.util import Redirect
-from twisted.web.resource import NoResource
-from twisted.internet import defer
-
-from buildbot.status.web.base import HtmlResource, abbreviate_age, \
- BuildLineMixin, ActionResource, path_to_slave, path_to_authzfail
-from buildbot import util
-
-class ShutdownActionResource(ActionResource):
-
- def __init__(self, slave):
- self.slave = slave
- self.action = "gracefulShutdown"
-
- @defer.inlineCallbacks
- def performAction(self, request):
- res = yield self.getAuthz(request).actionAllowed(self.action,
- request,
- self.slave)
-
- url = None
- if res:
- self.slave.setGraceful(True)
- url = path_to_slave(request, self.slave)
- else:
- url = path_to_authzfail(request)
- defer.returnValue(url)
-
-class PauseActionResource(ActionResource):
-
- def __init__(self, slave, state):
- self.slave = slave
- self.action = "pauseSlave"
- self.state = state
-
- @defer.inlineCallbacks
- def performAction(self, request):
- res = yield self.getAuthz(request).actionAllowed(self.action,
- request,
- self.slave)
-
- url = None
- if res:
- self.slave.setPaused(self.state)
- url = path_to_slave(request, self.slave)
- else:
- url = path_to_authzfail(request)
- defer.returnValue(url)
-
-# /buildslaves/$slavename
-class OneBuildSlaveResource(HtmlResource, BuildLineMixin):
- addSlash = False
- def __init__(self, slavename):
- HtmlResource.__init__(self)
- self.slavename = slavename
-
- def getPageTitle(self, req):
- return "Buildbot: %s" % self.slavename
-
- def getChild(self, path, req):
- s = self.getStatus(req)
- slave = s.getSlave(self.slavename)
- if path == "shutdown":
- return ShutdownActionResource(slave)
- if path == "pause" or path == "unpause":
- return PauseActionResource(slave, path == "pause")
- return Redirect(path_to_slave(req, slave))
-
- def content(self, request, ctx):
- s = self.getStatus(request)
- slave = s.getSlave(self.slavename)
-
- my_builders = []
- for bname in s.getBuilderNames():
- b = s.getBuilder(bname)
- for bs in b.getSlaves():
- if bs.getName() == self.slavename:
- my_builders.append(b)
-
- # Current builds
- current_builds = []
- for b in my_builders:
- for cb in b.getCurrentBuilds():
- if cb.getSlavename() == self.slavename:
- current_builds.append(self.get_line_values(request, cb))
-
- try:
- max_builds = int(request.args.get('numbuilds')[0])
- except:
- max_builds = 10
-
- recent_builds = []
- n = 0
- for rb in s.generateFinishedBuilds(builders=[b.getName() for b in my_builders]):
- if rb.getSlavename() == self.slavename:
- n += 1
- recent_builds.append(self.get_line_values(request, rb))
- if n > max_builds:
- break
-
- # connects over the last hour
- slave = s.getSlave(self.slavename)
- connect_count = slave.getConnectCount()
-
- if slave.isPaused():
- pause_url = request.childLink("unpause")
- else:
- pause_url = request.childLink("pause")
-
- ctx.update(dict(slave=slave,
- slavename = self.slavename,
- current = current_builds,
- recent = recent_builds,
- shutdown_url = request.childLink("shutdown"),
- pause_url = pause_url,
- authz = self.getAuthz(request),
- this_url = "../../../" + path_to_slave(request, slave),
- access_uri = slave.getAccessURI()),
- admin = unicode(slave.getAdmin() or '', 'utf-8'),
- host = unicode(slave.getHost() or '', 'utf-8'),
- slave_version = slave.getVersion(),
- show_builder_column = True,
- connect_count = connect_count)
- template = request.site.buildbot_service.templates.get_template("buildslave.html")
- data = template.render(**ctx)
- return data
-
-# /buildslaves
-class BuildSlavesResource(HtmlResource):
- pageTitle = "BuildSlaves"
- addSlash = True
-
- def content(self, request, ctx):
- s = self.getStatus(request)
-
- #?no_builders=1 disables build column
- show_builder_column = not (request.args.get('no_builders', '0')[0])=='1'
- ctx['show_builder_column'] = show_builder_column
-
- used_by_builder = {}
- for bname in s.getBuilderNames():
- b = s.getBuilder(bname)
- for bs in b.getSlaves():
- slavename = bs.getName()
- if slavename not in used_by_builder:
- used_by_builder[slavename] = []
- used_by_builder[slavename].append(bname)
-
- slaves = ctx['slaves'] = []
- for name in util.naturalSort(s.getSlaveNames()):
- info = {}
- slaves.append(info)
- slave = s.getSlave(name)
- slave_status = s.botmaster.slaves[name].slave_status
- info['running_builds'] = len(slave_status.getRunningBuilds())
- info['link'] = request.childLink(urllib.quote(name,''))
- info['name'] = name
-
- if show_builder_column:
- info['builders'] = []
- for b in used_by_builder.get(name, []):
- info['builders'].append(dict(link=request.childLink("../builders/%s" % b), name=b))
-
- info['version'] = slave.getVersion()
- info['connected'] = slave.isConnected()
- info['connectCount'] = slave.getConnectCount()
- info['paused'] = slave.isPaused()
-
- info['admin'] = unicode(slave.getAdmin() or '', 'utf-8')
- last = slave.lastMessageReceived()
- if last:
- info['last_heard_from_age'] = abbreviate_age(time.time() - last)
- info['last_heard_from_time'] = time.strftime("%Y-%b-%d %H:%M:%S",
- time.localtime(last))
-
- template = request.site.buildbot_service.templates.get_template("buildslaves.html")
- data = template.render(**ctx)
- return data
-
- def getChild(self, path, req):
- try:
- self.getStatus(req).getSlave(path)
- return OneBuildSlaveResource(path)
- except KeyError:
- return NoResource("No such slave '%s'" % html.escape(path))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py
deleted file mode 100644
index a725a35d..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py
+++ /dev/null
@@ -1,741 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Portions Copyright Buildbot Team Members
-# Original Copyright (c) 2010 The Chromium Authors.
-
-"""Simple JSON exporter."""
-
-import datetime
-import os
-import re
-
-from twisted.internet import defer
-from twisted.web import html, resource, server
-
-from buildbot.status.web.base import HtmlResource
-from buildbot.util import json
-
-
-_IS_INT = re.compile('^[-+]?\d+$')
-
-
-FLAGS = """\
- - as_text
- - By default, application/json is used. Setting as_text=1 change the type
- to text/plain and implicitly sets compact=0 and filter=1. Mainly useful to
- look at the result in a web browser.
- - compact
- - By default, the json data is compact and defaults to 1. For easier to read
- indented output, set compact=0.
- - select
- - By default, most children data is listed. You can do a random selection
- of data by using select=<sub-url> multiple times to coagulate data.
- "select=" includes the actual url otherwise it is skipped.
- - numbuilds
- - By default, only in memory cached builds are listed. You can as for more data
- by using numbuilds=<number>.
- - filter
- - Filters out null, false, and empty string, list and dict. This reduce the
- amount of useless data sent.
- - callback
- - Enable uses of JSONP as described in
- http://en.wikipedia.org/wiki/JSONP. Note that
- Access-Control-Allow-Origin:* is set in the HTTP response header so you
- can use this in compatible browsers.
-"""
-
-EXAMPLES = """\
- - /json
- - Root node, that *doesn't* mean all the data. Many things (like logs) must
- be explicitly queried for performance reasons.
- - /json/builders/
- - All builders.
- - /json/builders/<A_BUILDER>
- - A specific builder as compact text.
- - /json/builders/<A_BUILDER>/builds
- - All *cached* builds.
- - /json/builders/<A_BUILDER>/builds/_all
- - All builds. Warning, reads all previous build data.
- - /json/builders/<A_BUILDER>/builds/<A_BUILD>
- - Where <A_BUILD> is either positive, a build number, or negative, a past
- build.
- - /json/builders/<A_BUILDER>/builds/-1/source_stamp/changes
- - Build changes
- - /json/builders/<A_BUILDER>/builds?select=-1&select=-2
- - Two last builds on '<A_BUILDER>' builder.
- - /json/builders/<A_BUILDER>/builds?select=-1/source_stamp/changes&select=-2/source_stamp/changes
- - Changes of the two last builds on '<A_BUILDER>' builder.
- - /json/builders/<A_BUILDER>/slaves
- - Slaves associated to this builder.
- - /json/builders/<A_BUILDER>?select=&select=slaves
- - Builder information plus details information about its slaves. Neat eh?
- - /json/slaves/<A_SLAVE>
- - A specific slave.
- - /json?select=slaves/<A_SLAVE>/&select=project&select=builders/<A_BUILDER>/builds/<A_BUILD>
- - A selection of random unrelated stuff as an random example. :)
-"""
-
-
-def RequestArg(request, arg, default):
- return request.args.get(arg, [default])[0]
-
-
-def RequestArgToBool(request, arg, default):
- value = RequestArg(request, arg, default)
- if value in (False, True):
- return value
- value = value.lower()
- if value in ('1', 'true'):
- return True
- if value in ('0', 'false'):
- return False
- # Ignore value.
- return default
-
-
-def FilterOut(data):
- """Returns a copy with None, False, "", [], () and {} removed.
- Warning: converts tuple to list."""
- if isinstance(data, (list, tuple)):
- # Recurse in every items and filter them out.
- items = map(FilterOut, data)
- if not filter(lambda x: not x in ('', False, None, [], {}, ()), items):
- return None
- return items
- elif isinstance(data, dict):
- return dict(filter(lambda x: not x[1] in ('', False, None, [], {}, ()),
- [(k, FilterOut(v)) for (k, v) in data.iteritems()]))
- else:
- return data
-
-
-class JsonResource(resource.Resource):
- """Base class for json data."""
-
- contentType = "application/json"
- cache_seconds = 60
- help = None
- pageTitle = None
- level = 0
-
- def __init__(self, status):
- """Adds transparent lazy-child initialization."""
- resource.Resource.__init__(self)
- # buildbot.status.builder.Status
- self.status = status
-
- def getChildWithDefault(self, path, request):
- """Adds transparent support for url ending with /"""
- if path == "" and len(request.postpath) == 0:
- return self
- if path == 'help' and self.help:
- pageTitle = ''
- if self.pageTitle:
- pageTitle = self.pageTitle + ' help'
- return HelpResource(self.help,
- pageTitle=pageTitle,
- parent_node=self)
- # Equivalent to resource.Resource.getChildWithDefault()
- if self.children.has_key(path):
- return self.children[path]
- return self.getChild(path, request)
-
- def putChild(self, name, res):
- """Adds the resource's level for help links generation."""
-
- def RecurseFix(res, level):
- res.level = level + 1
- for c in res.children.itervalues():
- RecurseFix(c, res.level)
-
- RecurseFix(res, self.level)
- resource.Resource.putChild(self, name, res)
-
- def render_GET(self, request):
- """Renders a HTTP GET at the http request level."""
- d = defer.maybeDeferred(lambda : self.content(request))
- def handle(data):
- if isinstance(data, unicode):
- data = data.encode("utf-8")
- request.setHeader("Access-Control-Allow-Origin", "*")
- if RequestArgToBool(request, 'as_text', False):
- request.setHeader("content-type", 'text/plain')
- else:
- request.setHeader("content-type", self.contentType)
- request.setHeader("content-disposition",
- "attachment; filename=\"%s.json\"" % request.path)
- # Make sure we get fresh pages.
- if self.cache_seconds:
- now = datetime.datetime.utcnow()
- expires = now + datetime.timedelta(seconds=self.cache_seconds)
- request.setHeader("Expires",
- expires.strftime("%a, %d %b %Y %H:%M:%S GMT"))
- request.setHeader("Pragma", "no-cache")
- return data
- d.addCallback(handle)
- def ok(data):
- request.write(data)
- request.finish()
- def fail(f):
- request.processingFailed(f)
- return None # processingFailed will log this for us
- d.addCallbacks(ok, fail)
- return server.NOT_DONE_YET
-
- @defer.inlineCallbacks
- def content(self, request):
- """Renders the json dictionaries."""
- # Supported flags.
- select = request.args.get('select')
- as_text = RequestArgToBool(request, 'as_text', False)
- filter_out = RequestArgToBool(request, 'filter', as_text)
- compact = RequestArgToBool(request, 'compact', not as_text)
- callback = request.args.get('callback')
-
- # Implement filtering at global level and every child.
- if select is not None:
- del request.args['select']
- # Do not render self.asDict()!
- data = {}
- # Remove superfluous /
- select = [s.strip('/') for s in select]
- select.sort(cmp=lambda x,y: cmp(x.count('/'), y.count('/')),
- reverse=True)
- for item in select:
- # Start back at root.
- node = data
- # Implementation similar to twisted.web.resource.getChildForRequest
- # but with a hacked up request.
- child = self
- prepath = request.prepath[:]
- postpath = request.postpath[:]
- request.postpath = filter(None, item.split('/'))
- while request.postpath and not child.isLeaf:
- pathElement = request.postpath.pop(0)
- node[pathElement] = {}
- node = node[pathElement]
- request.prepath.append(pathElement)
- child = child.getChildWithDefault(pathElement, request)
-
- # some asDict methods return a Deferred, so handle that
- # properly
- if hasattr(child, 'asDict'):
- child_dict = yield defer.maybeDeferred(lambda :
- child.asDict(request))
- else:
- child_dict = {
- 'error' : 'Not available',
- }
- node.update(child_dict)
-
- request.prepath = prepath
- request.postpath = postpath
- else:
- data = yield defer.maybeDeferred(lambda : self.asDict(request))
-
- if filter_out:
- data = FilterOut(data)
- if compact:
- data = json.dumps(data, sort_keys=True, separators=(',',':'))
- else:
- data = json.dumps(data, sort_keys=True, indent=2)
- if callback:
- # Only accept things that look like identifiers for now
- callback = callback[0]
- if re.match(r'^[a-zA-Z$][a-zA-Z$0-9.]*$', callback):
- data = '%s(%s);' % (callback, data)
- defer.returnValue(data)
-
- @defer.inlineCallbacks
- def asDict(self, request):
- """Generates the json dictionary.
-
- By default, renders every childs."""
- if self.children:
- data = {}
- for name in self.children:
- child = self.getChildWithDefault(name, request)
- if isinstance(child, JsonResource):
- data[name] = yield defer.maybeDeferred(lambda :
- child.asDict(request))
- # else silently pass over non-json resources.
- defer.returnValue(data)
- else:
- raise NotImplementedError()
-
-
-def ToHtml(text):
- """Convert a string in a wiki-style format into HTML."""
- indent = 0
- in_item = False
- output = []
- for line in text.splitlines(False):
- match = re.match(r'^( +)\- (.*)$', line)
- if match:
- if indent < len(match.group(1)):
- output.append('<ul>')
- indent = len(match.group(1))
- elif indent > len(match.group(1)):
- while indent > len(match.group(1)):
- output.append('</ul>')
- indent -= 2
- if in_item:
- # Close previous item
- output.append('</li>')
- output.append('<li>')
- in_item = True
- line = match.group(2)
- elif indent:
- if line.startswith((' ' * indent) + ' '):
- # List continuation
- line = line.strip()
- else:
- # List is done
- if in_item:
- output.append('</li>')
- in_item = False
- while indent > 0:
- output.append('</ul>')
- indent -= 2
-
- if line.startswith('/'):
- if not '?' in line:
- line_full = line + '?as_text=1'
- else:
- line_full = line + '&as_text=1'
- output.append('<a href="' + html.escape(line_full) + '">' +
- html.escape(line) + '</a>')
- else:
- output.append(html.escape(line).replace(' ', '&nbsp;&nbsp;'))
- if not in_item:
- output.append('<br>')
-
- if in_item:
- output.append('</li>')
- while indent > 0:
- output.append('</ul>')
- indent -= 2
- return '\n'.join(output)
-
-
-class HelpResource(HtmlResource):
- def __init__(self, text, pageTitle, parent_node):
- HtmlResource.__init__(self)
- self.text = text
- self.pageTitle = pageTitle
- self.parent_level = parent_node.level
- self.parent_children = parent_node.children.keys()
-
- def content(self, request, cxt):
- cxt['level'] = self.parent_level
- cxt['text'] = ToHtml(self.text)
- cxt['children'] = [ n for n in self.parent_children if n != 'help' ]
- cxt['flags'] = ToHtml(FLAGS)
- cxt['examples'] = ToHtml(EXAMPLES).replace(
- 'href="/json',
- 'href="../%sjson' % (self.parent_level * '../'))
-
- template = request.site.buildbot_service.templates.get_template("jsonhelp.html")
- return template.render(**cxt)
-
-class BuilderPendingBuildsJsonResource(JsonResource):
- help = """Describe pending builds for a builder.
-"""
- pageTitle = 'Builder'
-
- def __init__(self, status, builder_status):
- JsonResource.__init__(self, status)
- self.builder_status = builder_status
-
- def asDict(self, request):
- # buildbot.status.builder.BuilderStatus
- d = self.builder_status.getPendingBuildRequestStatuses()
- def to_dict(statuses):
- return defer.gatherResults(
- [ b.asDict_async() for b in statuses ])
- d.addCallback(to_dict)
- return d
-
-
-class BuilderJsonResource(JsonResource):
- help = """Describe a single builder.
-"""
- pageTitle = 'Builder'
-
- def __init__(self, status, builder_status):
- JsonResource.__init__(self, status)
- self.builder_status = builder_status
- self.putChild('builds', BuildsJsonResource(status, builder_status))
- self.putChild('slaves', BuilderSlavesJsonResources(status,
- builder_status))
- self.putChild(
- 'pendingBuilds',
- BuilderPendingBuildsJsonResource(status, builder_status))
-
- def asDict(self, request):
- # buildbot.status.builder.BuilderStatus
- return self.builder_status.asDict_async()
-
-
-class BuildersJsonResource(JsonResource):
- help = """List of all the builders defined on a master.
-"""
- pageTitle = 'Builders'
-
- def __init__(self, status):
- JsonResource.__init__(self, status)
- for builder_name in self.status.getBuilderNames():
- self.putChild(builder_name,
- BuilderJsonResource(status,
- status.getBuilder(builder_name)))
-
-
-class BuilderSlavesJsonResources(JsonResource):
- help = """Describe the slaves attached to a single builder.
-"""
- pageTitle = 'BuilderSlaves'
-
- def __init__(self, status, builder_status):
- JsonResource.__init__(self, status)
- self.builder_status = builder_status
- for slave_name in self.builder_status.slavenames:
- self.putChild(slave_name,
- SlaveJsonResource(status,
- self.status.getSlave(slave_name)))
-
-
-class BuildJsonResource(JsonResource):
- help = """Describe a single build.
-"""
- pageTitle = 'Build'
-
- def __init__(self, status, build_status):
- JsonResource.__init__(self, status)
- self.build_status = build_status
- # TODO: support multiple sourcestamps
- sourcestamp = build_status.getSourceStamps()[0]
- self.putChild('source_stamp',
- SourceStampJsonResource(status, sourcestamp))
- self.putChild('steps', BuildStepsJsonResource(status, build_status))
-
- def asDict(self, request):
- return self.build_status.asDict()
-
-
-class AllBuildsJsonResource(JsonResource):
- help = """All the builds that were run on a builder.
-"""
- pageTitle = 'AllBuilds'
-
- def __init__(self, status, builder_status):
- JsonResource.__init__(self, status)
- self.builder_status = builder_status
-
- def getChild(self, path, request):
- # Dynamic childs.
- if isinstance(path, int) or _IS_INT.match(path):
- build_status = self.builder_status.getBuild(int(path))
- if build_status:
- return BuildJsonResource(self.status, build_status)
- return JsonResource.getChild(self, path, request)
-
- def asDict(self, request):
- results = {}
- # If max > buildCacheSize, it'll trash the cache...
- cache_size = self.builder_status.master.config.caches['Builds']
- max = int(RequestArg(request, 'max', cache_size))
- for i in range(0, max):
- child = self.getChildWithDefault(-i, request)
- if not isinstance(child, BuildJsonResource):
- continue
- results[child.build_status.getNumber()] = child.asDict(request)
- return results
-
-
-class BuildsJsonResource(AllBuildsJsonResource):
- help = """Builds that were run on a builder.
-"""
- pageTitle = 'Builds'
-
- def __init__(self, status, builder_status):
- AllBuildsJsonResource.__init__(self, status, builder_status)
- self.putChild('_all', AllBuildsJsonResource(status, builder_status))
-
- def getChild(self, path, request):
- # Transparently redirects to _all if path is not ''.
- return self.children['_all'].getChildWithDefault(path, request)
-
- def asDict(self, request):
- # This would load all the pickles and is way too heavy, especially that
- # it would trash the cache:
- # self.children['builds'].asDict(request)
- # TODO(maruel) This list should also need to be cached but how?
- builds = dict([
- (int(file), None)
- for file in os.listdir(self.builder_status.basedir)
- if _IS_INT.match(file)
- ])
- return builds
-
-
-class BuildStepJsonResource(JsonResource):
- help = """A single build step.
-"""
- pageTitle = 'BuildStep'
-
- def __init__(self, status, build_step_status):
- # buildbot.status.buildstep.BuildStepStatus
- JsonResource.__init__(self, status)
- self.build_step_status = build_step_status
- # TODO self.putChild('logs', LogsJsonResource())
-
- def asDict(self, request):
- return self.build_step_status.asDict()
-
-
-class BuildStepsJsonResource(JsonResource):
- help = """A list of build steps that occurred during a build.
-"""
- pageTitle = 'BuildSteps'
-
- def __init__(self, status, build_status):
- JsonResource.__init__(self, status)
- self.build_status = build_status
- # The build steps are constantly changing until the build is done so
- # keep a reference to build_status instead
-
- def getChild(self, path, request):
- # Dynamic childs.
- build_step_status = None
- if isinstance(path, int) or _IS_INT.match(path):
- build_step_status = self.build_status.getSteps()[int(path)]
- else:
- steps_dict = dict([(step.getName(), step)
- for step in self.build_status.getSteps()])
- build_step_status = steps_dict.get(path)
- if build_step_status:
- # Create it on-demand.
- child = BuildStepJsonResource(self.status, build_step_status)
- # Cache it.
- index = self.build_status.getSteps().index(build_step_status)
- self.putChild(str(index), child)
- self.putChild(build_step_status.getName(), child)
- return child
- return JsonResource.getChild(self, path, request)
-
- def asDict(self, request):
- # Only use the number and not the names!
- results = {}
- index = 0
- for step in self.build_status.getSteps():
- results[index] = step.asDict()
- index += 1
- return results
-
-
-class ChangeJsonResource(JsonResource):
- help = """Describe a single change that originates from a change source.
-"""
- pageTitle = 'Change'
-
- def __init__(self, status, change):
- # buildbot.changes.changes.Change
- JsonResource.__init__(self, status)
- self.change = change
-
- def asDict(self, request):
- return self.change.asDict()
-
-
-class ChangesJsonResource(JsonResource):
- help = """List of changes.
-"""
- pageTitle = 'Changes'
-
- def __init__(self, status, changes):
- JsonResource.__init__(self, status)
- for c in changes:
- # c.number can be None or clash another change if the change was
- # generated inside buildbot or if using multiple pollers.
- if c.number is not None and str(c.number) not in self.children:
- self.putChild(str(c.number), ChangeJsonResource(status, c))
- else:
- # Temporary hack since it creates information exposure.
- self.putChild(str(id(c)), ChangeJsonResource(status, c))
-
- def asDict(self, request):
- """Don't throw an exception when there is no child."""
- if not self.children:
- return {}
- return JsonResource.asDict(self, request)
-
-
-class ChangeSourcesJsonResource(JsonResource):
- help = """Describe a change source.
-"""
- pageTitle = 'ChangeSources'
-
- def asDict(self, request):
- result = {}
- n = 0
- for c in self.status.getChangeSources():
- # buildbot.changes.changes.ChangeMaster
- change = {}
- change['description'] = c.describe()
- result[n] = change
- n += 1
- return result
-
-
-class ProjectJsonResource(JsonResource):
- help = """Project-wide settings.
-"""
- pageTitle = 'Project'
-
- def asDict(self, request):
- return self.status.asDict()
-
-
-class SlaveJsonResource(JsonResource):
- help = """Describe a slave.
-"""
- pageTitle = 'Slave'
-
- def __init__(self, status, slave_status):
- JsonResource.__init__(self, status)
- self.slave_status = slave_status
- self.name = self.slave_status.getName()
- self.builders = None
-
- def getBuilders(self):
- if self.builders is None:
- # Figure out all the builders to which it's attached
- self.builders = []
- for builderName in self.status.getBuilderNames():
- if self.name in self.status.getBuilder(builderName).slavenames:
- self.builders.append(builderName)
- return self.builders
-
- def asDict(self, request):
- results = self.slave_status.asDict()
- # Enhance it by adding more informations.
- results['builders'] = {}
- for builderName in self.getBuilders():
- builds = []
- builder_status = self.status.getBuilder(builderName)
- cache_size = builder_status.master.config.caches['Builds']
- numbuilds = int(request.args.get('numbuilds', [cache_size - 1])[0])
- for i in range(1, numbuilds):
- build_status = builder_status.getBuild(-i)
- if not build_status or not build_status.isFinished():
- # If not finished, it will appear in runningBuilds.
- break
- if build_status.getSlavename() == self.name:
- builds.append(build_status.getNumber())
- results['builders'][builderName] = builds
- return results
-
-
-class SlavesJsonResource(JsonResource):
- help = """List the registered slaves.
-"""
- pageTitle = 'Slaves'
-
- def __init__(self, status):
- JsonResource.__init__(self, status)
- for slave_name in status.getSlaveNames():
- self.putChild(slave_name,
- SlaveJsonResource(status,
- status.getSlave(slave_name)))
-
-
-class SourceStampJsonResource(JsonResource):
- help = """Describe the sources for a SourceStamp.
-"""
- pageTitle = 'SourceStamp'
-
- def __init__(self, status, source_stamp):
- # buildbot.sourcestamp.SourceStamp
- JsonResource.__init__(self, status)
- self.source_stamp = source_stamp
- self.putChild('changes',
- ChangesJsonResource(status, source_stamp.changes))
- # TODO(maruel): Should redirect to the patch's url instead.
- #if source_stamp.patch:
- # self.putChild('patch', StaticHTML(source_stamp.path))
-
- def asDict(self, request):
- return self.source_stamp.asDict()
-
-class MetricsJsonResource(JsonResource):
- help = """Master metrics.
-"""
- title = "Metrics"
-
- def asDict(self, request):
- metrics = self.status.getMetrics()
- if metrics:
- return metrics.asDict()
- else:
- # Metrics are disabled
- return None
-
-
-
-class JsonStatusResource(JsonResource):
- """Retrieves all json data."""
- help = """JSON status
-
-Root page to give a fair amount of information in the current buildbot master
-status. You may want to use a child instead to reduce the load on the server.
-
-For help on any sub directory, use url /child/help
-"""
- pageTitle = 'Buildbot JSON'
-
- def __init__(self, status):
- JsonResource.__init__(self, status)
- self.level = 1
- self.putChild('builders', BuildersJsonResource(status))
- self.putChild('change_sources', ChangeSourcesJsonResource(status))
- self.putChild('project', ProjectJsonResource(status))
- self.putChild('slaves', SlavesJsonResource(status))
- self.putChild('metrics', MetricsJsonResource(status))
- # This needs to be called before the first HelpResource().body call.
- self.hackExamples()
-
- def content(self, request):
- result = JsonResource.content(self, request)
- # This is done to hook the downloaded filename.
- request.path = 'buildbot'
- return result
-
- def hackExamples(self):
- global EXAMPLES
- # Find the first builder with a previous build or select the last one.
- builder = None
- for b in self.status.getBuilderNames():
- builder = self.status.getBuilder(b)
- if builder.getBuild(-1):
- break
- if not builder:
- return
- EXAMPLES = EXAMPLES.replace('<A_BUILDER>', builder.getName())
- build = builder.getBuild(-1)
- if build:
- EXAMPLES = EXAMPLES.replace('<A_BUILD>', str(build.getNumber()))
- if builder.slavenames:
- EXAMPLES = EXAMPLES.replace('<A_SLAVE>', builder.slavenames[0])
-
-# vim: set ts=4 sts=4 sw=4 et:
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py
deleted file mode 100644
index 138fa3cc..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import urllib
-from buildbot.status.web.base import HtmlResource, path_to_builder, \
- path_to_build, css_classes
-from buildbot.status.web.logs import LogsResource
-from buildbot import util
-from time import ctime
-
-# /builders/$builder/builds/$buildnum/steps/$stepname
-class StatusResourceBuildStep(HtmlResource):
- pageTitle = "Build Step"
- addSlash = True
-
- def __init__(self, build_status, step_status):
- HtmlResource.__init__(self)
- self.status = build_status
- self.step_status = step_status
-
- def content(self, req, cxt):
- s = self.step_status
- b = s.getBuild()
-
- logs = cxt['logs'] = []
- for l in s.getLogs():
- # FIXME: If the step name has a / in it, this is broken
- # either way. If we quote it but say '/'s are safe,
- # it chops up the step name. If we quote it and '/'s
- # are not safe, it escapes the / that separates the
- # step name from the log number.
- logs.append({'has_contents': l.hasContents(),
- 'name': l.getName(),
- 'link': req.childLink("logs/%s" % urllib.quote(l.getName())) })
-
- stepStatistics = s.getStatistics()
- statistics = cxt['statistics'] = []
- for stat in stepStatistics:
- statistics.append({'name': stat, 'value': stepStatistics[stat]})
-
- start, end = s.getTimes()
-
- if start:
- cxt['start'] = ctime(start)
- if end:
- cxt['end'] = ctime(end)
- cxt['elapsed'] = util.formatInterval(end - start)
- else:
- cxt['end'] = "Not Finished"
- cxt['elapsed'] = util.formatInterval(util.now() - start)
-
- cxt.update(dict(builder_link = path_to_builder(req, b.getBuilder()),
- build_link = path_to_build(req, b),
- b = b,
- s = s,
- result_css = css_classes[s.getResults()[0]]))
-
- template = req.site.buildbot_service.templates.get_template("buildstep.html");
- return template.render(**cxt)
-
- def getChild(self, path, req):
- if path == "logs":
- return LogsResource(self.step_status)
- return HtmlResource.getChild(self, path, req)
-
-
-
-# /builders/$builder/builds/$buildnum/steps
-class StepsResource(HtmlResource):
- addSlash = True
-
- def __init__(self, build_status):
- HtmlResource.__init__(self)
- self.build_status = build_status
-
- def content(self, req, ctx):
- return "subpages show data for each step"
-
- def getChild(self, path, req):
- for s in self.build_status.getSteps():
- if s.getName() == path:
- return StatusResourceBuildStep(self.build_status, s)
- return HtmlResource.getChild(self, path, req)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html
deleted file mode 100644
index f7b799a2..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>About this Buildbot</h1>
-
-<div class="column">
-
-<h2>Version Information</h2>
-<ul>
-{% set item_class=cycler('alt', '') %}
-
- <li class="{{ item_class.next() }}">Buildbot: {{ buildbot }}</li>
- <li class="{{ item_class.next() }}">Twisted: {{ twisted }}</li>
- <li class="{{ item_class.next() }}">Jinja: {{ jinja }}</li>
- <li class="{{ item_class.next() }}">Python: {{ python }}</li>
- <li class="{{ item_class.next() }}">Buildmaster platform: {{ platform }}</li>
-
-</ul>
-
-<h2>Source code</h2>
-
-<p>Buildbot is a free software project, released under the terms of the
-<a href="http://www.gnu.org/licenses/gpl.html">GNU GPL</a>.</p>
-
-<p>Please visit the <a href="http://buildbot.net/">Buildbot Home Page</a> for
-more information, including documentation, bug reports, and source
-downloads.</p>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html
deleted file mode 100644
index bae600f7..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Authentication Failed</h1>
-
-<p>The username or password you entered were not correct.
- Please go back and try again.
-</p>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html
deleted file mode 100644
index e2bfcd99..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Authorization Failed</h1>
-
-<p>You are not allowed to perform this action.
-</p>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html
deleted file mode 100644
index ec5b80b6..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% macro box(text=[], comment=None) -%}
-
-{%- if comment -%}<!-- {{ comment }} -->{%- endif -%}
- <td class="{{ kwargs.class or kwargs.class_ or "" }}"
- {%- for prop in ("align", "colspan", "rowspan", "border", "valign", "halign") -%}
- {%- if prop in kwargs %} {{ prop }}="{{ kwargs[prop] }}"{% endif -%}
- {%- endfor -%}>
-
- {%- if text is string -%}
- {{ text }}
- {%- else -%}
- {{- text|join("<br/>") -}}
- {%- endif -%}
- </td>
-{% endmacro %}
-
-{# this is currently just the text part of the boxes #}
-
-{% macro build_box(reason, url, number) -%}
- <a title="Reason: {{ reason|e }}" href="{{ url }}">Build {{ number }}</a>
-{%- endmacro %}
-
-{% macro step_box(text, logs, urls, stepinfo) -%}
- {%- if text is string -%}
- {{ text }}
- {%- else -%}
- {{- text|join("<br/>") -}}
- {%- endif -%}
- <br/>
- {%- for l in logs %}
- <a {% if l.url %}href="{{ l.url }}"{% endif %}>{{ l.name|e }}</a><br/>
- {%- endfor -%}
-
- {%- for u in urls %}
- [<a href="{{ u.link }}" class="BuildStep external">{{ u.name|e }}</a>]<br/>
- {%- endfor -%}
-{%- endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html
deleted file mode 100644
index 0f508880..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html
+++ /dev/null
@@ -1,238 +0,0 @@
-{% extends "layout.html" %}
-{% import 'forms.html' as forms %}
-{% from "change_macros.html" import change with context %}
-
-{% block content %}
-
-<h1>
-Builder <a href="{{ path_to_builder }}">{{ b.getBuilder().getName() }}</a>
-Build #{{ b.getNumber() }}
-</h1>
-
-<div class="column">
-
-{% if not b.isFinished() %}
- <h2>Build In Progress:</h2>
-
- {% if when_time %}
- <p>ETA: {{ when_time }} [{{ when }}]</p>
- {% endif %}
-
- {{ current_step }}
-
- {% if authz.advertiseAction('stopBuild', request) %}
- <h2>Stop Build</h2>
- {{ forms.stop_build(build_url+"/stop", authz, on_all=False, short=False, label='This Build') }}
- {% endif %}
-{% else %}
- <h2>Results:</h2>
-
- <p class="{{ result_css }} result">
- {{ b.getText()|join(' ')|capitalize }}
- </p>
-
- {% if b.getTestResults() %}
- <h3><a href="{{ tests_link }}"/></h3>
- {% endif %}
-{% endif %}
-
-<h2>
-{% if sourcestamps|count == 1 %}
-SourceStamp:
-{% else %}
-SourceStamps:
-{% endif %}
-</h2>
-
-{% for ss in sourcestamps %}
-<h3>{{ ss.codebase }}</h3>
- <table class="info" width="100%">
- {% set ss_class = cycler('alt','') %}
-
- {% if ss.project %}
- <tr class="{{ ss_class.next() }}"><td class="left">Project</td><td>{{ ss.project|projectlink }}</td></tr>
- {% endif %}
-
- {% if ss.repository %}
- <tr class="{{ ss_class.next() }}"><td class="left">Repository</td><td>{{ ss.repository|repolink }}</td></tr>
- {% endif %}
-
- {% if ss.branch %}
- <tr class="{{ ss_class.next() }}"><td class="left">Branch</td><td>{{ ss.branch|e }}</td></tr>
- {% endif %}
-
- {% if ss.revision %}
- <tr class="{{ ss_class.next() }}"><td class="left">Revision</td><td>{{ ss.revision|revlink(ss.repository) }}</td></tr>
- {% endif %}
-
- {% if got_revisions[ss.codebase] %}
- <tr class="{{ ss_class.next() }}"><td class="left">Got Revision</td><td>{{ got_revisions[ss.codebase]|revlink(ss.repository) }}</td></tr>
- {% endif %}
-
- {% if ss.patch %}
- <tr class="{{ ss_class.next() }}"><td class="left">Patch</td><td>YES</td></tr>
- {% endif %}
-
- {% if ss.changes %}
- <tr class="{{ ss_class.next() }}"><td class="left">Changes</td><td><a href="#changes-{{ ss.codebase }}">{{ ss.changes|count }} change{{ 's' if ss.changes|count > 1 else '' }}</a></td></tr>
- {% endif %}
-
- {% if not ss.branch and not ss.revision and not ss.patch and not ss.changes %}
- <tr class="{{ ss_class.next() }}"><td class="left" colspan="2">Build of most recent revision</td></tr>
- {% endif %}
- </table>
-{% endfor %}
-
-{#
- # TODO: turn this into a table, or some other sort of definition-list
- # that doesn't take up quite so much vertical space
- #}
-
-<h2>BuildSlave:</h2>
-
-{% if slave_url %}
- <a href="{{ slave_url|e }}">{{ b.getSlavename()|e }}</a>
-{% else %}
- {{ b.getSlavename()|e }}
-{% endif %}
-
-<h2>Reason:</h2>
-<p>
-{{ b.getReason()|e }}
-</p>
-
-<h2>Steps and Logfiles:</h2>
-
-{#
- # TODO:
- # urls = self.original.getURLs()
- # ex_url_class = "BuildStep external"
- # for name, target in urls.items():
- # text.append('[<a href="%s" class="%s">%s</a>]' %
- # (target, ex_url_class, html.escape(name)))
- #}
-
-<ol>
-{% for s in steps %}
- <li>
- <div class="{{ s.css_class }} result">
- <a href="{{ s.link }}">{{ s.name }}</a>
- {{ s.text }}&nbsp;<span style="float:right">{{ '( ' + s.time_to_run + ' )' if s.time_to_run else '' }}</span>
- </div>
-
- <ol>
- {% set item_class = cycler('alt', '') %}
- {% for l in s.logs %}
- <li class="{{ item_class.next() }}"><a href="{{ l.link }}">{{ l.name }}</a></li>
- {% else %}
- <li class="{{ item_class.next() }}">- no logs -</li>
- {% endfor %}
-
- {% for u in s.urls %}
- <li class="{{ item_class.next() }}"><a href="{{ u.url }}">{{ u.logname }}</a></li>
- {% endfor %}
- </ol>
- </li>
-{% endfor %}
-</ol>
-
-</div>
-<div class="column">
-
-<h2>Build Properties:</h2>
-
-<table class="info" width="100%">
-<tr><th>Name</th><th>Value</th><th>Source</th></tr>
-
-{% for p in properties %}
-{% if p.source != "Force Build Form" %}
- <tr class="{{ loop.cycle('alt', '') }}">
- <td class="left">{{ p.name|e }}</td>
- {% if p.short_value %}
- <td>{{ p.short_value|e }} .. [property value too long]</td>
- {% else %}
- {% if p.value is not mapping %}
- <td>{{ p.value|e }}</td>
- {% else %}
- <td>
- <table class="info" width="100%">
- {%- for key, value in p.value.items() recursive %}
- <tr><td>{{ key|e }}</td><td>{{ value|e }}</td></tr>
- {% endfor %}
- </table>
- </td>
- {% endif %}
- {% endif %}
- <td>{{ p.source|e }}</td>
- </tr>
-{% endif %}
-{% endfor %}
-</table>
-<h2>Forced Build Properties:</h2>
-<table class="info" width="100%">
-<tr><th>Name</th><th>Label</th><th>Value</th></tr>
-
-{% for p in properties %}
- {% if p.source == "Force Build Form" %}
- <tr class="{{ loop.cycle('alt', '') }}">
- <td class="left">{{ p.name|e }}</td>
- <td class="left">
- {% if p.label %}
- {{ p.label }}
- {% endif %}
- </td>
- {% if p.text %}
- <td><textarea readonly cols="{{p.cols}}" rows="{{p.rows}}">{{ p.text|e }}</textarea></td>
- {% else %}
- <td>{{ p.value|e }}</td>
- {% endif %}
- </tr>
- {% endif %}
-{% endfor %}
-</table>
-
-<h2>Responsible Users:</h2>
-
-{% if responsible_users %}
- <ol>
- {% for u in responsible_users %}
- <li class="{{ loop.cycle('alt', '') }}">{{ u|user }}</li>
- {% endfor %}
- </ol>
-{% else %}
- <p>no responsible users</p>
-{% endif %}
-
-
-<h2>Timing:</h2>
-<table class="info" width="100%">
- <tr class="alt"><td class="left">Start</td><td>{{ start }}</td></tr>
-{% if end %}
- <tr><td class="left">End</td><td>{{ end }}</td></tr>
-{% endif %}
- <tr {{ 'class="alt"' if end else '' }}><td class="left">Elapsed</td><td>{{ elapsed }}</td></tr>
-</table>
-
-</div>
-
-<br style="clear:both"/>
-
-{% if has_changes %}
- <div class="column">
- <h2>All Changes:</h2>
- {% for ss in sourcestamps %}
- {% if ss.changes %}
- <h3 id="changes-{{ ss.codebase }}"> {{ ss.codebase }}:</h3>
- <ol>
- {% for c in ss.changes %}
- <li><h3>Change #{{ c.number }}</h3>
- {{ change(c.asDict()) }}
- </li>
- {% endfor %}
- </ol>
- {% endif %}
- {% endfor %}
- </div>
-{% endif %}
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html
deleted file mode 100644
index fc08b9dc..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% macro build_line(b, include_builder=False) %}
- <small>({{ b.time }})</small>
- Rev: {{ b.rev|shortrev(b.rev_repo) }}
- <span class="{{ b.class }}">{{ b.results }}</span>
- {% if include_builder %}
- <a href="{{ b.builderurl }}">{{ b.builder_name }}</a>
- {% endif %}
- <a href="{{ b.buildurl }}">#{{ b.buildnum }}</a> -
- {{ b.text|capitalize }}
-{% endmacro %}
-
-{% macro build_tr(b, include_builder=False, loop=None) %}
- <tr class="{{ loop.cycle('alt', '') if loop }}">
- <td>{{ b.time }}</td>
- <td>{{ b.rev|shortrev(b.rev_repo) }}</td>
- <td class="{{ b.class }}">{{ b.results }}</td>
- {%- if include_builder %}
- <td><a href="{{ b.builderurl }}">{{ b.builder_name }}</a></td>
- {% endif %}
- <td><a href="{{ b.buildurl }}">#{{ b.buildnum }}</a></td>
- <td class="left">{{ b.text|capitalize }}</td>
- </tr>
-{% endmacro %}
-
-{% macro build_table(builds, include_builder=False) %}
-{% if builds %}
-<table class="info">
- <tr>
- <th>Time</th>
- <th>Revision</th>
- <th>Result</th>
- {%- if include_builder %}
- <th>Builder</th>
- {% endif %}
- <th>Build #</th>
- <th>Info</th>
- </tr>
- {% for b in builds %}
- {{ build_tr(b, include_builder, loop) }}
- {% endfor %}
-</table>
-{% else %}
- No matching builds found
-{% endif %}
-{% endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html
deleted file mode 100644
index f557d7c5..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html
+++ /dev/null
@@ -1,184 +0,0 @@
-{% from 'build_line.html' import build_table %}
-{% import 'forms.html' as forms %}
-
-{% extends "layout.html" %}
-
-{% block head %}
-{{ super() }}
-<script type='text/javascript'>
-// <![CDATA[
-//
-
-// Mapping OE Core branch names to bitbake branch names
-var bbvermap = {
- 'jethro': '1.28',
- 'krogoth': '1.30',
- 'morty': '1.32',
- 'pyro': '1.34',
- 'rocko': '1.36',
- 'sumo': '1.38',
- 'master': 'master'
-};
-
-var eclipseBranchFormat = "branch_eclipse-poky-";
-
-function isEclipseBranch(elementName) {
- var pattern = eclipseBranchFormat + "*";
- return new RegExp(pattern).test(elementName);
-}
-
-function updateFormBranchInputs(pokybranch) {
- var elements = document.querySelectorAll('input[name^="branch_"]');
-
- for (var i = 0, len = elements.length; i < len; i++) {
- var newval = pokybranch;
- if (elements[i].name == "branch_bitbake") {
- newval = bbvermap[pokybranch];
- } else if (isEclipseBranch(elements[i].name)) {
- eclipseRelease = elements[i].name.split(eclipseBranchFormat, 2)[1];
- // Match the Eclipse branch format
- if (pokybranch != "master") {
- newval = eclipseRelease + "/" + pokybranch;
- } else {
- newval = eclipseRelease + "-master";
- }
- } else if (elements[i].name == "branch_refkit") {
- // Refkit only tracks OE-Core master
- newval = "master";
- } else if (elements[i].name == "branch_meta-qt3") {
- // won't get a rocko, or newer, branch
- if (['jethro', 'krogoth', 'morty', 'pyro'].indexOf(pokybranch) < 0) {
- newval = "master"
- }
- } else if (elements[i].name == "branch_meta-gplv2") {
- // only has pyro and master branches
- if (pokybranch != "pyro") {
- newval = "master"
- }
- }
- elements[i].value = newval;
- }
-}
-
-// ]]>
-</script>
-{% endblock %}
-
-{% block content %}
-
-<h1>Builder {{ name }}</h1>
-
-<p>(<a href="{{ path_to_root }}waterfall?show={{ name }}">view in waterfall</a>)</p>
-
-{% if description %}
- <div class="BuilderDescription">{{ description }}</div>
-{% endif %}
-
-<div class="column">
-
-{% if current %}
- <h2>Current Builds:</h2>
- <ul>
- {% for b in current %}
- <li><a href="{{ b.link }}">{{ b.num }}</a>
- {% if b.when %}
- ETA: {{ b.when_time }} [{{ b.when }}]
- {% endif %}
-
- {{ b.current_step }}
-
- {% if authz.advertiseAction('stopBuild', request) %}
- {{ forms.stop_build(b.stop_url, authz, on_all=False, short=True, label='Build') }}
- {% endif %}
- </li>
- {% endfor %}
- </ul>
-{% else %}
- <h2>No current builds</h2>
-{% endif %}
-
-{% if pending %}
- <h2>Pending Build Requests:</h2>
- <ul>
- {% for b in pending %}
- <li><small>({{ b.when }}, waiting {{ b.delay }})</small>
-
- {% if authz.advertiseAction('cancelPendingBuild', request) %}
- {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=True, id=b.id) }}
- {% endif %}
-
- {% if b.num_changes < 4 %}
- {% for c in b.changes %}{{ c.revision|shortrev(c.repo) }}
- (<a href="{{ c.url }}">{{ c.who|email }}</a>){% if not loop.last %},{% endif %}
- {% endfor %}
- {% else %}
- ({{ b.num_changes }} changes)
- {% endif %}
-
- {% if 'owner' in b.properties %}
- <b>Forced build</b>
- by {{b.properties['owner'][0]}}
- <small>{{b.properties['reason'][0]}}</small>
- {% endif %}
- </li>
- {% endfor %}
- </ul>
-
- {% if authz.advertiseAction('cancelPendingBuild', request) %}
- {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=False, id='all') }}
- {% endif %}
-
-{% else %}
- <h2>No Pending Build Requests</h2>
-{% endif %}
-
-<h2>Recent Builds:</h2>
-
-{{ build_table(recent) }}
-
-<a href="?numbuilds={{numbuilds + 5}}">Show more</a>
-
-</div>
-<div class="column">
-
-<h2>Buildslaves:</h2>
-<table class="info">
-{% if slaves %}
-<tr>
- <th>Name</th>
- <th>Status</th>
- <th>Admin</th>
-</tr>
-{% endif %}
-{% for s in slaves %}
- <tr class="{{ loop.cycle('alt', '') }}">
- <td><b><a href="{{ s.link|e }}">{{ s.name|e }}</a></b></td>
- {% if s.connected %}
- {% if s.paused %}
- <td class="paused">paused</td>
- {% else %}
- <td class="idle">connected</td>
- {% endif %}
- {% else %}
- <td class="offline">offline</td>
- {% endif %}
- <td>{{ s.admin|email if s.admin else ""}}</td>
- </tr>
-{% else %}
- <td>no slaves attached</td>
-{% endfor %}
-</table>
-
-{% if authz.advertiseAction('pingBuilder', request) %}
- <h2>Ping slaves</h2>
- {{ forms.ping_builder(builder_url+"/ping", authz) }}
-{% endif %}
-
-{% if authz.advertiseAction('forceBuild', request) and force_schedulers != {} %}
- <h2>Force build</h2>
- {{ forms.force_build(builder_url+"/force", authz, request, False, force_schedulers=force_schedulers,default_props=default_props) }}
-{% endif %}
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html
deleted file mode 100644
index 67cb0225..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html
+++ /dev/null
@@ -1,50 +0,0 @@
-{% extends 'layout.html' %}
-{% import 'forms.html' as forms %}
-{% from "box_macros.html" import box %}
-
-{% block content %}
-<h1>Builders: {{ branches|join(', ')|e }}</h1>
-
-<table>
-{% for b in builders %}
- <tr>
- <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td>
- {% if b.build_url %}
- <td class="LastBuild box {{ b.build_css_class }}">
- <a href="{{ b.build_url }}">{{ b.build_label }}</a>
- <br/>{{ b.build_text }}
- </td>
- {% else %}
- <td class="LastBuild box">no build</td>
- {% endif %}
- {{ box(**b.current_box) }}
- </tr>
-{% endfor %}
-</table>
-
-{% if num_building > 0 %}
- {% if authz.advertiseAction('stopAllBuilds', request) or authz.advertiseAction('stopBuild', request) %}
- <h2>Stop Selected Builds</h2>
- {{ forms.stop_build(path_to_root+"builders/_selected/stopselected", authz, on_selected=True, builders=builders, label='Selected Builds') }}
- <h2>Stop All Builds</h2>
- {{ forms.stop_build(path_to_root+"builders/_all/stopall", authz, on_all=True, label='All Builds') }}
- {% endif %}
-{% endif %}
-
-{% if authz.advertiseAction('cancelAllPendingBuilds', request) %}
- <h2>Cancel Selected Pending Builds</h2>
- {{ forms.cancel_build(path_to_root+"builders/_selected/cancelpendingselected", authz, on_selected=True, builders=builders, label='Selected Pending Builds') }}
- <h2>Cancel All Pending Builds</h2>
- {{ forms.cancel_build(path_to_root+"builders/_all/cancelpendingall", authz, on_all=True, label='All Pending Builds') }}
-{% endif %}
-
-{% if num_online > 0 %}
- {% if authz.advertiseAction('forceAllBuilds', request) or authz.advertiseAction('forceBuild', request) %}
- <h2>Force Selected Builds</h2>
- {{ forms.force_build(path_to_root+"builders/_selected/forceselected", authz, request, on_selected=True, builders=builders, force_schedulers=force_schedulers, default_props=default_props) }}
- <h2>Force All Builds</h2>
- {{ forms.force_build(path_to_root+"builders/_all/forceall", authz,request, on_all=True, force_schedulers=force_schedulers, default_props=default_props) }}
- {% endif %}
-{% endif %}
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html
deleted file mode 100644
index d9f55038..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html
+++ /dev/null
@@ -1,68 +0,0 @@
-{% from 'build_line.html' import build_table, build_line %}
-{% import 'forms.html' as forms %}
-
-{% extends "layout.html" %}
-{% block content %}
-<h1>Buildslave: {{ slavename|e }}</h1>
-
-<div class="column">
-
-{% if current %}
- <h2>Currently building:</h2>
- <ul>
- {% for b in current %}
- <li>{{ build_line(b, True) }}
- <form method="post" action="{{ b.buildurl }}/stop" class="command stopbuild" style="display:inline">
- <input type="submit" value="Stop Build" />
- <input type="hidden" name="url" value="{{ this_url }}" />
- </form>
- </li>
- {% endfor %}
- </ul>
-{% else %}
- <h2>No current builds</h2>
-{% endif %}
-
-<h2>Recent builds</h2>
-{{ build_table(recent, True) }}
-
-</div>
-<div class="column">
-{% if access_uri %}
- <a href="{{ access_uri|e }}">Click to Access Slave</a>
-{% endif %}
-
-{% if admin %}
- <h2>Administrator</h2>
- <p>{{ admin|email }}</p>
-{% endif %}
-
-{% if host %}
- <h2>Slave information</h2>
- Buildbot-Slave {{ slave_version }}
- <pre>{{ host|e }}</pre>
-{% endif %}
-
-<h2>Connection Status</h2>
-<p>
-{{ connect_count }} connection(s) in the last hour
-{% if not slave.isConnected() %}
-(not currently connected)
-{% else %}
-</p>
- {% if authz.advertiseAction('gracefulShutdown', request) %}
- <h2>Graceful Shutdown</h2>
- {% if slave.getGraceful() %}
- <p>Slave will shut down gracefully when it is idle.</p>
- {% else %}
- {{ forms.graceful_shutdown(shutdown_url, authz) }}
- {% endif %}
- {% endif %}
- {% if authz.advertiseAction('pauseSlave', request) %}
- <h2>Pause Slave</h2>
- {{ forms.pause_slave(pause_url, authz, slave.isPaused()) }}
- {% endif %}
-{% endif %}
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html
deleted file mode 100644
index 567e3747..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html
+++ /dev/null
@@ -1,76 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Buildslaves</h1>
-
-<div class="column">
-
-<table class="info">
-
-<tr>
- <th>Name</th>
- {%- if show_builder_column %}
- <th>Builders</th>
- {%- endif %}
- <th>BuildBot</th>
- <th>Admin</th>
- <th>Last heard from</th>
- <th>Connects/Hour</th>
- <th>Status</th>
-</tr>
-
-{% for s in slaves %}
- <tr class="{{ loop.cycle('alt','') }}">
- <td><b><a href="{{ s.link }}">{{ s.name }}</a></b></td>
-
- {%- if show_builder_column %}
- <td>
- {%- if s.builders %}
- {%- for b in s.builders %}
- <a href="{{ b.link }}">{{ b.name }}</a>
- {%- endfor %}
- {%- else %}
- <span class="Warning">no builders</span>
- {%- endif -%}
- </td>
- {%- endif %}
-
-
- <td>{{ (s.version or '-')|e }}</td>
-
- {%- if s.admin -%}
- <td>{{ s.admin|email }}</td>
- {%- else -%}
- <td>-</td>
- {%- endif -%}
-
- <td>
- {%- if s.last_heard_from_age -%}
- {{ s.last_heard_from_age }} <small>({{ s.last_heard_from_time }})</small>
- {%- endif -%}
- </td>
- <td>
- {{ s.connectCount }}
- </td>
-
- {% if s.connected %}
- {% if s.running_builds %}
- <td class="building">Running {{ s.running_builds }} build(s)</td>
- {% elif s.paused %}
- <td class="paused">Paused</td>
- {% else %}
- <td class="idle">Idle</td>
- {% endif %}
-
- {% else %}
- <td class="offline">Not connected</td>
- {% endif %}
-
- </tr>
-{% endfor %}
-</table>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html
deleted file mode 100644
index df33878a..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% extends "layout.html" %}
-{% from "box_macros.html" import box %}
-
-{% block header %}
-{% endblock %}
-
-{% block barecontent %}
-<table>
- {% for r in rows %}
- <tr>{{ box(**r) }}</tr>
- {% endfor %}
-
- <tr>{{ box(**build) }}</tr>
-</table>
-{% endblock %}
-
-{% block footer %}
-{% endblock %}
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html
deleted file mode 100644
index c2c75140..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>
- Builder <a href="{{ builder_link }}">{{ b.getBuilder().getName() }}</a>
- build <a href="{{ build_link }}">#{{ b.getNumber() }}</a>
- step <a href="">{{ s.getName() }}</a>
-</h1>
-
-<div class="column">
-
-{% if s.isFinished() %}
- <h2>Finished</h2>
- <p class="{{ result_css }} result">
- {%- set text = s.getText() -%}
- {%- if text is string %}{{ text|e }}
- {%- else %}{{ text|join(" ")|e }}{% endif -%}
- </p>
-{% else %}
- <h2>Not Finished</h2>
- <p>ETA {{ s.getETA()|e }} seconds</p>
-{% endif %}
-
-{% set exp = s.getExpectations() %}
-{% if exp %}
- <h2>Expectations</h2>
- <ul>
- {% for e in exp %}
- <li>{{ e[0]|e }}: current={{ e[1] }}, target={{ e[2] }}</li>
- {% endfor %}
- </ul>
-{% endif %}
-
-<h2>Timing</h2>
-{% if start %}
- <table class="info">
- <tr class="alt"><td class="left">Start</td><td>{{ start }}</td></tr>
- <tr><td class="left">End</td><td>{{ end or "Not finished" }}</td></tr>
- <tr class="alt"><td class="left">Elapsed</td><td>{{ elapsed }}</td></tr>
- </table>
-{% else %}
- <b>Not started</b>
-{% endif %}
-
-<h2>Logs</h2>
-<ul>
-{% for l in logs %}
- <li class="{{ loop.cycle('alt', '') }}">
- {% if l.has_contents %}
- <a href="{{ l.link|e }}">{{ l.name|e }}</a>
- {% else %}
- {{ l.name|e }}
- {% endif %}
- </li>
-{% else %}
- <li class="alt">- No logs -</li>
-{% endfor %}
-</ul>
-
-{% if statistics %}
-<h2>Statistics</h2>
-<table class="info">
- <tr><th>Name</th><th>Value</th></tr>
- {% for stat in statistics %}
- <tr class="{{ loop.cycle('alt', '') }}"><td>{{ stat.name|e }}</td><td>{{ stat.value|e }}</td></tr>
- {% endfor %}
-</table>
-{% endif %}
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html
deleted file mode 100644
index f12161da..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "layout.html" %}
-{% from "change_macros.html" import change with context %}
-{% import 'forms.html' as forms %}
-
-{% block content %}
-
-<h1>{{ pageTitle }}</h1>
-
-<div class="column">
-
-{{ change(c) }}
-
-{% if authz.advertiseAction('stopChange', request) %}
- <h3>Cancel Builds For Change:</h3>
- {{ forms.stop_change_builds("/builders/_all/stopchangeall", c.number, authz) }}
-{% endif %}
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html
deleted file mode 100644
index 2ca01d9f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html
+++ /dev/null
@@ -1,76 +0,0 @@
-{% macro change(c) %}
-
-<table class="info">
- {% set row_class=cycler('alt','') %}
- <tr class="{{ row_class.next() }}">
- <td class="left">Category</td>
- <td><b>{{ c.category }}</b></td>
- </tr>
- <tr class="{{ row_class.next() }}">
- <td class="left">Changed by</td>
- <td><b>{{ c.who|email }}</b></td>
- </tr>
- <tr class="{{ row_class.next() }}">
- <td class="left">Changed at</td>
- <td><b>{{ c.at }}</b></td>
- </tr>
-
- {% if c.repository %}
- <tr class="{{ row_class.next() }}">
- <td class="left">Repository</td>
- <td><b>{{ c.repository|repolink }}</b></td>
- </tr>
- {% endif %} {% if c.project %}
- <tr class="{{ row_class.next() }}">
- <td class="left">Project</td>
- <td><b>{{ c.project|projectlink }}</b></td>
- </tr>
- {% endif %} {% if c.branch %}
- <tr class="{{ row_class.next() }}">
- <td class="left">Branch</td>
- <td><b>{{ c.branch|e }}</b></td>
- </tr>
- {% endif %} {% if c.rev %}
- <tr class="{{ row_class.next() }}">
- <td class="left">Revision</td>
- <td>{%- if c.revlink -%}<a href="{{ c.revlink }}">{{ c.rev|e }}</a>
- {%- else -%}{{ c.rev|revlink(c.repository) }} {%- endif -%}</td>
- </tr>
- {% endif %}
-</table>
-
-{% if c.comments %}
-<h3>Comments</h3>
-<pre class="comments">{{ c.comments|changecomment(c.project) }}</pre>
-{% endif %}
-
-<h3 class="files">Changed files</h3>
-<ul>
- {% for f in c.files -%}
- <li class="{{ loop.cycle('alt', '') }}">{%- if f.url %}<a
- href="{{ f.url }}"><b>{{ f.name|e }}</b></a></li>
- {%- else %}
- <b>{{ f.name|e }}</b>
- {%- endif -%}
- </li>
- {% else %}
- <li>no files</li>
- {% endfor %}
-</ul>
-
-{% if c.properties %}
-<h3>Properties</h3>
-<table class="info">
- {% for p in c.properties %}
- <tr class="{{ loop.cycle('alt') }}">
- <td class="left">{{ p[0]|capitalize|e }}</td>
- <td>{{ p[1]|e }}</td>
- </tr>
- {% endfor %}
-</table>
-{% endif %}
-{%- endmacro %}
-
-{% macro box_contents(who, url, pageTitle, revision, project) -%}
-<a href="{{ url }}" title="{{ pageTitle|e }}">{{ who|user }}</a>
-{%- endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html
deleted file mode 100644
index 24674dd5..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html
+++ /dev/null
@@ -1,21 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Changesources</h1>
-
-<div class="column">
-
-{% if sources %}
- <ol>
- {% for s in sources -%}
- <li class="{{ loop.cycle('alt', '') }}">{{ s.describe() }}</li>
- {% endfor -%}
- </ol>
-{% else %}
- none (push only)
-{% endif %}
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html
deleted file mode 100644
index a51c946e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html
+++ /dev/null
@@ -1,276 +0,0 @@
-{% extends "layout.html" %}
-
-{% block head %}
-{{ super() }}
-<script type='text/javascript'>
-// <![CDATA[
-//
-
-//
-// Functions used to display the build status bubble on box click.
-//
-
-// show the build status box. This is called when the user clicks on a block.
-function showBuildBox(url, event) {
- // Find the current curson position.
- var cursorPosTop = (window.event ? window.event.clientY : event.pageY)
- var cursorPosLeft = (window.event ? window.event.clientX : event.pageX)
-
- // Offset the position by 5, to make the window appears under the cursor.
- cursorPosTop = cursorPosTop + document.body.scrollTop -5 ;
- cursorPosLeft = cursorPosLeft + document.body.scrollLeft - 5;
-
- // Move the div (hidden) under the cursor.
- var divBox = document.getElementById('divBox');
- divBox.style.top = parseInt(cursorPosTop) + 'px';
- divBox.style.left = parseInt(cursorPosLeft) + 'px';
-
- // Reload the hidden frame with the build page we want to show.
- // The onload even on this frame will update the div and make it visible.
- document.getElementById("frameBox").src = url
-
- // We don't want to reload the page.
- return false;
-}
-
-// OnLoad handler for the iframe containing the build to show.
-function updateDiv(event) {
- // Get the frame innerHTML.
- var iframeContent = document.getElementById("frameBox").contentWindow.document.body.innerHTML;
-
- // If there is any content, update the div, and make it visible.
- if (iframeContent) {
- var divBox = document.getElementById('divBox');
- divBox.innerHTML = iframeContent ;
- divBox.style.display = "block";
- }
-}
-
-// Util functions to know if an element is contained inside another element.
-// We use this to know when we mouse out our build status div.
-function containsDOM (container, containee) {
- var isParent = false;
- do {
- if ((isParent = container == containee))
- break;
- containee = containee.parentNode;
- } while (containee != null);
-
- return isParent;
-}
-
-// OnMouseOut handler. Returns true if the mouse moved out of the element.
-// It is false if the mouse is still in the element, but in a blank part of it,
-// like in an empty table cell.
-function checkMouseLeave(element, event) {
- if (element.contains && event.toElement) {
- return !element.contains(event.toElement);
- }
- else if (event.relatedTarget) {
- return !containsDOM(element, event.relatedTarget);
- }
-}
-
-// ]]>
-</script>
-{% endblock %}
-
-{% block content %}
-
-<h1>Console View</h1>
-
-<div align="center">
- <table width="95%" class="Grid" border="0" cellspacing="0">
- <tr>
- <td width="33%" align="left" class="left_align">
-{% if categories|length > 1 %}
- <br><b>Categories:</b> {% for c in categories %}{{ c.name|e }} {% endfor %}
-{% endif %}
-{% if codebase %}
- <br><b>Codebase:</b> {{ codebase|e }}
-{% endif %}
-{% if repository %}
- <br><b>Repository:</b> {{ repository|e }}
-{% endif %}
-{% if project %}
- <br><b>Project:</b> {{ project|e }}
-{% endif %}
-{% if branch != ANYBRANCH %}
- <br><b>Branch:</b> {{ branch|e }}
-{% endif %}
- </td>
- <td width="33%" align="center" class="center_align">
- <div align="center">
- <table class="info">
- <tr>
- <td>Legend:&nbsp;&nbsp;</td>
- <td class='legend success' title='All tests passed'>Passed</td>
- <td class='legend failure' title='There is a new failure. Take a look!'>Failed</td>
- <td class='legend warnings' title='Build has warnings'>Warnings</td>
- <td class='legend failure-again' title='It was failing before, and it is still failing. Make sure you did not introduce new regressions'>Failed&nbsp;Again</td>
- <td class='legend running' title='The tests are still running'>Running</td>
- <td class='legend exception' title='Something went wrong with the test, there is no result'>Exception</td>
- <td class='legend offline' title='The builder is offline, as there are no slaves connected to it'>Offline</td>
- <td class='legend notstarted' title='No result yet.'>No&nbsp;data</td>
- </tr>
- </table>
- </div>
- </td>
- <td width="33%" align="right" class="right_align">
- <script type="text/javascript">
-// <![CDATA[
- function reload_page() {
- name_value = document.getElementById('namebox').value
- if (document.location.href.lastIndexOf('?') == -1)
- document.location.href = document.location.href+ '?name=' + name_value;
- else
- document.location.href = document.location.href+ '&name=' + name_value;
- }
-// ]]>
- </script>
- <form onsubmit='reload_page()'>
- <input id='namebox' name='name' type='text' style='color:#999;'
- onblur='this.value = this.value || this.defaultValue; this.style.color = "#999";'
- onfocus='this.value=""; this.style.color = "#000";'
- value='Personalized for...'/>
- <input type='submit' value='Go'/>
- </form>
- </td>
- </tr>
- </table>
-</div>
-
-<br/>
-
-{% set alt_class = cycler('', 'Alt') %}
-
-<div align="center">
-<table width="96%">
-
-{% if categories|length > 1 %}
- <tr>
- <td width="1%">
- </td>
- <td width="1%">
- </td>
- {% for c in categories %}
- <td class='DevStatus {{ alt_class.next() }} {{ "first" if loop.first else '' }} {{ "last" if loop.last else '' }}' width='{{ c.size }}%'>
- {{ c.name|e }}
- </td>
- {% endfor %}
- </tr>
- <tr class='DevStatusSpacing'>
- </tr>
-{% endif %}
-
-{% if slaves %}
- <tr>
- <td width="1%">
- </td>
- <td width="1%">
- </td>
- {% for c in categories %}
- <td class='DevSlave {{ alt_class.next() }}'>
- <table width="100%">
- <tr>
- {% for s in slaves[c.name] %}
- <td class='DevSlaveBox'>
- <a href='{{ s.url }}' title='{{ s.pageTitle }}' class='DevSlaveBox {{ s.color }}' target="_blank">
- </a>
- </td>
- {% endfor %}
- </tr>
- </table>
- </td>
- {% endfor %}
- </tr>
-{% endif %}
-
-{% for r in revisions %}
- {% set alt = alt_class.next() %}
- {% set firstrev = "first" if loop.first else '' %}
-
- <tr>
- <td class='DevRev {{ alt }}' width="1%">
- {{ r.id|shortrev(r.repository) }}
- </td>
- <td class='DevName {{ alt }}' width="1%">
- {{ r.who|user }}
- </td>
-
- {% for c in categories %}
- {% set last = "last" if loop.last else "" %}
- <td class='DevStatus {{ alt }} {{ last if not firstrev else '' }}'>
- <table width="100%">
- <tr>
- {% for b in r.builds[c.name] %}
- <td class='DevStatusBox'>
- <a href='#' onclick='showBuildBox("{{ b.url }}", event); return false;'
- title='{{ b.pageTitle|e }}' class='DevStatusBox {{ b.color }} {{ b.tag }}'
- target="_blank"></a>
- </td>
- {% endfor %}
- </tr>
- </table>
- </td>
- {% endfor %}
- </tr>
-
- <tr>
- <td colspan="{{ r.span }}" class='DevComment {{ alt }} {% if not r.details %}DevBottom{% endif %}'>
- {{ r.comments|changecomment(r.project or None)|replace('\n', '<br/>')|replace(' ','&nbsp; ') }}
- </td>
- </tr>
-
- {% if r.details %}
- <tr>
- <td colspan="{{ r.span }}" class='DevDetails {{ alt }} DevBottom'>
- <ul style='margin: 0px; padding: 0 0 0 1.5em;'>
- {% for d in r.details %}
- <li>{{ d.buildername }}: {{ d.status }} - &nbsp;
- {%- for l in d.logs -%}
- <a href="{{ l.url }}">{{ l.name }}</a>
- {%- endfor -%}
- </li>
- {% endfor %}
- </ul>
- </td>
- </tr>
- {% endif %}
-
- <tr class='DevStatusSpacing'>
- <td>
- </td>
- </tr>
-
-{% else %}
- <tr><td>No revisions available</td></tr>
-{% endfor %}
-
-</table>
-</div>
-
-
-<div id="divBox" onmouseout="if (checkMouseLeave(this, event)) this.style.display = 'None'" class="BuildWaterfall">
-</div>
-
-
-<iframe id="frameBox" style="display: none;"></iframe>
-
-<script type="text/javascript">
-// replace 'onload="updateDiv(event);" with this, as iframe doesn't have onload event in xhtml
-window.onload = function() {
- document.getElementById('frameBox').onload = function(event) {
- updateDiv(event);
- };
-};
-</script>
-
-{% endblock %}
-
-
-{% block footer %}
-
-{{ super() }}
-{# <p>Debug info: {{ debuginfo }}</p> #}
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html
deleted file mode 100644
index 662355de..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Directory listing for {{ path }}</h1>
-
-{% set row_class = cycler('alt', '') %}
-
-<table>
-
-<tr class="{{ row_class.next() }}">
-<th style="min-width:18em">Name</th>
-<th style="min-width:8em">Size</th>
-<th style="min-width:10em">Type</th>
-<th style="min-width:10em">Encoding</th>
-</tr>
-
-{% for d in directories %}
- <tr class="directory {{ row_class.next() }}">
- <td><a href="{{ d.href }}"><b>{{ d.text }}</b></a></td>
- <td><b>{{ d.size }}</b></td>
- <td><b>{{ d.type }}</b></td>
- <td><b>{{ d.encoding }}</b></td>
- </tr>
-{% endfor %}
-
-{% for f in files %}
- <tr class="file {{ row_class.next() }}">
- <td><a href="{{ f.href }}">{{ f.text }}</a></td>
- <td>{{ f.size }}</td>
- <td>{{ f.type }}</td>
- <td>{{ f.encoding }}</td>
- </tr>
-{% endfor %}
-</table>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html
deleted file mode 100644
index 91f4e591..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-{{ content }}
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml
deleted file mode 100644
index c423e7b0..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-{% from 'feed_description.html' import item_desc %}
-
-<?xml version="1.0" encoding="utf-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom">
- <id>{{ title_url }}</id>
- <title>{{ pageTitle|e }}</title>
- {% if project_url -%}
- <link rel="self" href="{{ title_url }}/atom"/>
- <link rel="alternate" href="{{ title_url }}"/>
- {% endif %}
- {%- if description -%}
- <subtitle>{{ description }}</subtitle>
- {% endif %}
- {%- if rfc3339_pubdate -%}
- <updated>{{ rfc3339_pubdate }}</updated>
- {% endif -%}
- <author>
- <name>BuildBot</name>
- </author>
-
- {% for b in builds -%}
- <entry>
- <title>{{ b.pageTitle }}</title>
- <link href="{{ b.link }}"/>
- <content type="xhtml">
- <div xmlns="http://www.w3.org/1999/xhtml">
- {{ item_desc(b, title_url, title)|indent(6) }}
- <pre xml:space="preserve">{{ b.log_lines|join('\n')|e }}</pre>
- </div>
- </content>
- {% if b.rfc3339_pubdate -%}
- <updated>{{ b.rfc3339_pubdate }}</updated>
- <id>{{ b.guid }}</id>
- {% endif -%}
- <author>Buildbot</author>
- </entry>
-
- {% endfor -%}
-
-</feed>
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html
deleted file mode 100644
index 7f387c67..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html
+++ /dev/null
@@ -1,18 +0,0 @@
-{% from 'feed_sources.html' import srcs_desc %}
-
-{% macro item_desc(b, title_url, title) -%}
- <p>
- Date: {{ b.date }}<br/>
- Project home: <a href="{{ title_url }}">{{ title|e }}</a><br/>
- Builder summary: <a href="{{ b.summary_link }}">{{ b.name }}</a><br/>
- Build details: <a href="{{ b.link }}">Build {{ b.number }}</a><br/>
- Author list: <b>{{ b.responsible_users|join(', ') }}</b><br/>
- Failed step(s): <b>{{ b.failed_steps|join(', ') }}</b><br/>
- </p>
- {% for src in b.sources %}
- {{ srcs_desc(src) }}
- {% endfor %}
- <p>
- <i>Last lines of the build log:</i>
- </p>
-{%- endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml
deleted file mode 100644
index 9f30112a..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-{% from 'feed_description.html' import item_desc %}
-
-<?xml version="1.0" encoding="utf-8"?>
-<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
- <channel>
- <title>{{ pageTitle|e }}</title>
- <link>{{ title_url }}</link>
- <atom:link href="{{ title_url }}rss" rel="self" type="application/rss+xml"/>
- {% if language -%}
- <language>{{ language }}</language>
- {% endif %}
- {%- if description -%}
- <description>{{ description }}</description>
- {% endif %}
- {%- if rfc822_pubdate -%}
- <pubDate>{{ rfc822_pubdate }}</pubDate>
- {% endif %}
-
- {% for b in builds -%}
- <item>
- <title>{{ b.pageTitle }}</title>
- <link>{{ b.link }}</link>
- <description>
- <![CDATA[
- {{ item_desc(b, title_url, title)|indent(8) }}
- <pre>{{ b.log_lines|join('\n')|e }}</pre>
- ]]>
- </description>
- {% if b.rfc822_pubdate -%}
- <pubDate>{{ b.rfc822_pubdate }}</pubDate>
- <guid isPermaLink="false">{{ b.guid }}</guid>
- {%- endif %}
-
- </item>
-
- {% endfor %}
-
- </channel>
-</rss>
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html
deleted file mode 100644
index 4ec3bc8f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% macro srcs_desc(src) -%}
- <div>
- {%- if src.codebase -%}
- <b>Codebase: {{ src.codebase }}</b><br/>
- {% endif %}
- <p>
- Repository: {{ src.repository }}<br/>
- {%- if src.branch -%}
- Branch: {{ src.branch }}<br/>
- {% endif %}
- {%- if src.revision -%}
- Revision: {{ src.revision }}<br/>
- {% endif %}
- </p>
- </div>
-{%- endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html
deleted file mode 100644
index 30c664c7..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<hr />
-<div class="footer">
-
-<a href="{{ welcomeurl }}">Welcome Page</a>
-<br />
-
-<a href="http://buildbot.net/">Buildbot</a>-{{ version }}
-
-{% if title %}
- working for
- {% if title_url %}
- <a href="{{ title_url }}">{{ title }}</a>
- {% else %}
- {{ title }}
- {% endif %}
- project
-{% endif %}
-
-<br />
-
-Page built: {{ time }} ({{ tz }})
-</div>
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html
deleted file mode 100644
index 133c465a..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html
+++ /dev/null
@@ -1,288 +0,0 @@
-
-{% macro cancel_pending_build(cancel_url, authz, short=False, id='all') %}
- <form method="post" name="cancel" action="{{ cancel_url }}" class='command cancelbuild'
- {{ 'style="display:inline"' if short else '' }}>
- {% if not short %}
- {% if id == 'all' %}
- <p>To cancel all builds, push the 'Cancel' button</p>
- <p>To cancel individual builds, click the 'Cancel' buttons above.</p>
- {% else %}
- <p>To cancel this build, push the 'Cancel' button</p>
- {% endif %}
- {% endif %}
- <input type="hidden" name="id" value="{{ id }}" />
- <input type="submit" value="Cancel" />
- </form>
-{% endmacro %}
-
-{% macro stop_change_builds(stopchange_url, changenum, authz) %}
- {% if not changenum %}
- <form method="post" action="{{ stopchange_url }}" class='command stopchange'>
- {% if changenum %}
- <p>To cancel all builds for this change, push the 'Cancel' button</p>
- {% else %}
- <p>To cancel builds for this builder for a given change, fill out the
- following field and push the 'Cancel' button</p>
- {% endif %}
-
- {% if changenum %}
- <input type="hidden" name="change" value="{{ changenum }}" />
- {% else %}
- <div class="row">
- <span class="label">Change #:</span>
- <input type="text" name="change"/>
- </div>
- {% endif %}
- <input type="submit" value="Cancel" />
- </form>
- {% endif %}
-{% endmacro %}
-
-{% macro stop_build(stop_url, authz, on_all=False, on_selected=False, builders=[], short=False, label="Build") %}
- {% if not short %}
- <form method="post" name="stop_build" action="{{ stop_url }}" class='command stopbuild'
- {{ 'style="display:inline"' if short else '' }}>
- {% if not short %}
- {% if on_all %}
- <p>To stop all builds, fill out the following field and
- push the <i>Stop {{ label }}</i> button</p>
- {% elif on_selected %}
- <p>To stop selected builds, select the builders, fill out the
- following field and push the <i>Stop {{ label }}</i> button</p>
- <table>
- {% for b in builders %}
- <tr>
- <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td>
- <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td>
- </tr>
- {% endfor %}
- </table>
-
- {% else %}
- <p>To stop this build, fill out the following field and
- push the <i>Stop {{ label }}</i> button</p>
- {% endif %}
- {% endif %}
-
- {% if not short %}
- <div class="row">
- <span class="label">Reason:</span>
- <input type="text" name="comments"/>
- </div>
- {% endif %}
-
- <input type="submit" value="Stop {{ label }}" />
- </form>
- {% endif %}
-{% endmacro %}
-
-{% macro cancel_build(cancel_url, authz, on_all=False, on_selected=False, builders=[], short=False, label="Build") %}
- {% if not short %}
- <form method="post" name="cancel_build" action="{{ cancel_url }}" class='command cancelbuild'
- {{ 'style="display:inline"' if short else '' }}>
- {% if not short %}
- {% if on_all %}
- <p>To cancel all pending builds, fill out the following field and
- push the <i>Cancel {{ label }}</i> button</p>
- {% elif on_selected %}
- <p>To cancel selected pending builds, select the builders, fill out the
- following field and push the <i>Cancel {{ label }}</i> button</p>
- <table>
- {% for b in builders %}
- <tr>
- <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td>
- <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td>
- </tr>
- {% endfor %}
- </table>
-
- {% else %}
- <p>To cancel this pending build, fill out the following field and
- push the <i>Cancel {{ label }}</i> button</p>
- {% endif %}
- {% endif %}
-
- {% if not short %}
- <div class="row">
- <span class="label">Reason:</span>
- <input type="text" name="comments"/>
- </div>
- {% endif %}
-
- <input type="submit" value="Cancel {{ label }}" />
- </form>
- {% endif %}
-{% endmacro %}
-
-{% macro force_build_scheduler_parameter(f, authz, request, sch, default_props) %}
- {% if f and not f.hide and (f.fullName != "username" or not authz.authenticated(request)) %}
- <div class="row{% for subtype in f.type %} force-{{subtype}}{%endfor%}"{% if f.name %} id="force-{{sch.name}}-{{f.fullName}}"{% endif %}>
- {% if 'text' in f.type or 'int' in f.type %}
- <span class="label">{{f.label}}</span>
- <input type='text' size='{{f.size}}' name='{{f.fullName}}' value='{{default_props[sch.name+"."+f.fullName]}}' />
- {% elif 'bool' in f.type%}
- <input type='checkbox' name='checkbox' value='{{f.fullName}}' {{default_props[sch.name+"."+f.fullName]}} />
- <span class="label">{{f.label}}</span>
- {% elif 'textarea' in f.type %}
- <span class="label">{{f.label}}</span>
- <textarea name='{{f.fullName}}' rows={{f.rows}} cols={{f.cols}}>{{default_props[sch.name+"."+f.fullName]}}</textarea>
- {% elif 'list' in f.type %}
- <span class="label">{{f.label}}</span>
- <span class="select">
- <select name='{{f.fullName}}' {{ f.multiple and "multiple" or ""}}>
- {% for c in default_props[sch.name+"."+f.fullName+".choices"] %}
- <option {{(c in default_props[sch.name+"."+f.fullName]) and "selected" or ""}}>{{c}}</option>
- {% endfor %}
- </select>
- </span>
- {% elif 'nested' in f.type %}
- {% if f.label %}<span class="label">{{f.label}}</span>{% endif %}
- {% for subfield in f.fields %}
- {{ force_build_scheduler_parameter(subfield, authz, request, sch, default_props) }}
- {% endfor %}
- {% endif %}
- </div>
- {% endif %}
-{% endmacro %}
-
-{% macro force_build_one_scheduler(force_url, authz, request, on_all, on_selected, builders, sch, default_props) %}
- <form method="post" name="force_build" action="{{ force_url }}" class="command_forcebuild">
-
- <h3>{{ sch.name|e }}</h3>
- {% if on_all %}
- <p>To force a build on <strong>all Builders</strong>, fill out the following fields
- and push the 'Force Build' button</p>
- {% elif on_selected %}
- <p>To force a build on <strong>certain Builders</strong>, select the
- builders, fill out the following fields and push the
- 'Force Build' button</p>
-
- <table>
- {% for b in builders %}
- {% if b.name in sch.builderNames %}
- <tr>
- <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td>
- <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td>
- </tr>
- {% endif %}
- {% endfor %}
- </table>
-
- {% else %}
- <p>To force a build, fill out the following fields and
- push the 'Force Build' button</p>
- {% endif %}
- <input type='hidden' name='forcescheduler' value='{{sch.name}}' />
- <p>
- <hr />
- {% if "nightly" in sch.builderNames %}
- Set up branch values for Poky branch: <select id ="select_release"
- name="build_release" onchange="updateFormBranchInputs(this.value)">
- <option value="master" selected>master</option>
- <option value="rocko">rocko</option>
- <option value="pyro">pyro</option>
- <option value="morty">morty</option>
- <option value="krogoth">krogoth</option>
- </select>
- <hr/>
- {% endif %}
-
- {% for f in sch.all_fields %}
- {{ force_build_scheduler_parameter(f, authz, request, sch, default_props) }}
- {% endfor %}
-
- <input type="submit" value="Force Build" />
- </form>
-{% endmacro %}
-{% macro force_build(force_url, authz, request, on_all=False, on_selected=False, builders=[], force_schedulers={},default_props={}) %}
- {% for name, sch in force_schedulers.items() | sort %}
- {{ force_build_one_scheduler(force_url, authz, request, on_all, on_selected, builders, sch, default_props=default_props) }}
- {% endfor %}
-
-{% endmacro %}
-
-{% macro graceful_shutdown(shutdown_url, authz) %}
- <form method="post" action="{{ shutdown_url }}" class='command graceful_shutdown'>
-
- <p>To cause this slave to shut down gracefully when it is idle,
- push the 'Graceful Shutdown' button</p>
- <input type="submit" value="Graceful Shutdown" />
- </form>
-{% endmacro %}
-
-{% macro pause_slave(pause_url, authz, paused) %}
- <form method="post" action="{{ pause_url }}" class='command pause_slave'>
-
- {% if paused %}
- <p>To cause this slave to start running new builds again,
- push the 'Unpause Slave' button</p>
- {% else %}
- <p>To cause this slave to stop running new builds,
- push the 'Pause Slave' button</p>
- {% endif %}
-
- {% if paused %}
- <input type="submit" value="Unpause Slave" />
- {% else %}
- <input type="submit" value="Pause Slave" />
- {% endif %}
- </form>
-{% endmacro %}
-
-{% macro clean_shutdown(shutdown_url, authz) %}
- <form method="post" action="{{ shutdown_url }}" class='command clean_shutdown'>
- <p>To cause this master to shut down cleanly, push the 'Clean Shutdown' button.</p>
- <p>No other builds will be started on this master, and the master will
- stop once all current builds are finished.</p>
-
- <input type="submit" value="Clean Shutdown" />
- </form>
-{% endmacro %}
-
-{% macro cancel_clean_shutdown(cancel_shutdown_url, authz) %}
- <form method="post" action="{{ cancel_shutdown_url }}" class='command cancel_clean_shutdown'>
- <p>To cancel a previously initiated shutdown, push the 'Cancel Shutdown' button.</p>
-
- <input type="submit" value="Cancel Shutdown" />
- </form>
-{% endmacro %}
-
-{% macro ping_builder(ping_url, authz) %}
- <form method="post" action="{{ ping_url }}" class='command ping_builder'>
- <p>To ping the buildslave(s), push the 'Ping' button</p>
- <input type="submit" value="Ping Builder" />
- </form>
-{% endmacro %}
-
-{% macro rebuild_build(rebuild_url, authz, ss) %}
- <form method="post" action="{{ rebuild_url }}" class="command rebuild">
-
- {% if on_all %}
- <p>To force a build on <strong>all Builders</strong>, fill out the following fields
- and push the 'Force Build' button</p>
- {% else %}
- <p>To force a build, fill out the following fields and
- push the 'Force Build' button</p>
- {% endif %}
- <div class="row">
- <span class="label">Reason for re-running build:</span>
- <input type='text' name='comments' />
- </div>
- <div class="row">
- Rebuild using:
- <select name="useSourcestamp">
- <option value='exact' selected>Exact same revisions</option>
- <option value='updated'>Same sourcestamps (ignoring 'got revision')</option>
- </select>
- </div>
- <input type="submit" value="Rebuild" />
- </form>
-{% endmacro %}
-
-{% macro show_users(users_url, authz) %}
- <form method="post" action="{{ users_url }}" class='command show_users'>
- <p>To show users, press the 'Show Users' button</p>
-
- <input type="submit" value="Show Users" />
- </form>
-{% endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html
deleted file mode 100644
index ed44ea10..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{% extends "layout.html" %}
-{% import 'grid_macros.html' as grid with context %}
-
-{% block content %}
-
-<h1>Grid View</h1>
-
-<table class="Grid" border="0" cellspacing="0">
-
-<tr>
- <td class="title"><a href="{{ title_url }}">{{ title }}</a>
- {{ grid.category_title() }}
- </td>
-
- {% for i in range %}
- {{ grid.stamp_td(stamps[i], build_triggers[i]) }}
- {% endfor %}
-</tr>
-
-{% for builder in builders %}
- <tr>
- {{ grid.builder_td(builder) }}
- {% for build in builder.builds %}
- {{ grid.build_td(build) }}
- {% endfor %}
- </tr>
-{% endfor %}
-
-</table>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html
deleted file mode 100644
index 42a1b451..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html
+++ /dev/null
@@ -1,65 +0,0 @@
-{% macro category_title() -%}
- {% if categories %}
- <br>
- {% trans categories=categories %}
- <b>Category:</b></br>
- {% pluralize categories %}
- <b>Categories:</b><br/>
- {% endtrans %}
- {% for c in categories %}
- {{ c|e }}<br/>
- {% endfor %}
- {% endif %}
-
- {% if branch != ANYBRANCH %}
- <br><b>Branch:</b> {{ branch|e or "trunk" }}
- {% endif %}
-{%- endmacro %}
-
-
-{% macro stamp_td(sourcestamps, trigger) -%}
- <td valign="bottom" class="sourcestamp">
- {% for ss in sourcestamps %}
- {%- if ss.codebase %}{{ ss.codebase|e }}: {% endif %}
- {%- if ss.revision -%}
- <br/><b>Commit: </b>{{ ss.revision|shortrev(ss.repository) }}
- {%- else %}<br/><b>Commit: </b>latest{% endif %}
- {%- if ss.branch %} in {{ ss.branch|e }}{% endif %}
- {%- if ss.hasPatch %} [patch]{% endif -%}
- (<a href="http://errors.yoctoproject.org/Errors/Latest/Autobuilder/?filter={{ss.revision}}&type=commit">errors</a>,
- <a href="https://wiki.yoctoproject.org/wiki/BuildLog#{{trigger.builder}}_{{trigger.id}}_-_{{ss.branch}}_{{ss.revision}}">log</a>)
- <br/>
- {%- endfor %}
- </td>
-{%- endmacro %}
-
-{% macro builder_td(b) -%}
- <td valign="middle" style="text-align: center" class="builder {{ b.state }}">
- <a href="{{ b.url }}">{{ b.name }}</a>
- {%- if b.state != 'idle' or b.n_pending > 0 -%}
- <br/>({{ b.state }}
- {%- if b.n_pending > 0 -%}
- , plus {{ b.n_pending }}
- {%- endif -%}
- )
- {%- endif -%}
- {%- if b.time %}<br/><b>Time: </b> {{ b.time }} {% endif %}
- </td>
-{%- endmacro %}
-
-{% macro build_td(build) -%}
-{% if build %}
- <td valign="top" class="build {{ build.class }}" style="text-align: left" style="white-space: nowrap" valign="bottom" >
- {%- if build.release_name %}<br/><b>RELEASE NAME:</b> {{ build.release_name }}{% endif %}
- {%- if build.branchshortname %}<br/><b>Branch:</b> {{ build.branchshortname }} {% endif %}
- {%- if build.repository %}<br/><b>Repo: </b>
- {%- if build.cgiturl %} <a href="{{ build.cgiturl }}"> {% endif %}
- {{ build.repository }}
- {%- if build.cgiturl %} </a> {% endif %}
- {% endif %}
- <br/><b>Build:</b> <a href="{{ build.url }}">{{ build.text|join('<br/>') }}</a>
- </td>
-{% else %}
- <td class="build">&nbsp;</td>
-{% endif %}
-{%- endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html
deleted file mode 100644
index 9b6cadad..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html
+++ /dev/null
@@ -1,30 +0,0 @@
-{% extends "layout.html" %}
-{% import 'grid_macros.html' as grid with context %}
-
-{% block content %}
-
-<h1>Transposed Grid View</h1>
-
-<table class="Grid" border="0" cellspacing="0">
-
-<tr>
- <td class="title"><a href="{{ title_url }}">{{ title }}</a>
- {{ grid.category_title() }}
- </td>
- {% for builder in builders %}
- {{ grid.builder_td(builder) }}
- {% endfor %}
-</tr>
-
-{% for i in range %}
- <tr>
- {{ grid.stamp_td(stamps[i], build_triggers[i]) }}
- {% for b in builder_builds %}
- {{ grid.build_td(b[i]) }}
- {% endfor %}
- </tr>
-{% endfor %}
-
-</table>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html
deleted file mode 100644
index 63c155b9..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "layout.html" %}
-{% block content %}
-
-<p>{{ text }}</p>
-<h2>More Help:</h2>
-
-{% if level != 1 %}
-<p><a href="../help">Parent's Help</a></p>
-{% endif %}
-
-{% if children %}
-<p>Child Nodes</p>
-<ul>
-{% for child in children %}
- <li><a href="{{ child|e }}">{{ child|e }}</a>
- (<a href="{{ child|e }}/help">{{ child|e }}/help</a>)
- </li>
-{% endfor %}
-</ul>
-{% endif %}
-
-<h2>Flags:</h2>
-{{ flags }}
-
-<h2>Examples:</h2>
-{{ examples }}
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html
deleted file mode 100644
index 01dfb80c..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html
+++ /dev/null
@@ -1,90 +0,0 @@
-{%- block doctype -%}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-{% endblock %}
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- {% block head %}
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- {% if metatags %}
- {{ metatags }}
- {% endif %}
- {% if refresh %}
- <meta http-equiv="refresh" content="{{ refresh|e }}"/>
- {% endif %}
- <title>{{ pageTitle|e }}</title>
- <link rel="stylesheet" href="{{ stylesheet }}" type="text/css" />
- <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ path_to_root }}rss">
- <link rel="shortcut icon" href="{{ path_to_root }}favicon.ico">
- {% endblock %}
- </head>
- <body class="interface">
- {% block header -%}
- <div class="header">
- <a href="{{ path_to_root or '.' }}">Home</a>
- {% if authz.advertiseAction('view', request) %}
- - <a href="{{ path_to_root }}waterfall">Waterfall</a>
- <a href="{{ path_to_root }}grid">Grid</a>
- <a href="{{ path_to_root }}tgrid">T-Grid</a>
- <a href="{{ path_to_root }}console">Console</a>
- <a href="{{ path_to_root }}builders">Builders</a>
- <a href="{{ path_to_root }}one_line_per_build">Recent Builds</a>
- <a href="{{ path_to_root }}buildslaves">Buildslaves</a>
- <a href="{{ path_to_root }}changes">Changesources</a>
- {% if authz.advertiseAction('showUsersPage', request) %}
- <a href="{{ path_to_root }}users">Users</a>
- {% endif %}
- - <a href="{{ path_to_root }}json/help">JSON API</a>
- - <a href="{{ path_to_root }}about">About</a>
- {% endif %}
- <div class="auth">
- {% if authz.authenticated(request) %}
- {{ authz.getUsernameHTML(request) }}
- |<a href="{{ path_to_root }}logout">Logout</a>
- {% elif authz.useHttpHeader and authz.httpLoginUrl %}
- <a href="{{ authz.httpLoginUrl }}">Login</a>
- {% elif authz.auth %}
- <form method="post" name="login" action="{{ path_to_root }}login">
- <input type="text" name="username" size=10 />
- <input type="password" name="passwd" size=10 />
- <input type="submit" value="login" />
- </form>
- {% endif %}
- </div>
- </div>
- {% endblock %}
-
- {%- block barecontent -%}
- <hr/>
-
- {% if alert_msg != "" %}
- <div class="alert">
- {{ alert_msg }}
- </div>
- {% endif %}
-
- <div class="content">
- {%- block content -%}
- {%- endblock -%}
- </div>
- {%- endblock -%}
-
- {%- block footer -%}
- <div class="footer" style="clear:both">
- <hr/>
- <a href="http://buildbot.net/">BuildBot</a> ({{version}})
- {% if title -%}
- working for the&nbsp;
- {%- if title_url -%}
- <a href="{{ title_url }}">{{ title }}</a>
- {%- else -%}
- {{ title }}
- {%- endif -%}
- &nbsp;project.
- {%- endif -%}
- <br/>
- Page built: <b>{{ time }}</b> ({{ tz }})
- </div>
- {% endblock -%}
- </body>
-</html>
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html
deleted file mode 100644
index 116bbd6a..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{%- macro page_header(pageTitle, path_to_root, texturl) -%}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html>
- <head><title>{{ pageTitle }}</title>
- <link rel="stylesheet" href="{{ path_to_root }}default.css" type="text/css" />
- </head>
- <body class='log'>
- <a href="{{ texturl }}">(view as text)</a><br/>
- <pre>
-{%- endmacro -%}
-
-{%- macro chunks(entries) -%}
-{%- for entry in entries -%}
- <span class="{{ entry.type }}">{{ entry.text|e }}</span>
-{%- endfor -%}
-{%- endmacro -%}
-
-{%- macro page_footer() -%}
-</pre>
-</body>
-</html>
-{%- endmacro -%}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html
deleted file mode 100644
index d2484465..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "layout.html" %}
-{% from 'build_line.html' import build_table %}
-{% import 'forms.html' as forms %}
-
-{% block content %}
-<h1>Last {{ num_builds }} finished builds: {{ branches|join(', ')|e }}</h1>
-
-{% if builders %}
- <p>of builders: {{ builders|join(", ")|e }}</p>
-{% endif %}
-
-<div class="column">
-
-{{ build_table(builds, True) }}
-
-</div>
-<div class="column">
-
-{% if num_building > 0 %}
- {% if authz.advertiseAction('stopBuild', request) %}
- <h2>Stop All Builds</h2>
- {{ forms.stop_build("builders/_all/stopall", authz, on_all=True, label='All Builds') }}
- {% endif %}
-{% endif %}
-
-{% if num_online > 0 %}
- {% if authz.advertiseAction('forceAllBuilds', request) %}
- <h2>Force All Builds</h2>
- {{ forms.force_build("builders/_all/forceall", authz, request, True, force_schedulers=force_schedulers, default_props=default_props) }}
- {% endif %}
-{% endif %}
-
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html
deleted file mode 100644
index 051501f2..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html
+++ /dev/null
@@ -1,18 +0,0 @@
-{% extends "layout.html" %}
-{% from 'build_line.html' import build_line %}
-
-{% block content %}
-
-<h1>Last {{ num_builds }} builds of builder {{ builder_name|e }}:
- {{ branches|join(', ')|e }}
-</h1>
-
-<ul>
-{% for b in builds %}
- <li>{{ build_line(b) }}</li>
-{% else %}
- <li>No matching builds found</li>
-{% endfor %}
-</ul>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html
deleted file mode 100644
index 87a87a02..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html
+++ /dev/null
@@ -1,35 +0,0 @@
-{# both macro pairs must have the same signature #}
-
-{% macro id_replace(rev, url) -%}
- <span class="revision" title="Revision {{ rev }}"><a href="{{ url }}">
- {%- if rev|length > 40 %}{{ rev[:40] }}...
- {%- else %}{{ rev }}
- {%- endif -%}
- </a></span>
-{%- endmacro %}
-
-{% macro shorten_replace(short, rev, url) %}
- <div class="revision">
- <div class="short" title="Revision {{ rev }}">
- <a href="{{ url }}">{{ short }}...</a>
- </div>
- <div class="full">
- <a href="{{ url }}">{{ rev }}</a>
- </div>
- </div>
-{% endmacro %}
-
-{% macro id(rev, url) -%}
- <span class="revision" title="Revision {{ rev }}">
- {%- if rev|length > 40 %}{{ rev[:40] }}...
- {%- else %}{{ rev }}
- {%- endif -%}
- </span>
-{%- endmacro %}
-
-{% macro shorten(short, rev, url) %}
- <div class="revision">
- <div class="short" title="Revision {{ rev }}">{{ short }}...</div>
- <div class="full">{{ rev }}</div>
- </div>
-{% endmacro %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html
deleted file mode 100644
index 561973e4..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% extends 'layout.html' %}
-{% import 'forms.html' as forms %}
-
-{% block content %}
-
-<h1>Welcome to the Buildbot
-{%- if title -%}
- &nbsp;for the&nbsp;
- {%- if title_url -%}
- <a href="{{ title_url }}">{{ title }}</a>
- {%- else -%}
- {{ title }}
- {%- endif -%}
-&nbsp;project
-{%- endif -%}
-!
-</h1>
-
-<div class="column">
-
-<ul>
- {% set item_class=cycler('alt', '') %}
-
- <li class="{{ item_class.next() }}">The <a href="waterfall">Waterfall Display</a> will give you a
- time-oriented summary of recent buildbot activity. <a href="waterfall/help">Waterfall Help.</a></li>
-
- <li class="{{ item_class.next() }}">The <a href="grid">Grid Display</a> will give you a
- developer-oriented summary of recent buildbot activity.</li>
-
- <li class="{{ item_class.next() }}">The <a href="tgrid">Transposed Grid Display</a> presents
- the same information as the grid, but lists the revisions down the side.</li>
-
- <li class="{{ item_class.next() }}">The <a href="console">Console</a> presents
- a user-oriented status page.</li>
-
- <li class="{{ item_class.next() }}">The <a href="builders">Builders</a> and their most recent builds are
- here.</li>
-
- <li class="{{ item_class.next() }}"><a href="one_line_per_build">Recent Builds</a> are summarized here, one
- per line.</li>
-
- <li class="{{ item_class.next() }}"><a href="buildslaves">Buildslave</a> information</li>
- <li class="{{ item_class.next() }}"><a href="changes">Changesource</a> information.</li>
-
- <li class="{{ item_class.next() }}"><a href="about">About</a> this Buildbot</li>
-</ul>
-
-{%- if authz.advertiseAction('cleanShutdown', request) -%}
-{%- if shutting_down -%}
-Master is shutting down<br/>
-{{ forms.cancel_clean_shutdown(cancel_shutdown_url, authz) }}
-{%- else -%}
-{{ forms.clean_shutdown(shutdown_url, authz) }}
-{%- endif -%}
-{%- endif -%}
-
-<p><i>This and other pages can be overridden and customized.</i></p>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html
deleted file mode 100644
index 70dac7ae..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>
- Builder <a href="{{ builder_link }}">{{ b.getBuilder().getName() }}</a>
- build <a href="{{ build_link }}">#{{ b.getNumber() }}</a>
- test <a href="">{{ '.'.join(tr.getName()) }}</a>
-</h1>
-
-<div class="column">
-
- <h2>Result</h2>
- <p class="{{ result_css }} result">
- {{ result_word }}
- {%- set text = tr.getText() -%}
- {%- if text is string %}{{ text|e }}
- {%- else %}{{ text|join(" ")|e }}{% endif -%}
- </p>
-
-<h2>Logs</h2>
-<ul>
-{% for l in logs %}
- <h3>Log: {{ l.name|e }}</h3>
- <samp><pre>{{ l.log|e }}</pre></samp>
- </br>
-{% else %}
- <li class="alt">- No logs -</li>
-{% endfor %}
-</ul>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html
deleted file mode 100644
index eb136175..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>User: {{ user_identifier|e }}</h1>
-
-<div class="column">
-
-<table class="info">
-
-<tr>
- <th>Attribute Type</th>
- <th>Attribute Value</th>
-</tr>
-
-{% for attr in user %}
- <tr class="{{ loop.cycle('alt','') }}">
-
- <td>{{ attr|e }}</td>
- <td>{{ user[attr]|e }}</td>
-
- </tr>
-{% endfor %}
-
-</table>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html
deleted file mode 100644
index 5cb2dafc..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% extends "layout.html" %}
-
-{% block content %}
-
-<h1>Users</h1>
-
-<table class="info">
-
-<tr>
- <th>Uid</th>
- <th>Identifier</th>
-</tr>
-
-{% for user in users %}
- <tr class="{{ loop.cycle('alt','') }}">
-
- <td><b><a href="{{ user.user_link }}">{{ user.uid }}</a></b></td>
- <td>{{ user.identifier|e }}</td>
-
- </tr>
-{% endfor %}
-
-</table>
-
-</div>
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html
deleted file mode 100644
index e380406e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html
+++ /dev/null
@@ -1,66 +0,0 @@
-{% extends "layout.html" %}
-{% from "box_macros.html" import box %}
-
-{% block content %}
-
-<div>
- <h1 style="display: inline;">Waterfall</h1>
- <a style="float: right;" href="{{ help_url }}">waterfall help</a>
-</div>
-
-<table border="0" cellspacing="0">
-
-<tr class="LastBuild">
- <td align="right" colspan="2" class="Project">
- last build
- </td>
-
-{% for b in builders %}
- <td align="center" class="{{ b.top_class }}">
- <a href="{{ b.url }}">{{ b.name }}</a><br/>
- {{ " ".join(b.top) }}
- </td>
-{% endfor %}
-</tr>
-
-<tr class="Activity">
-<td align="right" colspan="2">current activity</td>
-
-{% for b in builders %}
- <td align="center" class="{{ b.status_class }}">
- {{ "<br/>".join(b.status) }}
- </td>
-{% endfor %}
-</tr>
-
-<tr>
-<td align="center" class="Time">{{ tz }}</td>
-<td align="center" class="Change"><a href="{{ changes_url }}">changes</a></td>
-
-{% for b in builders %}
- <td align="center" class="Builder"><a href="{{ b.url }}">{{ b.name }}</a></td>
-{% endfor %}
-</tr>
-
-{# waterfall contents goes here #}
-{% for i in range(gridlen) -%}
- <tr>
- {% for strip in grid -%}
- {%- if strip[i] -%}{{ box(**strip[i]) }}
- {%- elif no_bubble -%}{{ box() }}
- {%- endif -%}
- {%- endfor -%}
- </tr>
-{% endfor %}
-
-</table>
-
-{% if nextpage %}
- <a href="{{ nextpage }}">next page</a>
-{% endif %}
-
-{% if no_reload_page %}
- <a href="{{ no_reload_page }}">Stop Reloading</a>
-{% endif %}
-
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html
deleted file mode 100644
index c0e5ec6e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html
+++ /dev/null
@@ -1,140 +0,0 @@
-{% extends "layout.html" %}
-{% block content %}
-
-<form action="../waterfall" method="get">
-
-<h1>The Waterfall Display</h1>
-
-<p>The Waterfall display can be controlled by adding query arguments to the
-URL. For example, if your Waterfall is accessed via the URL
-<tt>http://buildbot.example.org:8080</tt>, then you could add a
-<tt>branch=</tt> argument (described below) by going to
-<tt>http://buildbot.example.org:8080?branch=beta4</tt> instead. Remember that
-query arguments are separated from each other with ampersands, but they are
-separated from the main URL with a question mark, so to add a
-<tt>branch=</tt> and two <tt>builder=</tt> arguments, you would use
-<tt>http://buildbot.example.org:8080?branch=beta4&amp;builder=unix&amp;builder=macos</tt>.</p>
-
-<h2>Limiting the Displayed Interval</h2>
-
-<p>The <tt>last_time=</tt> argument is a unix timestamp (seconds since the
-start of 1970) that will be used as an upper bound on the interval of events
-displayed: nothing will be shown that is more recent than the given time.
-When no argument is provided, all events up to and including the most recent
-steps are included.</p>
-
-<p>The <tt>first_time=</tt> argument provides the lower bound. No events will
-be displayed that occurred <b>before</b> this timestamp. Instead of providing
-<tt>first_time=</tt>, you can provide <tt>show_time=</tt>: in this case,
-<tt>first_time</tt> will be set equal to <tt>last_time</tt> minus
-<tt>show_time</tt>. <tt>show_time</tt> overrides <tt>first_time</tt>.</p>
-
-<p>The display normally shows the latest 200 events that occurred in the
-given interval, where each timestamp on the left hand edge counts as a single
-event. You can add a <tt>num_events=</tt> argument to override this this.</p>
-
-<h2>Showing non-Build events</h2>
-
-<p>By passing <tt>show_events=true</tt>, you can add the "buildslave
-attached", "buildslave detached", and "builder reconfigured" events that
-appear in-between the actual builds.</p>
-
-<p>
-<input type="checkbox" name="show_events" value="true"
-{% if show_events_checked %} checked="checked" {% endif %}/>
-Show non-Build events
-</p>
-
-<h2>Showing only Certain Branches</h2>
-
-<p>If you provide one or more <tt>branch=</tt> arguments, the display will be
-limited to builds that used one of the given branches. If no <tt>branch=</tt>
-arguments are given, builds from all branches will be displayed.</p>
-
-Erase the text from these "Show Branch:" boxes to remove that branch filter.
-
-{% if branches %}
-<table>
- {% for b in branches %}
- <tr>
- <td>Show Branch:
- <input type="text" name="branch" value="{{ b|e }}"/>
- </td>
- </tr>
- {% endfor %}
-</table>
-{% endif %}
-
-<h2>Limiting the Builders that are Displayed</h2>
-
-<p>By adding one or more <tt>builder=</tt> arguments, the display will be
-limited to showing builds that ran on the given builders. This serves to
-limit the display to the specific named columns. If no <tt>builder=</tt>
-arguments are provided, all Builders will be displayed.</p>
-
-<p>To view a Waterfall page with only a subset of Builders displayed, select
-the Builders you are interested in here.</p>
-
-<table>
-{% for bn in all_builders %}
- <tr><td><input type="checkbox" name="builder" value="{{ bn }}"
- {% if bn in show_builders %}checked="checked"{% endif %} />
- </td><td>{{bn}}</td></tr>
-{% endfor %}
-</table>
-
-<h2>Limiting the Builds that are Displayed</h2>
-
-<p>By adding one or more <tt>committer=</tt> arguments, the display will be
-limited to showing builds that were started by the given committer. If no
-<tt>committer=</tt> arguments are provided, all builds will be displayed.</p>
-
-<p>To view a Waterfall page with only a subset of Builds displayed, select
-the committers your are interested in here.</p>
-
-Erase the text from these "Show Committer:" boxes to remove that filter.
-
-{% if committers %}
- <table>
- {% for cn in committers %}
- <tr>
- <td>
- Show Committer: <input type="text" name="committer" value="{{ cn }}">
- </td>
- </tr>
- {% endfor %}
- </table>
-{% endif %}
-
-<h2>Showing only the Builders with failures</h2>
-
-<p>By adding the <tt>failures_only=true</tt> argument, the display will be limited
-to showing builders that are currently failing. A builder is considered
-failing if the last finished build was not successful, a step in the current
-build(s) failed, or if the builder is offline.</p>
-
-<p>
- <input type="checkbox" name="failures_only" value="true"
- {% if failures_only %}checked="checked"{% endif %}/>
- Show failures only
-</p>
-
-<h2>Auto-reloading the Page</h2>
-
-<p>Adding a <tt>reload=</tt> argument will cause the page to automatically
-reload itself after that many seconds.</p>
-
-<table>
-{% for value, name in times %}
- <tr><td><input type="radio" name="reload" value="{{ value|e }}"
- {% if value == current_reload_time %}checked="checked"{% endif %}/>
- </td><td>{{ name|e }}</td></tr>
-{% endfor %}
-</table>
-
-
-<h2>Reload Waterfall Page</h2>
-
-<input type="submit" value="View Waterfall" />
-</form>
-{% endblock %}
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py
deleted file mode 100644
index 52622982..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-import urllib
-from buildbot.status.web.base import HtmlResource, path_to_builder, \
- path_to_build, css_classes
-from buildbot.status.builder import Results
-
-# /builders/$builder/builds/$buildnum/steps/$stepname
-class StatusResourceBuildTest(HtmlResource):
- pageTitle = "Test Result"
- addSlash = True
-
- def __init__(self, build_status, test_result):
- HtmlResource.__init__(self)
- self.status = build_status
- self.test_result = test_result
-
- def content(self, req, cxt):
- tr = self.test_result
- b = self.status
-
- cxt['b'] = self.status
- logs = cxt['logs'] = []
- for lname, log in tr.getLogs().items():
- if isinstance(log, str):
- log = log.decode('utf-8')
- logs.append({'name': lname,
- 'log': log,
- 'link': req.childLink("logs/%s" % urllib.quote(lname)) })
-
- cxt['text'] = tr.text
- cxt['result_word'] = Results[tr.getResults()]
- cxt.update(dict(builder_link = path_to_builder(req, b.getBuilder()),
- build_link = path_to_build(req, b),
- result_css = css_classes[tr.getResults()],
- b = b,
- tr = tr))
-
- template = req.site.buildbot_service.templates.get_template("testresult.html")
- return template.render(**cxt)
-
- def getChild(self, path, req):
- # if path == "logs":
- # return LogsResource(self.step_status) #TODO we need another class
- return HtmlResource.getChild(self, path, req)
-
-
-
-# /builders/$builder/builds/$buildnum/steps
-class TestsResource(HtmlResource):
- addSlash = True
- nameDelim = '.' # Test result have names like a.b.c
-
- def __init__(self, build_status):
- HtmlResource.__init__(self)
- self.build_status = build_status
-
- def content(self, req, ctx):
- # TODO list the tests
- return "subpages show data for each test"
-
- def getChild(self, path, req):
- tpath = None
- if path:
- tpath = tuple(path.split(self.nameDelim))
- if tpath:
- tr = self.build_status.getTestResults().get(tpath)
- if tr:
- return StatusResourceBuildTest(self.build_status, tr)
- return HtmlResource.getChild(self, path, req)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py
deleted file mode 100644
index 953ae68f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import urllib
-from twisted.internet import defer
-from twisted.web.util import redirectTo
-from buildbot.status.web.base import HtmlResource, path_to_authzfail, \
- path_to_root, ActionResource
-
-class UsersActionResource(ActionResource):
-
- def __init__(self):
- self.action = "showUsersPage"
-
- @defer.inlineCallbacks
- def performAction(self, req):
- res = yield self.getAuthz(req).actionAllowed('showUsersPage', req)
- if not res:
- defer.returnValue(path_to_authzfail(req))
- return
- # show the table
- defer.returnValue(path_to_root(req) + "users")
-
-# /users/$uid
-class OneUserResource(HtmlResource):
- addSlash = False
- def __init__(self, uid):
- HtmlResource.__init__(self)
- self.uid = int(uid)
-
- def getPageTitle (self, req):
- return "Buildbot User: %s" % self.uid
-
- def content(self, request, ctx):
- status = self.getStatus(request)
-
- d = status.master.db.users.getUser(self.uid)
- def cb(usdict):
- ctx['user_identifier'] = usdict['identifier']
- user = ctx['user'] = {}
- for attr in usdict:
- if attr not in ['uid', 'identifier', 'bb_password']:
- user[attr] = usdict[attr]
-
- template = request.site.buildbot_service.templates.get_template("user.html")
- data = template.render(**ctx)
- return data
- d.addCallback(cb)
- return d
-
-# /users
-class UsersResource(HtmlResource):
- pageTitle = "Users"
- addSlash = True
-
- def __init__(self):
- HtmlResource.__init__(self)
-
- def getChild(self, path, req):
- return OneUserResource(path)
-
- @defer.inlineCallbacks
- def content(self, req, ctx):
- res = yield self.getAuthz(req).actionAllowed('showUsersPage', req)
- if not res:
- defer.returnValue(redirectTo(path_to_authzfail(req), req))
- return
-
- s = self.getStatus(req)
-
- usdicts = yield s.master.db.users.getUsers()
- users = ctx['users'] = usdicts
-
- for user in users:
- user['user_link'] = req.childLink(urllib.quote(str(user['uid']), ''))
- template = req.site.buildbot_service.templates.get_template(
- "users.html")
- defer.returnValue(template.render(**ctx))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py
deleted file mode 100644
index 681c5768..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py
+++ /dev/null
@@ -1,813 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-
-from zope.interface import implements
-from twisted.python import log, components
-from twisted.internet import defer
-import urllib
-
-import time, locale
-import operator
-
-from buildbot import interfaces, util
-from buildbot.status import builder, buildstep, build
-from buildbot.changes import changes
-
-from buildbot.status.web.base import Box, HtmlResource, IBox, ICurrentBox, \
- ITopBox, build_get_class, path_to_build, path_to_step, path_to_root, \
- map_branches
-
-
-def earlier(old, new):
- # minimum of two things, but "None" counts as +infinity
- if old:
- if new < old:
- return new
- return old
- return new
-
-def later(old, new):
- # maximum of two things, but "None" counts as -infinity
- if old:
- if new > old:
- return new
- return old
- return new
-
-
-class CurrentBox(components.Adapter):
- # this provides the "current activity" box, just above the builder name
- implements(ICurrentBox)
-
- def formatETA(self, prefix, eta):
- if eta is None:
- return []
- if eta < 60:
- return ["< 1 min"]
- eta_parts = ["~"]
- eta_secs = eta
- if eta_secs > 3600:
- eta_parts.append("%d hrs" % (eta_secs / 3600))
- eta_secs %= 3600
- if eta_secs > 60:
- eta_parts.append("%d mins" % (eta_secs / 60))
- eta_secs %= 60
- abstime = time.strftime("%H:%M", time.localtime(util.now()+eta))
- return [prefix, " ".join(eta_parts), "at %s" % abstime]
-
- def getBox(self, status, brcounts):
- # getState() returns offline, idle, or building
- state, builds = self.original.getState()
-
- # look for upcoming builds. We say the state is "waiting" if the
- # builder is otherwise idle and there is a scheduler which tells us a
- # build will be performed some time in the near future. TODO: this
- # functionality used to be in BuilderStatus.. maybe this code should
- # be merged back into it.
- upcoming = []
- builderName = self.original.getName()
- for s in status.getSchedulers():
- if builderName in s.listBuilderNames():
- upcoming.extend(s.getPendingBuildTimes())
- if state == "idle" and upcoming:
- state = "waiting"
-
- if state == "building":
- text = ["building"]
- if builds:
- for b in builds:
- eta = b.getETA()
- text.extend(self.formatETA("ETA in", eta))
- elif state == "offline":
- text = ["offline"]
- elif state == "idle":
- text = ["idle"]
- elif state == "waiting":
- text = ["waiting"]
- else:
- # just in case I add a state and forget to update this
- text = [state]
-
- # TODO: for now, this pending/upcoming stuff is in the "current
- # activity" box, but really it should go into a "next activity" row
- # instead. The only times it should show up in "current activity" is
- # when the builder is otherwise idle.
-
- # are any builds pending? (waiting for a slave to be free)
- brcount = brcounts[builderName]
- if brcount:
- text.append("%d pending" % brcount)
- for t in sorted(upcoming):
- if t is not None:
- eta = t - util.now()
- text.extend(self.formatETA("next in", eta))
- return Box(text, class_="Activity " + state)
-
-components.registerAdapter(CurrentBox, builder.BuilderStatus, ICurrentBox)
-
-
-class BuildTopBox(components.Adapter):
- # this provides a per-builder box at the very top of the display,
- # showing the results of the most recent build
- implements(IBox)
-
- def getBox(self, req):
- assert interfaces.IBuilderStatus(self.original)
- branches = [b for b in req.args.get("branch", []) if b]
- builder = self.original
- builds = list(builder.generateFinishedBuilds(map_branches(branches),
- num_builds=1))
- if not builds:
- return Box(["none"], class_="LastBuild")
- b = builds[0]
- url = path_to_build(req, b)
- text = b.getText()
- tests_failed = b.getSummaryStatistic('tests-failed', operator.add, 0)
- if tests_failed: text.extend(["Failed tests: %d" % tests_failed])
- # TODO: maybe add logs?
- class_ = build_get_class(b)
- return Box(text, urlbase=url, class_="LastBuild %s" % class_)
-components.registerAdapter(BuildTopBox, builder.BuilderStatus, ITopBox)
-
-class BuildBox(components.Adapter):
- # this provides the yellow "starting line" box for each build
- implements(IBox)
-
- def getBox(self, req):
- b = self.original
- number = b.getNumber()
- url = path_to_build(req, b)
- reason = b.getReason()
- template = req.site.buildbot_service.templates.get_template("box_macros.html")
- text = template.module.build_box(reason=reason,url=url,number=number)
- class_ = "start"
- if b.isFinished() and not b.getSteps():
- # the steps have been pruned, so there won't be any indication
- # of whether it succeeded or failed.
- class_ = build_get_class(b)
- return Box([text], class_="BuildStep " + class_)
-components.registerAdapter(BuildBox, build.BuildStatus, IBox)
-
-class StepBox(components.Adapter):
- implements(IBox)
-
- def getBox(self, req):
- urlbase = path_to_step(req, self.original)
- text = self.original.getText()
- if text is None:
- log.msg("getText() gave None", urlbase)
- text = []
- text = text[:]
- logs = self.original.getLogs()
-
- cxt = dict(text=text, logs=[], urls=[], stepinfo=self)
-
- for num in range(len(logs)):
- name = logs[num].getName()
- if logs[num].hasContents():
- url = urlbase + "/logs/%s" % urllib.quote(name)
- else:
- url = None
- cxt['logs'].append(dict(name=name, url=url))
-
- for name, target in self.original.getURLs().items():
- cxt['urls'].append(dict(link=target,name=name))
-
- template = req.site.buildbot_service.templates.get_template("box_macros.html")
- text = template.module.step_box(**cxt)
-
- class_ = "BuildStep " + build_get_class(self.original)
- return Box(text, class_=class_)
-components.registerAdapter(StepBox, buildstep.BuildStepStatus, IBox)
-
-
-class EventBox(components.Adapter):
- implements(IBox)
-
- def getBox(self, req):
- text = self.original.getText()
- class_ = "Event"
- return Box(text, class_=class_)
-components.registerAdapter(EventBox, builder.Event, IBox)
-
-
-class Spacer:
- implements(interfaces.IStatusEvent)
-
- def __init__(self, start, finish):
- self.started = start
- self.finished = finish
-
- def getTimes(self):
- return (self.started, self.finished)
- def getText(self):
- return []
-
-class SpacerBox(components.Adapter):
- implements(IBox)
-
- def getBox(self, req):
- #b = Box(["spacer"], "white")
- b = Box([])
- b.spacer = True
- return b
-components.registerAdapter(SpacerBox, Spacer, IBox)
-
-def insertGaps(g, showEvents, lastEventTime, idleGap=2):
- debug = False
-
- e = g.next()
- starts, finishes = e.getTimes()
- if debug: log.msg("E0", starts, finishes)
- if finishes == 0:
- finishes = starts
- if debug: log.msg("E1 finishes=%s, gap=%s, lET=%s" % \
- (finishes, idleGap, lastEventTime))
- if finishes is not None and finishes + idleGap < lastEventTime:
- if debug: log.msg(" spacer0")
- yield Spacer(finishes, lastEventTime)
-
- followingEventStarts = starts
- if debug: log.msg(" fES0", starts)
- yield e
-
- while 1:
- e = g.next()
- if not showEvents and isinstance(e, builder.Event):
- continue
- starts, finishes = e.getTimes()
- if debug: log.msg("E2", starts, finishes)
- if finishes == 0:
- finishes = starts
- if finishes is not None and finishes + idleGap < followingEventStarts:
- # there is a gap between the end of this event and the beginning
- # of the next one. Insert an idle event so the waterfall display
- # shows a gap here.
- if debug:
- log.msg(" finishes=%s, gap=%s, fES=%s" % \
- (finishes, idleGap, followingEventStarts))
- yield Spacer(finishes, followingEventStarts)
- yield e
- followingEventStarts = starts
- if debug: log.msg(" fES1", starts)
-
-
-class WaterfallHelp(HtmlResource):
- pageTitle = "Waterfall Help"
-
- def __init__(self, categories=None):
- HtmlResource.__init__(self)
- self.categories = categories
-
- def content(self, request, cxt):
- status = self.getStatus(request)
-
- cxt['show_events_checked'] = request.args.get("show_events", ["false"])[0].lower() == "true"
- cxt['branches'] = [b for b in request.args.get("branch", []) if b]
- cxt['failures_only'] = request.args.get("failures_only", ["false"])[0].lower() == "true"
- cxt['committers'] = [c for c in request.args.get("committer", []) if c]
-
- # this has a set of toggle-buttons to let the user choose the
- # builders
- show_builders = request.args.get("show", [])
- show_builders.extend(request.args.get("builder", []))
- cxt['show_builders'] = show_builders
- cxt['all_builders'] = status.getBuilderNames(categories=self.categories)
-
- # a couple of radio-button selectors for refresh time will appear
- # just after that text
- times = [("none", "None"),
- ("60", "60 seconds"),
- ("300", "5 minutes"),
- ("600", "10 minutes"),
- ]
- current_reload_time = request.args.get("reload", ["none"])
- if current_reload_time:
- current_reload_time = current_reload_time[0]
- if current_reload_time not in [t[0] for t in times]:
- times.insert(0, (current_reload_time, current_reload_time) )
-
- cxt['times'] = times
- cxt['current_reload_time'] = current_reload_time
-
- template = request.site.buildbot_service.templates.get_template("waterfallhelp.html")
- return template.render(**cxt)
-
-
-class ChangeEventSource(object):
- "A wrapper around a list of changes to supply the IEventSource interface"
- def __init__(self, changes):
- self.changes = changes
- # we want them in newest-to-oldest order
- self.changes.reverse()
-
- def eventGenerator(self, branches, categories, committers, minTime):
- for change in self.changes:
- if branches and change.branch not in branches:
- continue
- if categories and change.category not in categories:
- continue
- if committers and change.author not in committers:
- continue
- if minTime and change.when < minTime:
- continue
- yield change
-
-class WaterfallStatusResource(HtmlResource):
- """This builds the main status page, with the waterfall display, and
- all child pages."""
-
- def __init__(self, categories=None, num_events=200, num_events_max=None):
- HtmlResource.__init__(self)
- self.categories = categories
- self.num_events=num_events
- self.num_events_max=num_events_max
- self.putChild("help", WaterfallHelp(categories))
-
- def getPageTitle(self, request):
- status = self.getStatus(request)
- p = status.getTitle()
- if p:
- return "BuildBot: %s" % p
- else:
- return "BuildBot"
-
- def getChangeManager(self, request):
- # TODO: this wants to go away, access it through IStatus
- return request.site.buildbot_service.getChangeSvc()
-
- def get_reload_time(self, request):
- if "reload" in request.args:
- try:
- reload_time = int(request.args["reload"][0])
- return max(reload_time, 15)
- except ValueError:
- pass
- return None
-
- def isSuccess(self, builderStatus):
- # Helper function to return True if the builder is not failing.
- # The function will return false if the current state is "offline",
- # the last build was not successful, or if a step from the current
- # build(s) failed.
-
- # Make sure the builder is online.
- if builderStatus.getState()[0] == 'offline':
- return False
-
- # Look at the last finished build to see if it was success or not.
- lastBuild = builderStatus.getLastFinishedBuild()
- if lastBuild and lastBuild.getResults() != builder.SUCCESS:
- return False
-
- # Check all the current builds to see if one step is already
- # failing.
- currentBuilds = builderStatus.getCurrentBuilds()
- if currentBuilds:
- for build in currentBuilds:
- for step in build.getSteps():
- if step.getResults()[0] == builder.FAILURE:
- return False
-
- # The last finished build was successful, and all the current builds
- # don't have any failed steps.
- return True
-
- def content(self, request, ctx):
- status = self.getStatus(request)
- master = request.site.buildbot_service.master
-
- # before calling content_with_db_data, make a bunch of database
- # queries. This is a sick hack, but beats rewriting the entire
- # waterfall around asynchronous calls
-
- results = {}
-
- # recent changes
- changes_d = master.db.changes.getRecentChanges(40)
- def to_changes(chdicts):
- return defer.gatherResults([
- changes.Change.fromChdict(master, chdict)
- for chdict in chdicts ])
- changes_d.addCallback(to_changes)
- def keep_changes(changes):
- results['changes'] = changes
- changes_d.addCallback(keep_changes)
-
- # build request counts for each builder
- allBuilderNames = status.getBuilderNames(categories=self.categories)
- brstatus_ds = []
- brcounts = {}
- def keep_count(statuses, builderName):
- brcounts[builderName] = len(statuses)
- for builderName in allBuilderNames:
- builder_status = status.getBuilder(builderName)
- d = builder_status.getPendingBuildRequestStatuses()
- d.addCallback(keep_count, builderName)
- brstatus_ds.append(d)
-
- # wait for it all to finish
- d = defer.gatherResults([ changes_d ] + brstatus_ds)
- def call_content(_):
- return self.content_with_db_data(results['changes'],
- brcounts, request, ctx)
- d.addCallback(call_content)
- return d
-
- def content_with_db_data(self, changes, brcounts, request, ctx):
- status = self.getStatus(request)
- ctx['refresh'] = self.get_reload_time(request)
-
- # we start with all Builders available to this Waterfall: this is
- # limited by the config-file -time categories= argument, and defaults
- # to all defined Builders.
- allBuilderNames = status.getBuilderNames(categories=self.categories)
- builders = [status.getBuilder(name) for name in allBuilderNames]
-
- # but if the URL has one or more builder= arguments (or the old show=
- # argument, which is still accepted for backwards compatibility), we
- # use that set of builders instead. We still don't show anything
- # outside the config-file time set limited by categories=.
- showBuilders = request.args.get("show", [])
- showBuilders.extend(request.args.get("builder", []))
- if showBuilders:
- builders = [b for b in builders if b.name in showBuilders]
-
- # now, if the URL has one or category= arguments, use them as a
- # filter: only show those builders which belong to one of the given
- # categories.
- showCategories = request.args.get("category", [])
- if showCategories:
- builders = [b for b in builders if b.category in showCategories]
-
- # If the URL has the failures_only=true argument, we remove all the
- # builders that are not currently red or won't be turning red at the end
- # of their current run.
- failuresOnly = request.args.get("failures_only", ["false"])[0]
- if failuresOnly.lower() == "true":
- builders = [b for b in builders if not self.isSuccess(b)]
-
- (changeNames, builderNames, timestamps, eventGrid, sourceEvents) = \
- self.buildGrid(request, builders, changes)
-
- # start the table: top-header material
- locale_enc = locale.getdefaultlocale()[1]
- if locale_enc is not None:
- locale_tz = unicode(time.tzname[time.localtime()[-1]], locale_enc)
- else:
- locale_tz = unicode(time.tzname[time.localtime()[-1]])
- ctx['tz'] = locale_tz
- ctx['changes_url'] = request.childLink("../changes")
-
- bn = ctx['builders'] = []
-
- for name in builderNames:
- builder = status.getBuilder(name)
- top_box = ITopBox(builder).getBox(request)
- current_box = ICurrentBox(builder).getBox(status, brcounts)
- bn.append({'name': name,
- 'url': request.childLink("../builders/%s" % urllib.quote(name, safe='')),
- 'top': top_box.text,
- 'top_class': top_box.class_,
- 'status': current_box.text,
- 'status_class': current_box.class_,
- })
-
- ctx.update(self.phase2(request, changeNames + builderNames, timestamps, eventGrid,
- sourceEvents))
-
- def with_args(req, remove_args=[], new_args=[], new_path=None):
- # sigh, nevow makes this sort of manipulation easier
- newargs = req.args.copy()
- for argname in remove_args:
- newargs[argname] = []
- if "branch" in newargs:
- newargs["branch"] = [b for b in newargs["branch"] if b]
- for k,v in new_args:
- if k in newargs:
- newargs[k].append(v)
- else:
- newargs[k] = [v]
- newquery = "&amp;".join(["%s=%s" % (urllib.quote(k), urllib.quote(v))
- for k in newargs
- for v in newargs[k]
- ])
- if new_path:
- new_url = new_path
- elif req.prepath:
- new_url = req.prepath[-1]
- else:
- new_url = ''
- if newquery:
- new_url += "?" + newquery
- return new_url
-
- if timestamps:
- bottom = timestamps[-1]
- ctx['nextpage'] = with_args(request, ["last_time"],
- [("last_time", str(int(bottom)))])
-
-
- helpurl = path_to_root(request) + "waterfall/help"
- ctx['help_url'] = with_args(request, new_path=helpurl)
-
- if self.get_reload_time(request) is not None:
- ctx['no_reload_page'] = with_args(request, remove_args=["reload"])
-
- template = request.site.buildbot_service.templates.get_template("waterfall.html")
- data = template.render(**ctx)
- return data
-
- def buildGrid(self, request, builders, changes):
- debug = False
- # TODO: see if we can use a cached copy
-
- showEvents = False
- if request.args.get("show_events", ["false"])[0].lower() == "true":
- showEvents = True
- filterCategories = request.args.get('category', [])
- filterBranches = [b for b in request.args.get("branch", []) if b]
- filterBranches = map_branches(filterBranches)
- filterCommitters = [c for c in request.args.get("committer", []) if c]
- maxTime = int(request.args.get("last_time", [util.now()])[0])
- if "show_time" in request.args:
- minTime = maxTime - int(request.args["show_time"][0])
- elif "first_time" in request.args:
- minTime = int(request.args["first_time"][0])
- elif filterBranches or filterCommitters:
- minTime = util.now() - 24 * 60 * 60
- else:
- minTime = 0
- spanLength = 10 # ten-second chunks
- req_events=int(request.args.get("num_events", [self.num_events])[0])
- if self.num_events_max and req_events > self.num_events_max:
- maxPageLen = self.num_events_max
- else:
- maxPageLen = req_events
-
- # first step is to walk backwards in time, asking each column
- # (commit, all builders) if they have any events there. Build up the
- # array of events, and stop when we have a reasonable number.
-
- commit_source = ChangeEventSource(changes)
-
- lastEventTime = util.now()
- sources = [commit_source] + builders
- changeNames = ["changes"]
- builderNames = map(lambda builder: builder.getName(), builders)
- sourceNames = changeNames + builderNames
- sourceEvents = []
- sourceGenerators = []
-
- def get_event_from(g):
- try:
- while True:
- e = g.next()
- # e might be buildstep.BuildStepStatus,
- # builder.BuildStatus, builder.Event,
- # waterfall.Spacer(builder.Event), or changes.Change .
- # The showEvents=False flag means we should hide
- # builder.Event .
- if not showEvents and isinstance(e, builder.Event):
- continue
-
- if isinstance(e, buildstep.BuildStepStatus):
- # unfinished steps are always shown
- if e.isFinished() and e.isHidden():
- continue
-
- break
- event = interfaces.IStatusEvent(e)
- if debug:
- log.msg("gen %s gave1 %s" % (g, event.getText()))
- except StopIteration:
- event = None
- return event
-
- for s in sources:
- gen = insertGaps(s.eventGenerator(filterBranches,
- filterCategories,
- filterCommitters,
- minTime),
- showEvents,
- lastEventTime)
- sourceGenerators.append(gen)
- # get the first event
- sourceEvents.append(get_event_from(gen))
- eventGrid = []
- timestamps = []
-
- lastEventTime = 0
- for e in sourceEvents:
- if e and e.getTimes()[0] > lastEventTime:
- lastEventTime = e.getTimes()[0]
- if lastEventTime == 0:
- lastEventTime = util.now()
-
- spanStart = lastEventTime - spanLength
- debugGather = 0
-
- while 1:
- if debugGather: log.msg("checking (%s,]" % spanStart)
- # the tableau of potential events is in sourceEvents[]. The
- # window crawls backwards, and we examine one source at a time.
- # If the source's top-most event is in the window, is it pushed
- # onto the events[] array and the tableau is refilled. This
- # continues until the tableau event is not in the window (or is
- # missing).
-
- spanEvents = [] # for all sources, in this span. row of eventGrid
- firstTimestamp = None # timestamp of first event in the span
- lastTimestamp = None # last pre-span event, for next span
-
- for c in range(len(sourceGenerators)):
- events = [] # for this source, in this span. cell of eventGrid
- event = sourceEvents[c]
- while event and spanStart < event.getTimes()[0]:
- # to look at windows that don't end with the present,
- # condition the .append on event.time <= spanFinish
- if not IBox(event, None):
- log.msg("BAD EVENT", event, event.getText())
- assert 0
- if debug:
- log.msg("pushing", event.getText(), event)
- events.append(event)
- starts, finishes = event.getTimes()
- firstTimestamp = earlier(firstTimestamp, starts)
- event = get_event_from(sourceGenerators[c])
- if debug:
- log.msg("finished span")
-
- if event:
- # this is the last pre-span event for this source
- lastTimestamp = later(lastTimestamp,
- event.getTimes()[0])
- if debugGather:
- log.msg(" got %s from %s" % (events, sourceNames[c]))
- sourceEvents[c] = event # refill the tableau
- spanEvents.append(events)
-
- # only show events older than maxTime. This makes it possible to
- # visit a page that shows what it would be like to scroll off the
- # bottom of this one.
- if firstTimestamp is not None and firstTimestamp <= maxTime:
- eventGrid.append(spanEvents)
- timestamps.append(firstTimestamp)
-
- if lastTimestamp:
- spanStart = lastTimestamp - spanLength
- else:
- # no more events
- break
- if minTime is not None and lastTimestamp < minTime:
- break
-
- if len(timestamps) > maxPageLen:
- break
-
-
- # now loop
-
- # loop is finished. now we have eventGrid[] and timestamps[]
- if debugGather: log.msg("finished loop")
- assert(len(timestamps) == len(eventGrid))
- return (changeNames, builderNames, timestamps, eventGrid, sourceEvents)
-
- def phase2(self, request, sourceNames, timestamps, eventGrid,
- sourceEvents):
-
- if not timestamps:
- return dict(grid=[], gridlen=0)
-
- # first pass: figure out the height of the chunks, populate grid
- grid = []
- for i in range(1+len(sourceNames)):
- grid.append([])
- # grid is a list of columns, one for the timestamps, and one per
- # event source. Each column is exactly the same height. Each element
- # of the list is a single <td> box.
- lastDate = time.strftime("%d %b %Y",
- time.localtime(util.now()))
- for r in range(0, len(timestamps)):
- chunkstrip = eventGrid[r]
- # chunkstrip is a horizontal strip of event blocks. Each block
- # is a vertical list of events, all for the same source.
- assert(len(chunkstrip) == len(sourceNames))
- maxRows = reduce(lambda x,y: max(x,y),
- map(lambda x: len(x), chunkstrip))
- for i in range(maxRows):
- if i != maxRows-1:
- grid[0].append(None)
- else:
- # timestamp goes at the bottom of the chunk
- stuff = []
- # add the date at the beginning (if it is not the same as
- # today's date), and each time it changes
- todayday = time.strftime("%a",
- time.localtime(timestamps[r]))
- today = time.strftime("%d %b %Y",
- time.localtime(timestamps[r]))
- if today != lastDate:
- stuff.append(todayday)
- stuff.append(today)
- lastDate = today
- stuff.append(
- time.strftime("%H:%M:%S",
- time.localtime(timestamps[r])))
- grid[0].append(Box(text=stuff, class_="Time",
- valign="bottom", align="center"))
-
- # at this point the timestamp column has been populated with
- # maxRows boxes, most None but the last one has the time string
- for c in range(0, len(chunkstrip)):
- block = chunkstrip[c]
- assert(block != None) # should be [] instead
- for i in range(maxRows - len(block)):
- # fill top of chunk with blank space
- grid[c+1].append(None)
- for i in range(len(block)):
- # so the events are bottom-justified
- b = IBox(block[i]).getBox(request)
- b.parms['valign'] = "top"
- b.parms['align'] = "center"
- grid[c+1].append(b)
- # now all the other columns have maxRows new boxes too
- # populate the last row, if empty
- gridlen = len(grid[0])
- for i in range(len(grid)):
- strip = grid[i]
- assert(len(strip) == gridlen)
- if strip[-1] == None:
- if sourceEvents[i-1]:
- filler = IBox(sourceEvents[i-1]).getBox(request)
- else:
- # this can happen if you delete part of the build history
- filler = Box(text=["?"], align="center")
- strip[-1] = filler
- strip[-1].parms['rowspan'] = 1
- # second pass: bubble the events upwards to un-occupied locations
- # Every square of the grid that has a None in it needs to have
- # something else take its place.
- noBubble = request.args.get("nobubble",['0'])
- noBubble = int(noBubble[0])
- if not noBubble:
- for col in range(len(grid)):
- strip = grid[col]
- if col == 1: # changes are handled differently
- for i in range(2, len(strip)+1):
- # only merge empty boxes. Don't bubble commit boxes.
- if strip[-i] == None:
- next = strip[-i+1]
- assert(next)
- if next:
- #if not next.event:
- if next.spacer:
- # bubble the empty box up
- strip[-i] = next
- strip[-i].parms['rowspan'] += 1
- strip[-i+1] = None
- else:
- # we are above a commit box. Leave it
- # be, and turn the current box into an
- # empty one
- strip[-i] = Box([], rowspan=1,
- comment="commit bubble")
- strip[-i].spacer = True
- else:
- # we are above another empty box, which
- # somehow wasn't already converted.
- # Shouldn't happen
- pass
- else:
- for i in range(2, len(strip)+1):
- # strip[-i] will go from next-to-last back to first
- if strip[-i] == None:
- # bubble previous item up
- assert(strip[-i+1] != None)
- strip[-i] = strip[-i+1]
- strip[-i].parms['rowspan'] += 1
- strip[-i+1] = None
- else:
- strip[-i].parms['rowspan'] = 1
-
- # convert to dicts
- for i in range(gridlen):
- for strip in grid:
- if strip[i]:
- strip[i] = strip[i].td()
-
- return dict(grid=grid, gridlen=gridlen, no_bubble=noBubble, time=lastDate)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/words.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/words.py
deleted file mode 100644
index 32565ac6..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/words.py
+++ /dev/null
@@ -1,1097 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-import re, shlex, random
-from string import join, capitalize, lower
-
-from zope.interface import implements
-from twisted.internet import protocol, reactor
-from twisted.words.protocols import irc
-from twisted.python import usage, log
-from twisted.application import internet
-from twisted.internet import defer, task
-
-from buildbot import config, interfaces, util
-from buildbot import version
-from buildbot.interfaces import IStatusReceiver
-from buildbot.sourcestamp import SourceStamp
-from buildbot.status import base
-from buildbot.status.results import SUCCESS, WARNINGS, FAILURE, EXCEPTION, RETRY
-from buildbot.process.properties import Properties
-
-# twisted.internet.ssl requires PyOpenSSL, so be resilient if it's missing
-try:
- from twisted.internet import ssl
- have_ssl = True
-except ImportError:
- have_ssl = False
-
-def maybeColorize(text, color, useColors):
- irc_colors = [
- 'WHITE',
- 'BLACK',
- 'NAVY_BLUE',
- 'GREEN',
- 'RED',
- 'BROWN',
- 'PURPLE',
- 'OLIVE',
- 'YELLOW',
- 'LIME_GREEN',
- 'TEAL',
- 'AQUA_LIGHT',
- 'ROYAL_BLUE',
- 'HOT_PINK',
- 'DARK_GRAY',
- 'LIGHT_GRAY'
- ]
-
- if useColors:
- return "%c%d%s%c" % (3, irc_colors.index(color), text, 3)
- else:
- return text
-
-class UsageError(ValueError):
- def __init__(self, string = "Invalid usage", *more):
- ValueError.__init__(self, string, *more)
-
-class ForceOptions(usage.Options):
- optParameters = [
- ["builder", None, None, "which Builder to start"],
- ["branch", None, None, "which branch to build"],
- ["revision", None, None, "which revision to build"],
- ["reason", None, None, "the reason for starting the build"],
- ["props", None, None,
- "A set of properties made available in the build environment, "
- "format is --properties=prop1=value1,prop2=value2,.. "
- "option can be specified multiple times."],
- ]
-
- def parseArgs(self, *args):
- args = list(args)
- if len(args) > 0:
- if self['builder'] is not None:
- raise UsageError("--builder provided in two ways")
- self['builder'] = args.pop(0)
- if len(args) > 0:
- if self['reason'] is not None:
- raise UsageError("--reason provided in two ways")
- self['reason'] = " ".join(args)
-
-
-class IrcBuildRequest:
- hasStarted = False
- timer = None
-
- def __init__(self, parent, useRevisions=False, useColors=True):
- self.parent = parent
- self.useRevisions = useRevisions
- self.useColors = useColors
- self.timer = reactor.callLater(5, self.soon)
-
- def soon(self):
- del self.timer
- if not self.hasStarted:
- self.parent.send("The build has been queued, I'll give a shout"
- " when it starts")
-
- def started(self, s):
- self.hasStarted = True
- if self.timer:
- self.timer.cancel()
- del self.timer
- eta = s.getETA()
- if self.useRevisions:
- response = "build containing revision(s) [%s] forced" % s.getRevisions()
- else:
- response = "build #%d forced" % s.getNumber()
- if eta is not None:
- response = "build forced [ETA %s]" % self.parent.convertTime(eta)
- self.parent.send(response)
- self.parent.send("I'll give a shout when the build finishes")
- d = s.waitUntilFinished()
- d.addCallback(self.parent.watchedBuildFinished)
-
-class IRCContact(base.StatusReceiver):
- implements(IStatusReceiver)
- """I hold the state for a single user's interaction with the buildbot.
-
- There will be one instance of me for each user who interacts personally
- with the buildbot. There will be an additional instance for each
- 'broadcast contact' (chat rooms, IRC channels as a whole).
- """
-
- def __init__(self, bot, dest):
- self.bot = bot
- self.master = bot.master
- self.notify_events = {}
- self.subscribed = 0
- self.muted = False
- self.useRevisions = bot.useRevisions
- self.useColors = bot.useColors
- self.reported_builds = [] # tuples (when, buildername, buildnum)
- self.add_notification_events(bot.notify_events)
-
- # when people send us public messages ("buildbot: command"),
- # self.dest is the name of the channel ("#twisted"). When they send
- # us private messages (/msg buildbot command), self.dest is their
- # username.
- self.dest = dest
-
- # silliness
-
- silly = {
- "What happen ?": [ "Somebody set up us the bomb." ],
- "It's You !!": ["How are you gentlemen !!",
- "All your base are belong to us.",
- "You are on the way to destruction."],
- "What you say !!": ["You have no chance to survive make your time.",
- "HA HA HA HA ...."],
- }
-
- def doSilly(self, message):
- response = self.silly[message]
- when = 0.5
- for r in response:
- reactor.callLater(when, self.send, r)
- when += 2.5
-
- def getBuilder(self, which):
- try:
- b = self.bot.status.getBuilder(which)
- except KeyError:
- raise UsageError, "no such builder '%s'" % which
- return b
-
- def getControl(self, which):
- if not self.bot.control:
- raise UsageError("builder control is not enabled")
- try:
- bc = self.bot.control.getBuilder(which)
- except KeyError:
- raise UsageError("no such builder '%s'" % which)
- return bc
-
- def getAllBuilders(self):
- """
- @rtype: list of L{buildbot.process.builder.Builder}
- """
- names = self.bot.status.getBuilderNames(categories=self.bot.categories)
- names.sort()
- builders = [self.bot.status.getBuilder(n) for n in names]
- return builders
-
- def convertTime(self, seconds):
- if seconds < 60:
- return "%d seconds" % seconds
- minutes = int(seconds / 60)
- seconds = seconds - 60*minutes
- if minutes < 60:
- return "%dm%02ds" % (minutes, seconds)
- hours = int(minutes / 60)
- minutes = minutes - 60*hours
- return "%dh%02dm%02ds" % (hours, minutes, seconds)
-
- def reportBuild(self, builder, buildnum):
- """Returns True if this build should be reported for this contact
- (eliminating duplicates), and also records the report for later"""
- for w, b, n in self.reported_builds:
- if b == builder and n == buildnum:
- return False
- self.reported_builds.append([util.now(), builder, buildnum])
-
- # clean the reported builds
- horizon = util.now() - 60
- while self.reported_builds and self.reported_builds[0][0] < horizon:
- self.reported_builds.pop(0)
-
- # and return True, since this is a new one
- return True
-
- def splitArgs(self, args):
- """Returns list of arguments parsed by shlex.split() or
- raise UsageError if failed"""
- try:
- return shlex.split(args)
- except ValueError, e:
- raise UsageError(e)
-
- def command_HELLO(self, args, who):
- self.send("yes?")
-
- def command_VERSION(self, args, who):
- self.send("buildbot-%s at your service" % version)
-
- def command_LIST(self, args, who):
- args = self.splitArgs(args)
- if len(args) == 0:
- raise UsageError, "try 'list builders'"
- if args[0] == 'builders':
- builders = self.getAllBuilders()
- str = "Configured builders: "
- for b in builders:
- str += b.name
- state = b.getState()[0]
- if state == 'offline':
- str += "[offline]"
- str += " "
- str.rstrip()
- self.send(str)
- return
- command_LIST.usage = "list builders - List configured builders"
-
- def command_STATUS(self, args, who):
- args = self.splitArgs(args)
- if len(args) == 0:
- which = "all"
- elif len(args) == 1:
- which = args[0]
- else:
- raise UsageError, "try 'status <builder>'"
- if which == "all":
- builders = self.getAllBuilders()
- for b in builders:
- self.emit_status(b.name)
- return
- self.emit_status(which)
- command_STATUS.usage = "status [<which>] - List status of a builder (or all builders)"
-
- def validate_notification_event(self, event):
- if not re.compile("^(started|finished|success|failure|exception|warnings|(success|warnings|exception|failure)To(Failure|Success|Warnings|Exception))$").match(event):
- raise UsageError("try 'notify on|off <EVENT>'")
-
- def list_notified_events(self):
- self.send( "The following events are being notified: %r" % self.notify_events.keys() )
-
- def notify_for(self, *events):
- for event in events:
- if self.notify_events.has_key(event):
- return 1
- return 0
-
- def subscribe_to_build_events(self):
- self.bot.status.subscribe(self)
- self.subscribed = 1
-
- def unsubscribe_from_build_events(self):
- self.bot.status.unsubscribe(self)
- self.subscribed = 0
-
- def add_notification_events(self, events):
- for event in events:
- self.validate_notification_event(event)
- self.notify_events[event] = 1
-
- if not self.subscribed:
- self.subscribe_to_build_events()
-
- def remove_notification_events(self, events):
- for event in events:
- self.validate_notification_event(event)
- del self.notify_events[event]
-
- if len(self.notify_events) == 0 and self.subscribed:
- self.unsubscribe_from_build_events()
-
- def remove_all_notification_events(self):
- self.notify_events = {}
-
- if self.subscribed:
- self.unsubscribe_from_build_events()
-
- def command_NOTIFY(self, args, who):
- args = self.splitArgs(args)
-
- if not args:
- raise UsageError("try 'notify on|off|list <EVENT>'")
- action = args.pop(0)
- events = args
-
- if action == "on":
- if not events: events = ('started','finished')
- self.add_notification_events(events)
-
- self.list_notified_events()
-
- elif action == "off":
- if events:
- self.remove_notification_events(events)
- else:
- self.remove_all_notification_events()
-
- self.list_notified_events()
-
- elif action == "list":
- self.list_notified_events()
- return
-
- else:
- raise UsageError("try 'notify on|off <EVENT>'")
-
- command_NOTIFY.usage = "notify on|off|list [<EVENT>] ... - Notify me about build events. event should be one or more of: 'started', 'finished', 'failure', 'success', 'exception' or 'xToY' (where x and Y are one of success, warnings, failure, exception, but Y is capitalized)"
-
- def command_WATCH(self, args, who):
- args = self.splitArgs(args)
- if len(args) != 1:
- raise UsageError("try 'watch <builder>'")
- which = args[0]
- b = self.getBuilder(which)
- builds = b.getCurrentBuilds()
- if not builds:
- self.send("there are no builds currently running")
- return
- for build in builds:
- assert not build.isFinished()
- d = build.waitUntilFinished()
- d.addCallback(self.watchedBuildFinished)
- if self.useRevisions:
- r = "watching build %s containing revision(s) [%s] until it finishes" \
- % (which, build.getRevisions())
- else:
- r = "watching build %s #%d until it finishes" \
- % (which, build.getNumber())
- eta = build.getETA()
- if eta is not None:
- r += " [%s]" % self.convertTime(eta)
- r += ".."
- self.send(r)
- command_WATCH.usage = "watch <which> - announce the completion of an active build"
-
- def builderAdded(self, builderName, builder):
- if (self.bot.categories != None and
- builder.category not in self.bot.categories):
- return
-
- log.msg('[Contact] Builder %s added' % (builder))
- builder.subscribe(self)
-
- def builderRemoved(self, builderName):
- log.msg('[Contact] Builder %s removed' % (builderName))
-
- def buildStarted(self, builderName, build):
- builder = build.getBuilder()
- log.msg('[Contact] Builder %r in category %s started' % (builder, builder.category))
-
- # only notify about builders we are interested in
-
- if (self.bot.categories != None and
- builder.category not in self.bot.categories):
- log.msg('Not notifying for a build in the wrong category')
- return
-
- if not self.notify_for('started'):
- return
-
- if self.useRevisions:
- r = "build containing revision(s) [%s] on %s started" % \
- (build.getRevisions(), builder.getName())
- else:
- r = "build #%d of %s started, including [%s]" % \
- (build.getNumber(),
- builder.getName(),
- ", ".join([str(c.revision) for c in build.getChanges()])
- )
-
- self.send(r)
-
- results_descriptions = {
- SUCCESS: ("Success", 'GREEN'),
- WARNINGS: ("Warnings", 'YELLOW'),
- FAILURE: ("Failure", 'RED'),
- EXCEPTION: ("Exception", 'PURPLE'),
- RETRY: ("Retry", 'AQUA_LIGHT'),
- }
-
- def getResultsDescriptionAndColor(self, results):
- return self.results_descriptions.get(results, ("??",'RED'))
-
- def buildFinished(self, builderName, build, results):
- builder = build.getBuilder()
-
- if (self.bot.categories != None and
- builder.category not in self.bot.categories):
- return
-
- if not self.notify_for_finished(build):
- return
-
- builder_name = builder.getName()
- buildnum = build.getNumber()
- buildrevs = build.getRevisions()
-
- results = self.getResultsDescriptionAndColor(build.getResults())
- if self.reportBuild(builder_name, buildnum):
- if self.useRevisions:
- r = "build containing revision(s) [%s] on %s is complete: %s" % \
- (buildrevs, builder_name, results[0])
- else:
- r = "build #%d of %s is complete: %s" % \
- (buildnum, builder_name, results[0])
-
- r += ' [%s]' % maybeColorize(" ".join(build.getText()), results[1], self.useColors)
- buildurl = self.bot.status.getURLForThing(build)
- if buildurl:
- r += " Build details are at %s" % buildurl
-
- if self.bot.showBlameList and build.getResults() != SUCCESS and len(build.changes) != 0:
- r += ' blamelist: ' + ', '.join(list(set([c.who for c in build.changes])))
-
- self.send(r)
-
- def notify_for_finished(self, build):
- results = build.getResults()
-
- if self.notify_for('finished'):
- return True
-
- if self.notify_for(lower(self.results_descriptions.get(results)[0])):
- return True
-
- prevBuild = build.getPreviousBuild()
- if prevBuild:
- prevResult = prevBuild.getResults()
-
- required_notification_control_string = join((lower(self.results_descriptions.get(prevResult)[0]), \
- 'To', \
- capitalize(self.results_descriptions.get(results)[0])), \
- '')
-
- if (self.notify_for(required_notification_control_string)):
- return True
-
- return False
-
- def watchedBuildFinished(self, b):
-
- # only notify about builders we are interested in
- builder = b.getBuilder()
- if (self.bot.categories != None and
- builder.category not in self.bot.categories):
- return
-
- builder_name = builder.getName()
- buildnum = b.getNumber()
- buildrevs = b.getRevisions()
-
- results = self.getResultsDescriptionAndColor(b.getResults())
- if self.reportBuild(builder_name, buildnum):
- if self.useRevisions:
- r = "Hey! build %s containing revision(s) [%s] is complete: %s" % \
- (builder_name, buildrevs, results[0])
- else:
- r = "Hey! build %s #%d is complete: %s" % \
- (builder_name, buildnum, results[0])
-
- r += ' [%s]' % maybeColorize(" ".join(b.getText()), results[1], self.useColors)
- self.send(r)
- buildurl = self.bot.status.getURLForThing(b)
- if buildurl:
- self.send("Build details are at %s" % buildurl)
-
- def command_FORCE(self, args, who):
- errReply = "try 'force build [--branch=BRANCH] [--revision=REVISION] [--props=PROP1=VAL1,PROP2=VAL2...] <WHICH> <REASON>'"
- args = self.splitArgs(args)
- if not args:
- raise UsageError(errReply)
- what = args.pop(0)
- if what != "build":
- raise UsageError(errReply)
- opts = ForceOptions()
- opts.parseOptions(args)
-
- which = opts['builder']
- branch = opts['branch']
- revision = opts['revision']
- reason = opts['reason']
- props = opts['props']
-
- if which is None:
- raise UsageError("you must provide a Builder, " + errReply)
-
- # keep weird stuff out of the branch, revision, and properties args.
- branch_validate = self.master.config.validation['branch']
- revision_validate = self.master.config.validation['revision']
- pname_validate = self.master.config.validation['property_name']
- pval_validate = self.master.config.validation['property_value']
- if branch and not branch_validate.match(branch):
- log.msg("bad branch '%s'" % branch)
- self.send("sorry, bad branch '%s'" % branch)
- return
- if revision and not revision_validate.match(revision):
- log.msg("bad revision '%s'" % revision)
- self.send("sorry, bad revision '%s'" % revision)
- return
-
- properties = Properties()
- if props:
- # split props into name:value dict
- pdict = {}
- propertylist = props.split(",")
- for i in range(0,len(propertylist)):
- splitproperty = propertylist[i].split("=", 1)
- pdict[splitproperty[0]] = splitproperty[1]
-
- # set properties
- for prop in pdict:
- pname = prop
- pvalue = pdict[prop]
- if not pname_validate.match(pname) \
- or not pval_validate.match(pvalue):
- log.msg("bad property name='%s', value='%s'" % (pname, pvalue))
- self.send("sorry, bad property name='%s', value='%s'" %
- (pname, pvalue))
- return
- properties.setProperty(pname, pvalue, "Force Build IRC")
-
- bc = self.getControl(which)
-
- reason = "forced: by %s: %s" % (self.describeUser(who), reason)
- ss = SourceStamp(branch=branch, revision=revision)
- d = bc.submitBuildRequest(ss, reason, props=properties.asDict())
- def subscribe(buildreq):
- ireq = IrcBuildRequest(self, self.useRevisions)
- buildreq.subscribe(ireq.started)
- d.addCallback(subscribe)
- d.addErrback(log.err, "while forcing a build")
-
-
- command_FORCE.usage = "force build [--branch=branch] [--revision=revision] [--props=prop1=val1,prop2=val2...] <which> <reason> - Force a build"
-
- def command_STOP(self, args, who):
- args = self.splitArgs(args)
- if len(args) < 3 or args[0] != 'build':
- raise UsageError, "try 'stop build WHICH <REASON>'"
- which = args[1]
- reason = args[2]
-
- buildercontrol = self.getControl(which)
-
- r = "stopped: by %s: %s" % (self.describeUser(who), reason)
-
- # find an in-progress build
- builderstatus = self.getBuilder(which)
- builds = builderstatus.getCurrentBuilds()
- if not builds:
- self.send("sorry, no build is currently running")
- return
- for build in builds:
- num = build.getNumber()
- revs = build.getRevisions()
-
- # obtain the BuildControl object
- buildcontrol = buildercontrol.getBuild(num)
-
- # make it stop
- buildcontrol.stopBuild(r)
-
- if self.useRevisions:
- response = "build containing revision(s) [%s] interrupted" % revs
- else:
- response = "build %d interrupted" % num
- self.send(response)
-
- command_STOP.usage = "stop build <which> <reason> - Stop a running build"
-
- def emit_status(self, which):
- b = self.getBuilder(which)
- str = "%s: " % which
- state, builds = b.getState()
- str += state
- if state == "idle":
- last = b.getLastFinishedBuild()
- if last:
- start,finished = last.getTimes()
- str += ", last build %s ago: %s" % \
- (self.convertTime(int(util.now() - finished)), " ".join(last.getText()))
- if state == "building":
- t = []
- for build in builds:
- step = build.getCurrentStep()
- if step:
- s = "(%s)" % " ".join(step.getText())
- else:
- s = "(no current step)"
- ETA = build.getETA()
- if ETA is not None:
- s += " [ETA %s]" % self.convertTime(ETA)
- t.append(s)
- str += ", ".join(t)
- self.send(str)
-
- def command_LAST(self, args, who):
- args = self.splitArgs(args)
-
- if len(args) == 0:
- which = "all"
- elif len(args) == 1:
- which = args[0]
- else:
- raise UsageError, "try 'last <builder>'"
-
- def emit_last(which):
- last = self.getBuilder(which).getLastFinishedBuild()
- if not last:
- str = "(no builds run since last restart)"
- else:
- start,finish = last.getTimes()
- str = "%s ago: " % (self.convertTime(int(util.now() - finish)))
- str += " ".join(last.getText())
- self.send("last build [%s]: %s" % (which, str))
-
- if which == "all":
- builders = self.getAllBuilders()
- for b in builders:
- emit_last(b.name)
- return
- emit_last(which)
- command_LAST.usage = "last <which> - list last build status for builder <which>"
-
- def build_commands(self):
- commands = []
- for k in dir(self):
- if k.startswith('command_'):
- commands.append(k[8:].lower())
- commands.sort()
- return commands
-
- def describeUser(self, user):
- if self.dest[0] == '#':
- return "IRC user <%s> on channel %s" % (user, self.dest)
- return "IRC user <%s> (privmsg)" % user
-
- # commands
-
- def command_MUTE(self, args, who):
- # The order of these is important! ;)
- self.send("Shutting up for now.")
- self.muted = True
- command_MUTE.usage = "mute - suppress all messages until a corresponding 'unmute' is issued"
-
- def command_UNMUTE(self, args, who):
- if self.muted:
- # The order of these is important! ;)
- self.muted = False
- self.send("I'm baaaaaaaaaaack!")
- else:
- self.send("You hadn't told me to be quiet, but it's the thought that counts, right?")
- command_UNMUTE.usage = "unmute - disable a previous 'mute'"
-
- def command_HELP(self, args, who):
- args = self.splitArgs(args)
- if len(args) == 0:
- self.send("Get help on what? (try 'help <foo>', 'help <foo> <bar>, "
- "or 'commands' for a command list)")
- return
- command = args[0]
- meth = self.getCommandMethod(command)
- if not meth:
- raise UsageError, "no such command '%s'" % command
- usage = getattr(meth, 'usage', None)
- if isinstance(usage, dict):
- if len(args) == 1:
- k = None # command
- elif len(args) == 2:
- k = args[1] # command arg
- else:
- k = tuple(args[1:]) # command arg subarg ...
- usage = usage.get(k, None)
- if usage:
- self.send("Usage: %s" % usage)
- else:
- self.send("No usage info for " + ' '.join(["'%s'" % arg for arg in args]))
- command_HELP.usage = "help <command> [<arg> [<subarg> ...]] - Give help for <command> or one of it's arguments"
-
- def command_SOURCE(self, args, who):
- self.send("My source can be found at "
- "https://github.com/buildbot/buildbot")
- command_SOURCE.usage = "source - the source code for Buildbot"
-
- def command_COMMANDS(self, args, who):
- commands = self.build_commands()
- str = "buildbot commands: " + ", ".join(commands)
- self.send(str)
- command_COMMANDS.usage = "commands - List available commands"
-
- def command_DESTROY(self, args, who):
- if self.bot.nickname not in args:
- self.act("readies phasers")
-
- def command_DANCE(self, args, who):
- reactor.callLater(1.0, self.send, "<(^.^<)")
- reactor.callLater(2.0, self.send, "<(^.^)>")
- reactor.callLater(3.0, self.send, "(>^.^)>")
- reactor.callLater(3.5, self.send, "(7^.^)7")
- reactor.callLater(5.0, self.send, "(>^.^<)")
-
- def command_SHUTDOWN(self, args, who):
- if args not in ('check','start','stop','now'):
- raise UsageError("try 'shutdown check|start|stop|now'")
-
- if not self.bot.factory.allowShutdown:
- raise UsageError("shutdown control is not enabled")
-
- botmaster = self.master.botmaster
- shuttingDown = botmaster.shuttingDown
-
- if args == 'check':
- if shuttingDown:
- self.send("Status: buildbot is shutting down")
- else:
- self.send("Status: buildbot is running")
- elif args == 'start':
- if shuttingDown:
- self.send("Already started")
- else:
- self.send("Starting clean shutdown")
- botmaster.cleanShutdown()
- elif args == 'stop':
- if not shuttingDown:
- self.send("Nothing to stop")
- else:
- self.send("Stopping clean shutdown")
- botmaster.cancelCleanShutdown()
- elif args == 'now':
- self.send("Stopping buildbot")
- reactor.stop()
- command_SHUTDOWN.usage = {
- None: "shutdown check|start|stop|now - shutdown the buildbot master",
- "check": "shutdown check - check if the buildbot master is running or shutting down",
- "start": "shutdown start - start a clean shutdown",
- "stop": "shutdown cancel - stop the clean shutdown",
- "now": "shutdown now - shutdown immediately without waiting for the builders to finish"}
-
- # communication with the user
-
- def send(self, message):
- if not self.muted:
- self.bot.msgOrNotice(self.dest, message.encode("ascii", "replace"))
-
- def act(self, action):
- if not self.muted:
- self.bot.describe(self.dest, action.encode("ascii", "replace"))
-
- # main dispatchers for incoming messages
-
- def getCommandMethod(self, command):
- return getattr(self, 'command_' + command.upper(), None)
-
- def handleMessage(self, message, who):
- # a message has arrived from 'who'. For broadcast contacts (i.e. when
- # people do an irc 'buildbot: command'), this will be a string
- # describing the sender of the message in some useful-to-log way, and
- # a single Contact may see messages from a variety of users. For
- # unicast contacts (i.e. when people do an irc '/msg buildbot
- # command'), a single Contact will only ever see messages from a
- # single user.
- message = message.lstrip()
- if self.silly.has_key(message):
- self.doSilly(message)
- return defer.succeed(None)
-
- parts = message.split(' ', 1)
- if len(parts) == 1:
- parts = parts + ['']
- cmd, args = parts
- log.msg("irc command", cmd)
-
- meth = self.getCommandMethod(cmd)
- if not meth and message[-1] == '!':
- self.send("What you say!")
- return defer.succeed(None)
-
- if meth:
- d = defer.maybeDeferred(meth, args.strip(), who)
- @d.addErrback
- def usageError(f):
- f.trap(UsageError)
- self.send(str(f.value))
- @d.addErrback
- def logErr(f):
- log.err(f)
- self.send("Something bad happened (see logs)")
- d.addErrback(log.err)
- return d
- return defer.succeed(None)
-
- def handleAction(self, data, user):
- # this is sent when somebody performs an action that mentions the
- # buildbot (like '/me kicks buildbot'). 'user' is the name/nick/id of
- # the person who performed the action, so if their action provokes a
- # response, they can be named. This is 100% silly.
- if not data.endswith("s "+ self.bot.nickname):
- return
- words = data.split()
- verb = words[-2]
- if verb == "kicks":
- response = "%s back" % verb
- else:
- response = "%s %s too" % (verb, user)
- self.act(response)
-
-
-class IrcStatusBot(irc.IRCClient):
- """I represent the buildbot to an IRC server.
- """
- contactClass = IRCContact
-
- def __init__(self, nickname, password, channels, pm_to_nicks, status,
- categories, notify_events, noticeOnChannel=False,
- useRevisions=False, showBlameList=False, useColors=True):
- self.nickname = nickname
- self.channels = channels
- self.pm_to_nicks = pm_to_nicks
- self.password = password
- self.status = status
- self.master = status.master
- self.categories = categories
- self.notify_events = notify_events
- self.hasQuit = 0
- self.contacts = {}
- self.noticeOnChannel = noticeOnChannel
- self.useColors = useColors
- self.useRevisions = useRevisions
- self.showBlameList = showBlameList
- self._keepAliveCall = task.LoopingCall(lambda: self.ping(self.nickname))
-
- def connectionMade(self):
- irc.IRCClient.connectionMade(self)
- self._keepAliveCall.start(60)
-
- def connectionLost(self, reason):
- if self._keepAliveCall.running:
- self._keepAliveCall.stop()
- irc.IRCClient.connectionLost(self, reason)
-
- def msgOrNotice(self, dest, message):
- if self.noticeOnChannel and dest[0] == '#':
- self.notice(dest, message)
- else:
- self.msg(dest, message)
-
- def getContact(self, name):
- name = name.lower() # nicknames and channel names are case insensitive
- if name in self.contacts:
- return self.contacts[name]
- new_contact = self.contactClass(self, name)
- self.contacts[name] = new_contact
- return new_contact
-
- def log(self, msg):
- log.msg("%s: %s" % (self, msg))
-
-
- # the following irc.IRCClient methods are called when we have input
-
- def privmsg(self, user, channel, message):
- user = user.split('!', 1)[0] # rest is ~user@hostname
- # channel is '#twisted' or 'buildbot' (for private messages)
- if channel == self.nickname:
- # private message
- contact = self.getContact(user)
- contact.handleMessage(message, user)
- return
- # else it's a broadcast message, maybe for us, maybe not. 'channel'
- # is '#twisted' or the like.
- contact = self.getContact(channel)
- if message.startswith("%s:" % self.nickname) or message.startswith("%s," % self.nickname):
- message = message[len("%s:" % self.nickname):]
- contact.handleMessage(message, user)
-
- def action(self, user, channel, data):
- user = user.split('!', 1)[0] # rest is ~user@hostname
- # somebody did an action (/me actions) in the broadcast channel
- contact = self.getContact(channel)
- if self.nickname in data:
- contact.handleAction(data, user)
-
- def signedOn(self):
- if self.password:
- self.msg("Nickserv", "IDENTIFY " + self.password)
- for c in self.channels:
- if isinstance(c, dict):
- channel = c.get('channel', None)
- password = c.get('password', None)
- else:
- channel = c
- password = None
- self.join(channel=channel, key=password)
- for c in self.pm_to_nicks:
- self.getContact(c)
-
- def joined(self, channel):
- self.log("I have joined %s" % (channel,))
- # trigger contact contructor, which in turn subscribes to notify events
- self.getContact(channel)
-
- def left(self, channel):
- self.log("I have left %s" % (channel,))
-
- def kickedFrom(self, channel, kicker, message):
- self.log("I have been kicked from %s by %s: %s" % (channel,
- kicker,
- message))
-
-
-class ThrottledClientFactory(protocol.ClientFactory):
- lostDelay = random.randint(1, 5)
- failedDelay = random.randint(45, 60)
-
- def __init__(self, lostDelay=None, failedDelay=None):
- if lostDelay is not None:
- self.lostDelay = lostDelay
- if failedDelay is not None:
- self.failedDelay = failedDelay
-
- def clientConnectionLost(self, connector, reason):
- reactor.callLater(self.lostDelay, connector.connect)
-
- def clientConnectionFailed(self, connector, reason):
- reactor.callLater(self.failedDelay, connector.connect)
-
-
-class IrcStatusFactory(ThrottledClientFactory):
- protocol = IrcStatusBot
-
- status = None
- control = None
- shuttingDown = False
- p = None
-
- def __init__(self, nickname, password, channels, pm_to_nicks, categories, notify_events,
- noticeOnChannel=False, useRevisions=False, showBlameList=False,
- lostDelay=None, failedDelay=None, useColors=True, allowShutdown=False):
- ThrottledClientFactory.__init__(self, lostDelay=lostDelay,
- failedDelay=failedDelay)
- self.status = None
- self.nickname = nickname
- self.password = password
- self.channels = channels
- self.pm_to_nicks = pm_to_nicks
- self.categories = categories
- self.notify_events = notify_events
- self.noticeOnChannel = noticeOnChannel
- self.useRevisions = useRevisions
- self.showBlameList = showBlameList
- self.useColors = useColors
- self.allowShutdown = allowShutdown
-
- def __getstate__(self):
- d = self.__dict__.copy()
- del d['p']
- return d
-
- def shutdown(self):
- self.shuttingDown = True
- if self.p:
- self.p.quit("buildmaster reconfigured: bot disconnecting")
-
- def buildProtocol(self, address):
- p = self.protocol(self.nickname, self.password,
- self.channels, self.pm_to_nicks, self.status,
- self.categories, self.notify_events,
- noticeOnChannel = self.noticeOnChannel,
- useColors = self.useColors,
- useRevisions = self.useRevisions,
- showBlameList = self.showBlameList)
- p.factory = self
- p.status = self.status
- p.control = self.control
- self.p = p
- return p
-
- # TODO: I think a shutdown that occurs while the connection is being
- # established will make this explode
-
- def clientConnectionLost(self, connector, reason):
- if self.shuttingDown:
- log.msg("not scheduling reconnection attempt")
- return
- ThrottledClientFactory.clientConnectionLost(self, connector, reason)
-
- def clientConnectionFailed(self, connector, reason):
- if self.shuttingDown:
- log.msg("not scheduling reconnection attempt")
- return
- ThrottledClientFactory.clientConnectionFailed(self, connector, reason)
-
-
-class IRC(base.StatusReceiverMultiService):
- implements(IStatusReceiver)
-
- in_test_harness = False
-
- compare_attrs = ["host", "port", "nick", "password",
- "channels", "pm_to_nicks", "allowForce", "useSSL",
- "useRevisions", "categories", "useColors",
- "lostDelay", "failedDelay", "allowShutdown"]
-
- def __init__(self, host, nick, channels, pm_to_nicks=[], port=6667,
- allowForce=False, categories=None, password=None, notify_events={},
- noticeOnChannel = False, showBlameList = True, useRevisions=False,
- useSSL=False, lostDelay=None, failedDelay=None, useColors=True,
- allowShutdown=False):
- base.StatusReceiverMultiService.__init__(self)
-
- if allowForce not in (True, False):
- config.error("allowForce must be boolean, not %r" % (allowForce,))
- if allowShutdown not in (True, False):
- config.error("allowShutdown must be boolean, not %r" % (allowShutdown,))
-
- # need to stash these so we can detect changes later
- self.host = host
- self.port = port
- self.nick = nick
- self.channels = channels
- self.pm_to_nicks = pm_to_nicks
- self.password = password
- self.allowForce = allowForce
- self.useRevisions = useRevisions
- self.categories = categories
- self.notify_events = notify_events
- self.allowShutdown = allowShutdown
-
- self.f = IrcStatusFactory(self.nick, self.password,
- self.channels, self.pm_to_nicks,
- self.categories, self.notify_events,
- noticeOnChannel = noticeOnChannel,
- useRevisions = useRevisions,
- showBlameList = showBlameList,
- lostDelay = lostDelay,
- failedDelay = failedDelay,
- useColors = useColors,
- allowShutdown = allowShutdown)
-
- if useSSL:
- # SSL client needs a ClientContextFactory for some SSL mumbo-jumbo
- if not have_ssl:
- raise RuntimeError("useSSL requires PyOpenSSL")
- cf = ssl.ClientContextFactory()
- c = internet.SSLClient(self.host, self.port, self.f, cf)
- else:
- c = internet.TCPClient(self.host, self.port, self.f)
-
- c.setServiceParent(self)
-
- def setServiceParent(self, parent):
- base.StatusReceiverMultiService.setServiceParent(self, parent)
- self.f.status = parent
- if self.allowForce:
- self.f.control = interfaces.IControl(self.master)
-
- def stopService(self):
- # make sure the factory will stop reconnecting
- self.f.shutdown()
- return base.StatusReceiverMultiService.stopService(self)
-