aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers')
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/__init__.py0
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/base.py453
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/basic.py256
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/dependent.py148
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/filter.py18
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/forcesched.py666
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/manager.py95
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/timed.py410
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/triggerable.py94
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/trysched.py304
10 files changed, 0 insertions, 2444 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/__init__.py
+++ /dev/null
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/base.py
deleted file mode 100644
index 4b18f935..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/base.py
+++ /dev/null
@@ -1,453 +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 failure, log
-from twisted.application import service
-from twisted.internet import defer
-from buildbot.process.properties import Properties
-from buildbot.util import ComparableMixin
-from buildbot import config, interfaces
-from buildbot.util.state import StateMixin
-
-class BaseScheduler(service.MultiService, ComparableMixin, StateMixin):
- """
- Base class for all schedulers; this provides the equipment to manage
- reconfigurations and to handle basic scheduler state. It also provides
- utility methods to begin various sorts of builds.
-
- Subclasses should add any configuration-derived attributes to
- C{base.Scheduler.compare_attrs}.
- """
-
- implements(interfaces.IScheduler)
-
- DefaultCodebases = {'':{}}
-
- compare_attrs = ('name', 'builderNames', 'properties', 'codebases')
-
- def __init__(self, name, builderNames, properties,
- codebases = DefaultCodebases):
- """
- Initialize a Scheduler.
-
- @param name: name of this scheduler (used as a key for state)
- @type name: unicode
-
- @param builderNames: list of builders this scheduler may start
- @type builderNames: list of unicode
-
- @param properties: properties to add to builds triggered by this
- scheduler
- @type properties: dictionary
-
- @param codebases: codebases that are necessary to process the changes
- @type codebases: dict with following struct:
- key: '<codebase>'
- value: {'repository':'<repo>', 'branch':'<br>', 'revision:'<rev>'}
-
- @param consumeChanges: true if this scheduler wishes to be informed
- about the addition of new changes. Defaults to False. This should
- be passed explicitly from subclasses to indicate their interest in
- consuming changes.
- @type consumeChanges: boolean
- """
- service.MultiService.__init__(self)
- self.name = name
- "name of this scheduler; used to identify replacements on reconfig"
-
- ok = True
- if not isinstance(builderNames, (list, tuple)):
- ok = False
- else:
- for b in builderNames:
- if not isinstance(b, basestring):
- ok = False
- if not ok:
- config.error(
- "The builderNames argument to a scheduler must be a list "
- "of Builder names.")
-
- self.builderNames = builderNames
- "list of builder names to start in each buildset"
-
- self.properties = Properties()
- "properties that are contributed to each buildset"
- self.properties.update(properties, "Scheduler")
- self.properties.setProperty("scheduler", name, "Scheduler")
-
- self.objectid = None
-
- self.master = None
-
- # Set the codebases that are necessary to process the changes
- # These codebases will always result in a sourcestamp with or without changes
- if codebases is not None:
- if not isinstance(codebases, dict):
- config.error("Codebases must be a dict of dicts")
- for codebase, codebase_attrs in codebases.iteritems():
- if not isinstance(codebase_attrs, dict):
- config.error("Codebases must be a dict of dicts")
- if (codebases != BaseScheduler.DefaultCodebases and
- 'repository' not in codebase_attrs):
- config.error("The key 'repository' is mandatory in codebases")
- else:
- config.error("Codebases cannot be None")
-
- self.codebases = codebases
-
- # internal variables
- self._change_subscription = None
- self._change_consumption_lock = defer.DeferredLock()
-
- ## service handling
-
- def startService(self):
- service.MultiService.startService(self)
-
- def findNewSchedulerInstance(self, new_config):
- return new_config.schedulers[self.name] # should exist!
-
- def stopService(self):
- d = defer.maybeDeferred(self._stopConsumingChanges)
- d.addCallback(lambda _ : service.MultiService.stopService(self))
- return d
-
-
- ## status queries
-
- # TODO: these aren't compatible with distributed schedulers
-
- def listBuilderNames(self):
- "Returns the list of builder names"
- return self.builderNames
-
- def getPendingBuildTimes(self):
- "Returns a list of the next times that builds are scheduled, if known."
- return []
-
- ## change handling
-
- def startConsumingChanges(self, fileIsImportant=None, change_filter=None,
- onlyImportant=False):
- """
- Subclasses should call this method from startService to register to
- receive changes. The BaseScheduler class will take care of filtering
- the changes (using change_filter) and (if fileIsImportant is not None)
- classifying them. See L{gotChange}. Returns a Deferred.
-
- @param fileIsImportant: a callable provided by the user to distinguish
- important and unimportant changes
- @type fileIsImportant: callable
-
- @param change_filter: a filter to determine which changes are even
- considered by this scheduler, or C{None} to consider all changes
- @type change_filter: L{buildbot.changes.filter.ChangeFilter} instance
-
- @param onlyImportant: If True, only important changes, as specified by
- fileIsImportant, will be added to the buildset.
- @type onlyImportant: boolean
-
- """
- assert fileIsImportant is None or callable(fileIsImportant)
-
- # register for changes with master
- assert not self._change_subscription
- def changeCallback(change):
- # ignore changes delivered while we're not running
- if not self._change_subscription:
- return
-
- if change_filter and not change_filter.filter_change(change):
- return
- if change.codebase not in self.codebases:
- log.msg(format='change contains codebase %(codebase)s that is'
- 'not processed by scheduler %(scheduler)s',
- codebase=change.codebase, name=self.name)
- return
- if fileIsImportant:
- try:
- important = fileIsImportant(change)
- if not important and onlyImportant:
- return
- except:
- log.err(failure.Failure(),
- 'in fileIsImportant check for %s' % change)
- return
- else:
- important = True
-
- # use change_consumption_lock to ensure the service does not stop
- # while this change is being processed
- d = self._change_consumption_lock.run(self.gotChange, change, important)
- d.addErrback(log.err, 'while processing change')
- self._change_subscription = self.master.subscribeToChanges(changeCallback)
-
- return defer.succeed(None)
-
- def _stopConsumingChanges(self):
- # (note: called automatically in stopService)
-
- # acquire the lock change consumption lock to ensure that any change
- # consumption is complete before we are done stopping consumption
- def stop():
- if self._change_subscription:
- self._change_subscription.unsubscribe()
- self._change_subscription = None
- return self._change_consumption_lock.run(stop)
-
- def gotChange(self, change, important):
- """
- Called when a change is received; returns a Deferred. If the
- C{fileIsImportant} parameter to C{startConsumingChanges} was C{None},
- then all changes are considered important.
- The C{codebase} of the change has always an entry in the C{codebases}
- dictionary of the scheduler.
-
- @param change: the new change object
- @type change: L{buildbot.changes.changes.Change} instance
- @param important: true if this is an important change, according to
- C{fileIsImportant}.
- @type important: boolean
- @returns: Deferred
- """
- raise NotImplementedError
-
- ## starting bulids
-
- @defer.inlineCallbacks
- def addBuildsetForLatest(self, reason='', external_idstring=None,
- branch=None, repository='', project='',
- builderNames=None, properties=None):
- """
- Add a buildset for the 'latest' source in the given branch,
- repository, and project. This will create a relative sourcestamp for
- the buildset.
-
- This method will add any properties provided to the scheduler
- constructor to the buildset, and will call the master's addBuildset
- method with the appropriate parameters.
-
- @param reason: reason for this buildset
- @type reason: unicode string
- @param external_idstring: external identifier for this buildset, or None
- @param branch: branch to build (note that None often has a special meaning)
- @param repository: repository name for sourcestamp
- @param project: project name for sourcestamp
- @param builderNames: builders to name in the buildset (defaults to
- C{self.builderNames})
- @param properties: a properties object containing initial properties for
- the buildset
- @type properties: L{buildbot.process.properties.Properties}
- @returns: (buildset ID, buildrequest IDs) via Deferred
- """
- # Define setid for this set of changed repositories
- setid = yield self.master.db.sourcestampsets.addSourceStampSet()
-
- # add a sourcestamp for each codebase
- for codebase, cb_info in self.codebases.iteritems():
- ss_repository = cb_info.get('repository', repository)
- ss_branch = cb_info.get('branch', branch)
- ss_revision = cb_info.get('revision', None)
- yield self.master.db.sourcestamps.addSourceStamp(
- codebase=codebase,
- repository=ss_repository,
- branch=ss_branch,
- revision=ss_revision,
- project=project,
- changeids=set(),
- sourcestampsetid=setid)
-
- bsid,brids = yield self.addBuildsetForSourceStamp(
- setid=setid, reason=reason,
- external_idstring=external_idstring,
- builderNames=builderNames,
- properties=properties)
-
- defer.returnValue((bsid,brids))
-
-
- @defer.inlineCallbacks
- def addBuildsetForSourceStampDetails(self, reason='', external_idstring=None,
- branch=None, repository='', project='', revision=None,
- builderNames=None, properties=None):
- """
- Given details about the source code to build, create a source stamp and
- then add a buildset for it.
-
- @param reason: reason for this buildset
- @type reason: unicode string
- @param external_idstring: external identifier for this buildset, or None
- @param branch: branch to build (note that None often has a special meaning)
- @param repository: repository name for sourcestamp
- @param project: project name for sourcestamp
- @param revision: revision to build - default is latest
- @param builderNames: builders to name in the buildset (defaults to
- C{self.builderNames})
- @param properties: a properties object containing initial properties for
- the buildset
- @type properties: L{buildbot.process.properties.Properties}
- @returns: (buildset ID, buildrequest IDs) via Deferred
- """
- # Define setid for this set of changed repositories
- setid = yield self.master.db.sourcestampsets.addSourceStampSet()
-
- yield self.master.db.sourcestamps.addSourceStamp(
- branch=branch, revision=revision, repository=repository,
- project=project, sourcestampsetid=setid)
-
- rv = yield self.addBuildsetForSourceStamp(
- setid=setid, reason=reason,
- external_idstring=external_idstring,
- builderNames=builderNames,
- properties=properties)
- defer.returnValue(rv)
-
-
- @defer.inlineCallbacks
- def addBuildsetForSourceStampSetDetails(self, reason, sourcestamps,
- properties, builderNames=None):
- if sourcestamps is None:
- sourcestamps = {}
-
- # Define new setid for this set of sourcestamps
- new_setid = yield self.master.db.sourcestampsets.addSourceStampSet()
-
- # Merge codebases with the passed list of sourcestamps
- # This results in a new sourcestamp for each codebase
- for codebase in self.codebases:
- ss = self.codebases[codebase].copy()
- # apply info from passed sourcestamps onto the configured default
- # sourcestamp attributes for this codebase.
- ss.update(sourcestamps.get(codebase,{}))
-
- # add sourcestamp to the new setid
- yield self.master.db.sourcestamps.addSourceStamp(
- codebase=codebase,
- repository=ss.get('repository', ''),
- branch=ss.get('branch', None),
- revision=ss.get('revision', None),
- project=ss.get('project', ''),
- changeids=[c['number'] for c in ss.get('changes', [])],
- patch_body=ss.get('patch_body', None),
- patch_level=ss.get('patch_level', None),
- patch_author=ss.get('patch_author', None),
- patch_comment=ss.get('patch_comment', None),
- sourcestampsetid=new_setid)
-
- rv = yield self.addBuildsetForSourceStamp(
- setid=new_setid, reason=reason,
- properties=properties,
- builderNames=builderNames)
-
- defer.returnValue(rv)
-
-
- @defer.inlineCallbacks
- def addBuildsetForChanges(self, reason='', external_idstring=None,
- changeids=[], builderNames=None, properties=None):
- changesByCodebase = {}
-
- def get_last_change_for_codebase(codebase):
- return max(changesByCodebase[codebase],key = lambda change: change["changeid"])
-
- # Define setid for this set of changed repositories
- setid = yield self.master.db.sourcestampsets.addSourceStampSet()
-
- # Changes are retrieved from database and grouped by their codebase
- for changeid in changeids:
- chdict = yield self.master.db.changes.getChange(changeid)
- # group change by codebase
- changesByCodebase.setdefault(chdict["codebase"], []).append(chdict)
-
- for codebase in self.codebases:
- args = {'codebase': codebase, 'sourcestampsetid': setid }
- if codebase not in changesByCodebase:
- # codebase has no changes
- # create a sourcestamp that has no changes
- args['repository'] = self.codebases[codebase]['repository']
- args['branch'] = self.codebases[codebase].get('branch', None)
- args['revision'] = self.codebases[codebase].get('revision', None)
- args['changeids'] = set()
- args['project'] = ''
- else:
- #codebase has changes
- args['changeids'] = [c["changeid"] for c in changesByCodebase[codebase]]
- lastChange = get_last_change_for_codebase(codebase)
- for key in ['repository', 'branch', 'revision', 'project']:
- args[key] = lastChange[key]
-
- yield self.master.db.sourcestamps.addSourceStamp(**args)
-
- # add one buildset, this buildset is connected to the sourcestamps by the setid
- bsid,brids = yield self.addBuildsetForSourceStamp( setid=setid,
- reason=reason, external_idstring=external_idstring,
- builderNames=builderNames, properties=properties)
-
- defer.returnValue((bsid,brids))
-
- @defer.inlineCallbacks
- def addBuildsetForSourceStamp(self, ssid=None, setid=None, reason='', external_idstring=None,
- properties=None, builderNames=None):
- """
- Add a buildset for the given, already-existing sourcestamp.
-
- This method will add any properties provided to the scheduler
- constructor to the buildset, and will call the master's
- L{BuildMaster.addBuildset} method with the appropriate parameters, and
- return the same result.
-
- @param reason: reason for this buildset
- @type reason: unicode string
- @param external_idstring: external identifier for this buildset, or None
- @param properties: a properties object containing initial properties for
- the buildset
- @type properties: L{buildbot.process.properties.Properties}
- @param builderNames: builders to name in the buildset (defaults to
- C{self.builderNames})
- @param setid: idenitification of a set of sourcestamps
- @returns: (buildset ID, buildrequest IDs) via Deferred
- """
- assert (ssid is None and setid is not None) \
- or (ssid is not None and setid is None), "pass a single sourcestamp OR set not both"
-
- # combine properties
- if properties:
- properties.updateFromProperties(self.properties)
- else:
- properties = self.properties
-
- # apply the default builderNames
- if not builderNames:
- builderNames = self.builderNames
-
- # translate properties object into a dict as required by the
- # addBuildset method
- properties_dict = properties.asDict()
-
- if setid == None:
- if ssid is not None:
- ssdict = yield self.master.db.sourcestamps.getSourceStamp(ssid)
- setid = ssdict['sourcestampsetid']
- else:
- # no sourcestamp and no sets
- yield None
-
- rv = yield self.master.addBuildset(sourcestampsetid=setid,
- reason=reason, properties=properties_dict,
- builderNames=builderNames,
- external_idstring=external_idstring)
- defer.returnValue(rv)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/basic.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/basic.py
deleted file mode 100644
index a2b9f19c..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/basic.py
+++ /dev/null
@@ -1,256 +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, reactor
-from twisted.python import log
-from buildbot import util, config
-from buildbot.util import NotABranch
-from collections import defaultdict
-from buildbot.changes import filter, changes
-from buildbot.schedulers import base, dependent
-
-class BaseBasicScheduler(base.BaseScheduler):
- """
- @param onlyImportant: If True, only important changes will be added to the
- buildset.
- @type onlyImportant: boolean
-
- """
-
- compare_attrs = (base.BaseScheduler.compare_attrs +
- ('treeStableTimer', 'change_filter', 'fileIsImportant',
- 'onlyImportant') )
-
- _reactor = reactor # for tests
-
- fileIsImportant = None
-
- class NotSet: pass
- def __init__(self, name, shouldntBeSet=NotSet, treeStableTimer=None,
- builderNames=None, branch=NotABranch, branches=NotABranch,
- fileIsImportant=None, properties={}, categories=None,
- change_filter=None, onlyImportant=False, **kwargs):
- if shouldntBeSet is not self.NotSet:
- config.error(
- "pass arguments to schedulers using keyword arguments")
- if fileIsImportant and not callable(fileIsImportant):
- config.error(
- "fileIsImportant must be a callable")
-
- # initialize parent classes
- base.BaseScheduler.__init__(self, name, builderNames, properties, **kwargs)
-
- self.treeStableTimer = treeStableTimer
- if fileIsImportant is not None:
- self.fileIsImportant = fileIsImportant
- self.onlyImportant = onlyImportant
- self.change_filter = self.getChangeFilter(branch=branch,
- branches=branches, change_filter=change_filter,
- categories=categories)
-
- # the IDelayedCall used to wake up when this scheduler's
- # treeStableTimer expires.
- self._stable_timers = defaultdict(lambda : None)
- self._stable_timers_lock = defer.DeferredLock()
-
- def getChangeFilter(self, branch, branches, change_filter, categories):
- raise NotImplementedError
-
- def startService(self, _returnDeferred=False):
- base.BaseScheduler.startService(self)
-
- d = self.startConsumingChanges(fileIsImportant=self.fileIsImportant,
- change_filter=self.change_filter,
- onlyImportant=self.onlyImportant)
-
- # if treeStableTimer is False, then we don't care about classified
- # changes, so get rid of any hanging around from previous
- # configurations
- if not self.treeStableTimer:
- d.addCallback(lambda _ :
- self.master.db.schedulers.flushChangeClassifications(
- self.objectid))
-
- # otherwise, if there are classified changes out there, start their
- # treeStableTimers again
- else:
- d.addCallback(lambda _ :
- self.scanExistingClassifiedChanges())
-
- # handle Deferred errors, since startService does not return a Deferred
- d.addErrback(log.err, "while starting SingleBranchScheduler '%s'"
- % self.name)
-
- if _returnDeferred:
- return d # only used in tests
-
- def stopService(self):
- # the base stopService will unsubscribe from new changes
- d = base.BaseScheduler.stopService(self)
- @util.deferredLocked(self._stable_timers_lock)
- def cancel_timers(_):
- for timer in self._stable_timers.values():
- if timer:
- timer.cancel()
- self._stable_timers.clear()
- d.addCallback(cancel_timers)
- return d
-
- @util.deferredLocked('_stable_timers_lock')
- def gotChange(self, change, important):
- if not self.treeStableTimer:
- # if there's no treeStableTimer, we can completely ignore
- # unimportant changes
- if not important:
- return defer.succeed(None)
- # otherwise, we'll build it right away
- return self.addBuildsetForChanges(reason='scheduler',
- changeids=[ change.number ])
-
- timer_name = self.getTimerNameForChange(change)
-
- # if we have a treeStableTimer, then record the change's importance
- # and:
- # - for an important change, start the timer
- # - for an unimportant change, reset the timer if it is running
- d = self.master.db.schedulers.classifyChanges(
- self.objectid, { change.number : important })
- def fix_timer(_):
- if not important and not self._stable_timers[timer_name]:
- return
- if self._stable_timers[timer_name]:
- self._stable_timers[timer_name].cancel()
- def fire_timer():
- d = self.stableTimerFired(timer_name)
- d.addErrback(log.err, "while firing stable timer")
- self._stable_timers[timer_name] = self._reactor.callLater(
- self.treeStableTimer, fire_timer)
- d.addCallback(fix_timer)
- return d
-
- @defer.inlineCallbacks
- def scanExistingClassifiedChanges(self):
- # call gotChange for each classified change. This is called at startup
- # and is intended to re-start the treeStableTimer for any changes that
- # had not yet been built when the scheduler was stopped.
-
- # NOTE: this may double-call gotChange for changes that arrive just as
- # the scheduler starts up. In practice, this doesn't hurt anything.
- classifications = \
- yield self.master.db.schedulers.getChangeClassifications(
- self.objectid)
-
- # call gotChange for each change, after first fetching it from the db
- for changeid, important in classifications.iteritems():
- chdict = yield self.master.db.changes.getChange(changeid)
-
- if not chdict:
- continue
-
- change = yield changes.Change.fromChdict(self.master, chdict)
- yield self.gotChange(change, important)
-
- def getTimerNameForChange(self, change):
- raise NotImplementedError # see subclasses
-
- def getChangeClassificationsForTimer(self, objectid, timer_name):
- """similar to db.schedulers.getChangeClassifications, but given timer
- name"""
- raise NotImplementedError # see subclasses
-
- @util.deferredLocked('_stable_timers_lock')
- @defer.inlineCallbacks
- def stableTimerFired(self, timer_name):
- # if the service has already been stoppd then just bail out
- if not self._stable_timers[timer_name]:
- return
-
- # delete this now-fired timer
- del self._stable_timers[timer_name]
-
- classifications = \
- yield self.getChangeClassificationsForTimer(self.objectid,
- timer_name)
-
- # just in case: databases do weird things sometimes!
- if not classifications: # pragma: no cover
- return
-
- changeids = sorted(classifications.keys())
- yield self.addBuildsetForChanges(reason='scheduler',
- changeids=changeids)
-
- max_changeid = changeids[-1] # (changeids are sorted)
- yield self.master.db.schedulers.flushChangeClassifications(
- self.objectid, less_than=max_changeid+1)
-
- def getPendingBuildTimes(self):
- # This isn't locked, since the caller expects and immediate value,
- # and in any case, this is only an estimate.
- return [timer.getTime() for timer in self._stable_timers.values() if timer and timer.active()]
-
-class SingleBranchScheduler(BaseBasicScheduler):
- def getChangeFilter(self, branch, branches, change_filter, categories):
- if branch is NotABranch and not change_filter:
- config.error(
- "the 'branch' argument to SingleBranchScheduler is " +
- "mandatory unless change_filter is provided")
- elif branches is not NotABranch:
- config.error(
- "the 'branches' argument is not allowed for " +
- "SingleBranchScheduler")
-
-
- return filter.ChangeFilter.fromSchedulerConstructorArgs(
- change_filter=change_filter, branch=branch,
- categories=categories)
-
- def getTimerNameForChange(self, change):
- return "only" # this class only uses one timer
-
- def getChangeClassificationsForTimer(self, objectid, timer_name):
- return self.master.db.schedulers.getChangeClassifications(
- self.objectid)
-
-
-class Scheduler(SingleBranchScheduler):
- "alias for SingleBranchScheduler"
- def __init__(self, *args, **kwargs):
- log.msg("WARNING: the name 'Scheduler' is deprecated; use " +
- "buildbot.schedulers.basic.SingleBranchScheduler instead " +
- "(note that this may require you to change your import " +
- "statement)")
- SingleBranchScheduler.__init__(self, *args, **kwargs)
-
-
-class AnyBranchScheduler(BaseBasicScheduler):
- def getChangeFilter(self, branch, branches, change_filter, categories):
- assert branch is NotABranch
- return filter.ChangeFilter.fromSchedulerConstructorArgs(
- change_filter=change_filter, branch=branches,
- categories=categories)
-
- def getTimerNameForChange(self, change):
- # Py2.6+: could be a namedtuple
- return (change.codebase, change.project, change.repository, change.branch)
-
- def getChangeClassificationsForTimer(self, objectid, timer_name):
- codebase, project, repository, branch = timer_name # set in getTimerNameForChange
- return self.master.db.schedulers.getChangeClassifications(
- self.objectid, branch=branch, repository=repository,
- codebase=codebase, project=project)
-
-# now at buildbot.schedulers.dependent, but keep the old name alive
-Dependent = dependent.Dependent
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/dependent.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/dependent.py
deleted file mode 100644
index f28df579..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/dependent.py
+++ /dev/null
@@ -1,148 +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 twisted.python import log
-from buildbot import util, interfaces, config
-from buildbot.status.results import SUCCESS, WARNINGS
-from buildbot.schedulers import base
-
-class Dependent(base.BaseScheduler):
-
- compare_attrs = base.BaseScheduler.compare_attrs + ('upstream_name',)
-
- def __init__(self, name, upstream, builderNames, properties={}, **kwargs):
- base.BaseScheduler.__init__(self, name, builderNames, properties,
- **kwargs)
- if not interfaces.IScheduler.providedBy(upstream):
- config.error(
- "upstream must be another Scheduler instance")
- self.upstream_name = upstream.name
- self._buildset_addition_subscr = None
- self._buildset_completion_subscr = None
- self._cached_upstream_bsids = None
-
- # the subscription lock makes sure that we're done inserting a
- # subcription into the DB before registering that the buildset is
- # complete.
- self._subscription_lock = defer.DeferredLock()
-
- def startService(self):
- self._buildset_addition_subscr = \
- self.master.subscribeToBuildsets(self._buildsetAdded)
- self._buildset_completion_subscr = \
- self.master.subscribeToBuildsetCompletions(self._buildsetCompleted)
-
- # check for any buildsets completed before we started
- d = self._checkCompletedBuildsets(None, None)
- d.addErrback(log.err, 'while checking for completed buildsets in start')
-
- def stopService(self):
- if self._buildset_addition_subscr:
- self._buildset_addition_subscr.unsubscribe()
- if self._buildset_completion_subscr:
- self._buildset_completion_subscr.unsubscribe()
- self._cached_upstream_bsids = None
- return defer.succeed(None)
-
- @util.deferredLocked('_subscription_lock')
- def _buildsetAdded(self, bsid=None, properties=None, **kwargs):
- # check if this was submitetted by our upstream by checking the
- # scheduler property
- submitter = properties.get('scheduler', (None, None))[0]
- if submitter != self.upstream_name:
- return
-
- # record our interest in this buildset
- d = self._addUpstreamBuildset(bsid)
- d.addErrback(log.err, 'while subscribing to buildset %d' % bsid)
-
- def _buildsetCompleted(self, bsid, result):
- d = self._checkCompletedBuildsets(bsid, result)
- d.addErrback(log.err, 'while checking for completed buildsets')
-
- @util.deferredLocked('_subscription_lock')
- @defer.inlineCallbacks
- def _checkCompletedBuildsets(self, bsid, result):
- subs = yield self._getUpstreamBuildsets()
-
- sub_bsids = []
- for (sub_bsid, sub_sssetid, sub_complete, sub_results) in subs:
- # skip incomplete builds, handling the case where the 'complete'
- # column has not been updated yet
- if not sub_complete and sub_bsid != bsid:
- continue
-
- # build a dependent build if the status is appropriate
- if sub_results in (SUCCESS, WARNINGS):
- yield self.addBuildsetForSourceStamp(setid=sub_sssetid,
- reason='downstream')
-
- sub_bsids.append(sub_bsid)
-
- # and regardless of status, remove the subscriptions
- yield self._removeUpstreamBuildsets(sub_bsids)
-
- @defer.inlineCallbacks
- def _updateCachedUpstreamBuilds(self):
- if self._cached_upstream_bsids is None:
- bsids = yield self.master.db.state.getState(self.objectid,
- 'upstream_bsids', [])
- self._cached_upstream_bsids = bsids
-
- @defer.inlineCallbacks
- def _getUpstreamBuildsets(self):
- # get a list of (bsid, sssid, complete, results) for all
- # upstream buildsets
- yield self._updateCachedUpstreamBuilds()
-
- changed = False
- rv = []
- for bsid in self._cached_upstream_bsids[:]:
- bsdict = yield self.master.db.buildsets.getBuildset(bsid)
- if not bsdict:
- self._cached_upstream_bsids.remove(bsid)
- changed = True
- continue
-
- rv.append((bsid, bsdict['sourcestampsetid'], bsdict['complete'],
- bsdict['results']))
-
- if changed:
- yield self.master.db.state.setState(self.objectid,
- 'upstream_bsids', self._cached_upstream_bsids)
-
- defer.returnValue(rv)
-
- @defer.inlineCallbacks
- def _addUpstreamBuildset(self, bsid):
- yield self._updateCachedUpstreamBuilds()
-
- if bsid not in self._cached_upstream_bsids:
- self._cached_upstream_bsids.append(bsid)
-
- yield self.master.db.state.setState(self.objectid,
- 'upstream_bsids', self._cached_upstream_bsids)
-
- @defer.inlineCallbacks
- def _removeUpstreamBuildsets(self, bsids):
- yield self._updateCachedUpstreamBuilds()
-
- old = set(self._cached_upstream_bsids)
- self._cached_upstream_bsids = list(old - set(bsids))
-
- yield self.master.db.state.setState(self.objectid,
- 'upstream_bsids', self._cached_upstream_bsids)
-
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/filter.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/filter.py
deleted file mode 100644
index c06e2315..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/filter.py
+++ /dev/null
@@ -1,18 +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
-
-# old (pre-0.8.4) location for ChangeFilter
-from buildbot.changes.filter import ChangeFilter
-_hush_pyflakes = ChangeFilter # keep pyflakes happy
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/forcesched.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/forcesched.py
deleted file mode 100644
index 90ff950f..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/forcesched.py
+++ /dev/null
@@ -1,666 +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 traceback
-import re
-from twisted.internet import defer
-import email.utils as email_utils
-
-from buildbot.process.properties import Properties
-from buildbot.schedulers import base
-from buildbot import config
-
-class ValidationError(ValueError):
- pass
-
-DefaultField = object() # sentinel object to signal default behavior
-
-class BaseParameter(object):
- """
- BaseParameter provides a base implementation for property customization
- """
- name = ""
- parentName = None
- label = ""
- type = []
- default = ""
- required = False
- multiple = False
- regex = None
- debug=True
- hide = False
-
- @property
- def fullName(self):
- """A full name, intended to uniquely identify a parameter"""
- # join with '_' if both are set
- if self.parentName and self.name:
- return self.parentName+'_'+self.name
- # otherwise just use the one that is set
- # (this allows empty name for "anonymous nests")
- return self.name or self.parentName
-
- def setParent(self, parent):
- self.parentName = parent.fullName if parent else None
-
- def __init__(self, name, label=None, regex=None, **kw):
- """
- @param name: the name of the field, used during posting values
- back to the scheduler. This is not necessarily a UI value,
- and there may be restrictions on the characters allowed for
- this value. For example, HTML would require this field to
- avoid spaces and other punctuation ('-', '.', and '_' allowed)
- @type name: unicode
-
- @param label: (optional) the name of the field, used for UI display.
- @type label: unicode or None (to use 'name')
-
- @param regex: (optional) regex to validate the value with. Not used by
- all subclasses
- @type regex: unicode or regex
- """
-
- self.name = name
- self.label = name if label is None else label
- if regex:
- self.regex = re.compile(regex)
- # all other properties are generically passed via **kw
- self.__dict__.update(kw)
-
- def getFromKwargs(self, kwargs):
- """Simple customization point for child classes that do not need the other
- parameters supplied to updateFromKwargs. Return the value for the property
- named 'self.name'.
-
- The default implementation converts from a list of items, validates using
- the optional regex field and calls 'parse_from_args' for the final conversion.
- """
- args = kwargs.get(self.fullName, [])
- if len(args) == 0:
- if self.required:
- raise ValidationError("'%s' needs to be specified" % (self.label))
- if self.multiple:
- args = self.default
- else:
- args = [self.default]
-
- if self.regex:
- for arg in args:
- if not self.regex.match(arg):
- raise ValidationError("%s:'%s' does not match pattern '%s'"
- % (self.label, arg, self.regex.pattern))
-
- try:
- arg = self.parse_from_args(args)
- except Exception, e:
- # an exception will just display an alert in the web UI
- # also log the exception
- if self.debug:
- traceback.print_exc()
- raise e
- if arg is None:
- raise ValidationError("need %s: no default provided by config"
- % (self.fullName,))
- return arg
-
- def updateFromKwargs(self, properties, kwargs, **unused):
- """Primary entry point to turn 'kwargs' into 'properties'"""
- properties[self.name] = self.getFromKwargs(kwargs)
-
- def parse_from_args(self, l):
- """Secondary customization point, called from getFromKwargs to turn
- a validated value into a single property value"""
- if self.multiple:
- return map(self.parse_from_arg, l)
- else:
- return self.parse_from_arg(l[0])
-
- def parse_from_arg(self, s):
- return s
-
-
-class FixedParameter(BaseParameter):
- """A fixed parameter that cannot be modified by the user."""
- type = ["fixed"]
- hide = True
- default = ""
-
- def parse_from_args(self, l):
- return self.default
-
-
-class StringParameter(BaseParameter):
- """A simple string parameter"""
- type = ["text"]
- size = 10
-
- def parse_from_arg(self, s):
- return s
-
-
-class TextParameter(StringParameter):
- """A generic string parameter that may span multiple lines"""
- type = ["textarea"]
- cols = 80
- rows = 20
-
- def value_to_text(self, value):
- return str(value)
-
-
-class IntParameter(StringParameter):
- """An integer parameter"""
- type = ["int"]
-
- parse_from_arg = int # will throw an exception if parse fail
-
-
-class BooleanParameter(BaseParameter):
- """A boolean parameter"""
- type = ["bool"]
-
- def getFromKwargs(self, kwargs):
- return kwargs.get(self.fullName, None) == [True]
-
-
-class UserNameParameter(StringParameter):
- """A username parameter to supply the 'owner' of a build"""
- type = ["text"]
- default = ""
- size = 30
- need_email = True
-
- def __init__(self, name="username", label="Your name:", **kw):
- BaseParameter.__init__(self, name, label, **kw)
-
- def parse_from_arg(self, s):
- if not s and not self.required:
- return s
- if self.need_email:
- e = email_utils.parseaddr(s)
- if e[0]=='' or e[1] == '':
- raise ValidationError("%s: please fill in email address in the "
- "form 'User <email@email.com>'" % (self.name,))
- return s
-
-
-class ChoiceStringParameter(BaseParameter):
- """A list of strings, allowing the selection of one of the predefined values.
- The 'strict' parameter controls whether values outside the predefined list
- of choices are allowed"""
- type = ["list"]
- choices = []
- strict = True
-
- def parse_from_arg(self, s):
- if self.strict and not s in self.choices:
- raise ValidationError("'%s' does not belongs to list of available choices '%s'"%(s, self.choices))
- return s
-
- def getChoices(self, master, scheduler, buildername):
- return self.choices
-
-class InheritBuildParameter(ChoiceStringParameter):
- """A parameter that takes its values from another build"""
- type = ChoiceStringParameter.type + ["inherit"]
- name = "inherit"
- compatible_builds = None
-
- def getChoices(self, master, scheduler, buildername):
- return self.compatible_builds(master.status, buildername)
-
- def getFromKwargs(self, kwargs):
- raise ValidationError("InheritBuildParameter can only be used by properties")
-
- def updateFromKwargs(self, master, properties, changes, kwargs, **unused):
- arg = kwargs.get(self.fullName, [""])[0]
- splitted_arg = arg.split(" ")[0].split("/")
- if len(splitted_arg) != 2:
- raise ValidationError("bad build: %s"%(arg))
- builder, num = splitted_arg
- builder_status = master.status.getBuilder(builder)
- if not builder_status:
- raise ValidationError("unknown builder: %s in %s"%(builder, arg))
- b = builder_status.getBuild(int(num))
- if not b:
- raise ValidationError("unknown build: %d in %s"%(num, arg))
- props = {self.name:(arg.split(" ")[0])}
- for name, value, source in b.getProperties().asList():
- if source == "Force Build Form":
- if name == "owner":
- name = "orig_owner"
- props[name] = value
- properties.update(props)
- changes.extend(b.changes)
-
-
-class BuildslaveChoiceParameter(ChoiceStringParameter):
- """A parameter that lets the buildslave name be explicitly chosen.
-
- This parameter works in conjunction with 'buildbot.process.builder.enforceChosenSlave',
- which should be added as the 'canStartBuild' parameter to the Builder.
-
- The "anySentinel" parameter represents the sentinel value to specify that
- there is no buildslave preference.
- """
- anySentinel = '-any-'
- label = 'Build slave'
- required = False
- strict = False
-
- def __init__(self, name='slavename', **kwargs):
- ChoiceStringParameter.__init__(self, name, **kwargs)
-
- def updateFromKwargs(self, kwargs, **unused):
- slavename = self.getFromKwargs(kwargs)
- if slavename==self.anySentinel:
- # no preference, so dont set a parameter at all
- return
- ChoiceStringParameter.updateFromKwargs(self, kwargs=kwargs, **unused)
-
- def getChoices(self, master, scheduler, buildername):
- if buildername is None:
- # this is the "Force All Builds" page
- slavenames = master.status.getSlaveNames()
- else:
- builderStatus = master.status.getBuilder(buildername)
- slavenames = [slave.getName() for slave in builderStatus.getSlaves()]
- slavenames.sort()
- slavenames.insert(0, self.anySentinel)
- return slavenames
-
-
-class NestedParameter(BaseParameter):
- """A 'parent' parameter for a set of related parameters. This provices a
- logical grouping for the child parameters.
-
- Typically, the 'fullName' of the child parameters mix in the parent's
- 'fullName'. This allows for a field to appear multiple times in a form
- (for example, two codebases each have a 'branch' field).
-
- If the 'name' of the parent is the empty string, then the parent's name
- does not mix in with the child 'fullName'. This is useful when a field
- will not appear multiple time in a scheduler but the logical grouping is
- helpful.
-
- The result of a NestedParameter is typically a dictionary, with the key/value
- being the name/value of the children.
- """
- type = ['nested']
- fields = None
-
- def __init__(self, name, fields, **kwargs):
- BaseParameter.__init__(self, fields=fields, name=name, **kwargs)
-
- # fix up the child nodes with the parent (use None for now):
- self.setParent(None)
-
- def setParent(self, parent):
- BaseParameter.setParent(self, parent)
- for field in self.fields:
- field.setParent(self)
-
- def collectChildProperties(self, kwargs, properties, **kw):
- """Collapse the child values into a dictionary. This is intended to be
- called by child classes to fix up the fullName->name conversions."""
-
- childProperties = {}
- for field in self.fields:
- field.updateFromKwargs(kwargs=kwargs,
- properties=childProperties,
- **kw)
-
- kwargs[self.fullName] = childProperties
-
- def updateFromKwargs(self, kwargs, properties, **kw):
- """By default, the child values will be collapsed into a dictionary. If
- the parent is anonymous, this dictionary is the top-level properties."""
- self.collectChildProperties(kwargs=kwargs, properties=properties, **kw)
-
- # default behavior is to set a property
- # -- use setdefault+update in order to collapse 'anonymous' nested
- # parameters correctly
- if self.name:
- d = properties.setdefault(self.name, {})
- else:
- # if there's no name, collapse this nest all the way
- d = properties
- d.update(kwargs[self.fullName])
-
-class AnyPropertyParameter(NestedParameter):
- """A generic property parameter, where both the name and value of the property
- must be given."""
- type = NestedParameter.type + ["any"]
-
- def __init__(self, name, **kw):
- fields = [
- StringParameter(name='name', label="Name:"),
- StringParameter(name='value', label="Value:"),
- ]
- NestedParameter.__init__(self, name, label='', fields=fields, **kw)
-
- def getFromKwargs(self, kwargs):
- raise ValidationError("AnyPropertyParameter can only be used by properties")
-
- def updateFromKwargs(self, master, properties, kwargs, **kw):
- self.collectChildProperties(master=master,
- properties=properties,
- kwargs=kwargs,
- **kw)
-
- pname = kwargs[self.fullName].get("name", "")
- pvalue = kwargs[self.fullName].get("value", "")
- if not pname:
- return
-
- validation = master.config.validation
- pname_validate = validation['property_name']
- pval_validate = validation['property_value']
-
- if not pname_validate.match(pname) \
- or not pval_validate.match(pvalue):
- raise ValidationError("bad property name='%s', value='%s'" % (pname, pvalue))
- properties[pname] = pvalue
-
-
-class CodebaseParameter(NestedParameter):
- """A parameter whose result is a codebase specification instead of a property"""
- type = NestedParameter.type + ["codebase"]
- codebase = ''
-
- def __init__(self,
- codebase,
- name=None,
- label=None,
-
- branch=DefaultField,
- revision=DefaultField,
- repository=DefaultField,
- project=DefaultField,
-
- **kwargs):
- """
- A set of properties that will be used to generate a codebase dictionary.
-
- The branch/revision/repository/project should each be a parameter that
- will map to the corresponding value in the sourcestamp. Use None to disable
- the field.
-
- @param codebase: name of the codebase; used as key for the sourcestamp set
- @type codebase: unicode
-
- @param name: optional override for the name-currying for the subfields
- @type codebase: unicode
-
- @param label: optional override for the label for this set of parameters
- @type codebase: unicode
- """
-
- name = name or codebase
- if label is None and codebase:
- label = "Codebase: " + codebase
-
- if branch is DefaultField:
- branch = StringParameter(name='branch', label="Branch:")
- if revision is DefaultField:
- revision = StringParameter(name='revision', label="Revision:")
- if repository is DefaultField:
- repository = StringParameter(name='repository', label="Repository:")
- if project is DefaultField:
- project = StringParameter(name='project', label="Project:")
-
- fields = filter(None, [branch, revision, repository, project])
-
- NestedParameter.__init__(self, name=name, label=label,
- codebase=codebase,
- fields=fields, **kwargs)
-
- def createSourcestamp(self, properties, kwargs):
- # default, just return the things we put together
- return kwargs.get(self.fullName, {})
-
- def updateFromKwargs(self, sourcestamps, kwargs, properties, **kw):
- self.collectChildProperties(sourcestamps=sourcestamps,
- properties=properties,
- kwargs=kwargs,
- **kw)
-
- # convert the "property" to a sourcestamp
- ss = self.createSourcestamp(properties, kwargs)
- if ss is not None:
- sourcestamps[self.codebase] = ss
-
-
-class ForceScheduler(base.BaseScheduler):
- """
- ForceScheduler implements the backend for a UI to allow customization of
- builds. For example, a web form be populated to trigger a build.
- """
- compare_attrs = ( 'name', 'builderNames',
- 'reason', 'username',
- 'forcedProperties' )
-
- def __init__(self, name, builderNames,
- username=UserNameParameter(),
- reason=StringParameter(name="reason", default="force build", length=20),
-
- codebases=None,
-
- properties=[
- NestedParameter(name='', fields=[
- AnyPropertyParameter("property1"),
- AnyPropertyParameter("property2"),
- AnyPropertyParameter("property3"),
- AnyPropertyParameter("property4"),
- ])
- ],
-
- # deprecated; use 'codebase' instead
- branch=None,
- revision=None,
- repository=None,
- project=None
- ):
- """
- Initialize a ForceScheduler.
-
- The UI will provide a set of fields to the user; these fields are
- driven by a corresponding child class of BaseParameter.
-
- Use NestedParameter to provide logical groupings for parameters.
-
- The branch/revision/repository/project fields are deprecated and
- provided only for backwards compatibility. Using a Codebase(name='')
- will give the equivalent behavior.
-
- @param name: name of this scheduler (used as a key for state)
- @type name: unicode
-
- @param builderNames: list of builders this scheduler may start
- @type builderNames: list of unicode
-
- @param username: the "owner" for a build (may not be shown depending
- on the Auth configuration for the master)
- @type username: BaseParameter
-
- @param reason: the "reason" for a build
- @type reason: BaseParameter
-
- @param codebases: the codebases for a build
- @type codebases: list of string's or CodebaseParameter's;
- None will generate a default, but [] will
- remove all codebases
-
- @param properties: extra properties to configure the build
- @type properties: list of BaseParameter's
- """
-
- if not self.checkIfType(name, str):
- config.error("ForceScheduler name must be a unicode string: %r" %
- name)
-
- if not name:
- config.error("ForceScheduler name must not be empty: %r " %
- name)
-
- if not self.checkIfListOfType(builderNames, str):
- config.error("ForceScheduler builderNames must be a list of strings: %r" %
- builderNames)
-
- if self.checkIfType(reason, BaseParameter):
- self.reason = reason
- else:
- config.error("ForceScheduler reason must be a StringParameter: %r" %
- reason)
-
- if not self.checkIfListOfType(properties, BaseParameter):
- config.error("ForceScheduler properties must be a list of BaseParameters: %r" %
- properties)
-
- if self.checkIfType(username, BaseParameter):
- self.username = username
- else:
- config.error("ForceScheduler username must be a StringParameter: %r" %
- username)
-
- self.forcedProperties = []
-
- if any((branch, revision, repository, project)):
- if codebases:
- config.error("ForceScheduler: Must either specify 'codebases' or the 'branch/revision/repository/project' parameters: %r " % (codebases,))
-
- codebases = [
- CodebaseParameter(codebase='',
- branch=branch or DefaultField,
- revision=revision or DefaultField,
- repository=repository or DefaultField,
- project=project or DefaultField,
- )
- ]
-
- # Use the default single codebase form if none are provided
- if codebases is None:
- codebases =[CodebaseParameter(codebase='')]
- elif not codebases:
- config.error("ForceScheduler: 'codebases' cannot be empty; use CodebaseParameter(codebase='', hide=True) if needed: %r " % (codebases,))
-
- codebase_dict = {}
- for codebase in codebases:
- if isinstance(codebase, basestring):
- codebase = CodebaseParameter(codebase=codebase)
- elif not isinstance(codebase, CodebaseParameter):
- config.error("ForceScheduler: 'codebases' must be a list of strings or CodebaseParameter objects: %r" % (codebases,))
-
- self.forcedProperties.append(codebase)
- codebase_dict[codebase.codebase] = dict(branch='',repository='',revision='')
-
- base.BaseScheduler.__init__(self,
- name=name,
- builderNames=builderNames,
- properties={},
- codebases=codebase_dict)
-
- if properties:
- self.forcedProperties.extend(properties)
-
- # this is used to simplify the template
- self.all_fields = [ NestedParameter(name='', fields=[username, reason]) ]
- self.all_fields.extend(self.forcedProperties)
-
- def checkIfType(self, obj, chkType):
- return isinstance(obj, chkType)
-
- def checkIfListOfType(self, obj, chkType):
- isListOfType = True
-
- if self.checkIfType(obj, list):
- for item in obj:
- if not self.checkIfType(item, chkType):
- isListOfType = False
- break
- else:
- isListOfType = False
-
- return isListOfType
-
- def startService(self):
- pass
-
- def stopService(self):
- pass
-
- @defer.inlineCallbacks
- def gatherPropertiesAndChanges(self, **kwargs):
- properties = {}
- changeids = []
- sourcestamps = {}
-
- for param in self.forcedProperties:
- yield defer.maybeDeferred(param.updateFromKwargs,
- master=self.master,
- properties=properties,
- changes=changeids,
- sourcestamps=sourcestamps,
- kwargs=kwargs)
-
- changeids = map(lambda a: type(a)==int and a or a.number, changeids)
-
- real_properties = Properties()
- for pname, pvalue in properties.items():
- real_properties.setProperty(pname, pvalue, "Force Build Form")
-
- defer.returnValue((real_properties, changeids, sourcestamps))
-
- @defer.inlineCallbacks
- def force(self, owner, builderNames=None, **kwargs):
- """
- We check the parameters, and launch the build, if everything is correct
- """
- if builderNames is None:
- builderNames = self.builderNames
- else:
- builderNames = set(builderNames).intersection(self.builderNames)
-
- if not builderNames:
- defer.returnValue(None)
- return
-
- # Currently the validation code expects all kwargs to be lists
- # I don't want to refactor that now so much sure we comply...
- kwargs = dict((k, [v]) if not isinstance(v, list) else (k,v) for k,v in kwargs.items())
-
- # probably need to clean that out later as the IProperty is already a
- # validation mechanism
-
- reason = self.reason.getFromKwargs(kwargs)
- if owner is None:
- owner = self.username.getFromKwargs(kwargs)
-
- properties, changeids, sourcestamps = yield self.gatherPropertiesAndChanges(**kwargs)
-
- properties.setProperty("reason", reason, "Force Build Form")
- properties.setProperty("owner", owner, "Force Build Form")
-
- r = ("A build was forced by '%s': %s" % (owner, reason))
-
- # everything is validated, we can create our source stamp, and buildrequest
- res = yield self.addBuildsetForSourceStampSetDetails(
- reason = r,
- sourcestamps = sourcestamps,
- properties = properties,
- builderNames = builderNames,
- )
-
- defer.returnValue(res)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/manager.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/manager.py
deleted file mode 100644
index d4c8b795..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/manager.py
+++ /dev/null
@@ -1,95 +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 twisted.application import service
-from twisted.python import log, reflect
-from buildbot.process import metrics
-from buildbot import config, util
-
-class SchedulerManager(config.ReconfigurableServiceMixin,
- service.MultiService):
- def __init__(self, master):
- service.MultiService.__init__(self)
- self.setName('scheduler_manager')
- self.master = master
-
- @defer.inlineCallbacks
- def reconfigService(self, new_config):
- timer = metrics.Timer("SchedulerManager.reconfigService")
- timer.start()
-
- old_by_name = dict((sch.name, sch) for sch in self)
- old_set = set(old_by_name.iterkeys())
- new_by_name = new_config.schedulers
- new_set = set(new_by_name.iterkeys())
-
- removed_names, added_names = util.diffSets(old_set, new_set)
-
- # find any schedulers that don't know how to reconfig, and, if they
- # have changed, add them to both removed and added, so that we
- # run the new version. While we're at it, find any schedulers whose
- # fully qualified class name has changed, and consider those a removal
- # and re-add as well.
- for n in old_set & new_set:
- old = old_by_name[n]
- new = new_by_name[n]
- # detect changed class name
- if reflect.qual(old.__class__) != reflect.qual(new.__class__):
- removed_names.add(n)
- added_names.add(n)
-
- # compare using ComparableMixin if they don't support reconfig
- elif not hasattr(old, 'reconfigService'):
- if old != new:
- removed_names.add(n)
- added_names.add(n)
-
- # removals first
-
- for sch_name in removed_names:
- log.msg("removing scheduler '%s'" % (sch_name,))
- sch = old_by_name[sch_name]
- yield defer.maybeDeferred(lambda :
- sch.disownServiceParent())
- sch.master = None
-
- # .. then additions
-
- for sch_name in added_names:
- log.msg("adding scheduler '%s'" % (sch_name,))
- sch = new_by_name[sch_name]
-
- # get the scheduler's objectid
- class_name = '%s.%s' % (sch.__class__.__module__,
- sch.__class__.__name__)
- objectid = yield self.master.db.state.getObjectId(
- sch.name, class_name)
-
- # set up the scheduler
- sch.objectid = objectid
- sch.master = self.master
-
- # *then* attacah and start it
- sch.setServiceParent(self)
-
- metrics.MetricCountEvent.log("num_schedulers", len(list(self)),
- absolute=True)
-
- # reconfig any newly-added schedulers, as well as existing
- yield config.ReconfigurableServiceMixin.reconfigService(self,
- new_config)
-
- timer.stop()
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/timed.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/timed.py
deleted file mode 100644
index e735ca93..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/timed.py
+++ /dev/null
@@ -1,410 +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 util
-from buildbot.interfaces import ITriggerableScheduler
-from buildbot.process import buildstep, properties
-from buildbot.schedulers import base
-from twisted.internet import defer, reactor
-from twisted.python import log
-from buildbot import config
-from buildbot.changes import filter
-# Import croniter if available.
-# This is only required for Nightly schedulers,
-# so fail gracefully if it isn't present.
-try:
- from buildbot.util import croniter
-except ImportError:
- # Pyflakes doesn't like a redefinition here
- # Instead, we check if croniter is defined when we need it
- pass
-
-class Timed(base.BaseScheduler):
- """
- Parent class for timed schedulers. This takes care of the (surprisingly
- subtle) mechanics of ensuring that each timed actuation runs to completion
- before the service stops.
- """
-
- compare_attrs = base.BaseScheduler.compare_attrs
-
- def __init__(self, name, builderNames, properties={}, **kwargs):
- base.BaseScheduler.__init__(self, name, builderNames, properties,
- **kwargs)
-
- # tracking for when to start the next build
- self.lastActuated = None
-
- # A lock to make sure that each actuation occurs without interruption.
- # This lock governs actuateAt, actuateAtTimer, and actuateOk
- self.actuationLock = defer.DeferredLock()
- self.actuateOk = False
- self.actuateAt = None
- self.actuateAtTimer = None
-
- self._reactor = reactor # patched by tests
-
- def startService(self):
- base.BaseScheduler.startService(self)
-
- # no need to lock this; nothing else can run before the service is started
- self.actuateOk = True
-
- # get the scheduler's last_build time (note: only done at startup)
- d = self.getState('last_build', None)
- def set_last(lastActuated):
- self.lastActuated = lastActuated
- d.addCallback(set_last)
-
- # schedule the next build
- d.addCallback(lambda _ : self.scheduleNextBuild())
-
- # give subclasses a chance to start up
- d.addCallback(lambda _ : self.startTimedSchedulerService())
-
- # startService does not return a Deferred, so handle errors with a traceback
- d.addErrback(log.err, "while initializing %s '%s'" %
- (self.__class__.__name__, self.name))
-
- def startTimedSchedulerService(self):
- """Hook for subclasses to participate in the L{startService} process;
- can return a Deferred"""
-
- def stopService(self):
- # shut down any pending actuation, and ensure that we wait for any
- # current actuation to complete by acquiring the lock. This ensures
- # that no build will be scheduled after stopService is complete.
- def stop_actuating():
- self.actuateOk = False
- self.actuateAt = None
- if self.actuateAtTimer:
- self.actuateAtTimer.cancel()
- self.actuateAtTimer = None
- d = self.actuationLock.run(stop_actuating)
-
- # and chain to the parent class
- d.addCallback(lambda _ : base.BaseScheduler.stopService(self))
- return d
-
- ## Scheduler methods
-
- def getPendingBuildTimes(self):
- # take the latest-calculated value of actuateAt as a reasonable
- # estimate
- return [ self.actuateAt ]
-
- ## Timed methods
-
- def startBuild(self):
- """The time has come to start a new build. Returns a Deferred.
- Override in subclasses."""
- raise NotImplementedError
-
- def getNextBuildTime(self, lastActuation):
- """
- Called by to calculate the next time to actuate a BuildSet. Override
- in subclasses. To trigger a fresh call to this method, use
- L{rescheduleNextBuild}.
-
- @param lastActuation: the time of the last actuation, or None for never
-
- @returns: a Deferred firing with the next time a build should occur (in
- the future), or None for never.
- """
- raise NotImplementedError
-
- def scheduleNextBuild(self):
- """
- Schedule the next build, re-invoking L{getNextBuildTime}. This can be
- called at any time, and it will avoid contention with builds being
- started concurrently.
-
- @returns: Deferred
- """
- return self.actuationLock.run(self._scheduleNextBuild_locked)
-
- ## utilities
-
- def now(self):
- "Similar to util.now, but patchable by tests"
- return util.now(self._reactor)
-
- def _scheduleNextBuild_locked(self):
- # clear out the existing timer
- if self.actuateAtTimer:
- self.actuateAtTimer.cancel()
- self.actuateAtTimer = None
-
- # calculate the new time
- d = self.getNextBuildTime(self.lastActuated)
-
- # set up the new timer
- def set_timer(actuateAt):
- now = self.now()
- self.actuateAt = max(actuateAt, now)
- if actuateAt is not None:
- untilNext = self.actuateAt - now
- if untilNext == 0:
- log.msg(("%s: missed scheduled build time, so building "
- "immediately") % self.name)
- self.actuateAtTimer = self._reactor.callLater(untilNext,
- self._actuate)
- d.addCallback(set_timer)
-
- return d
-
- def _actuate(self):
- # called from the timer when it's time to start a build
- self.actuateAtTimer = None
- self.lastActuated = self.actuateAt
-
- @defer.inlineCallbacks
- def set_state_and_start():
- # bail out if we shouldn't be actuating anymore
- if not self.actuateOk:
- return
-
- # mark the last build time
- self.actuateAt = None
- yield self.setState('last_build', self.lastActuated)
-
- # start the build
- yield self.startBuild()
-
- # schedule the next build (noting the lock is already held)
- yield self._scheduleNextBuild_locked()
- d = self.actuationLock.run(set_state_and_start)
-
- # this function can't return a deferred, so handle any failures via
- # log.err
- d.addErrback(log.err, 'while actuating')
-
-
-class Periodic(Timed):
- compare_attrs = Timed.compare_attrs + ('periodicBuildTimer', 'branch',)
-
- def __init__(self, name, builderNames, periodicBuildTimer,
- branch=None, properties={}, onlyImportant=False):
- Timed.__init__(self, name=name, builderNames=builderNames,
- properties=properties)
- if periodicBuildTimer <= 0:
- config.error(
- "periodicBuildTimer must be positive")
- self.periodicBuildTimer = periodicBuildTimer
- self.branch = branch
- self.reason = "The Periodic scheduler named '%s' triggered this build" % self.name
-
- def getNextBuildTime(self, lastActuated):
- if lastActuated is None:
- return defer.succeed(self.now()) # meaning "ASAP"
- else:
- return defer.succeed(lastActuated + self.periodicBuildTimer)
-
- def startBuild(self):
- return self.addBuildsetForLatest(reason=self.reason, branch=self.branch)
-
-class NightlyBase(Timed):
- compare_attrs = (Timed.compare_attrs
- + ('minute', 'hour', 'dayOfMonth', 'month', 'dayOfWeek'))
-
- def __init__(self, name, builderNames, minute=0, hour='*',
- dayOfMonth='*', month='*', dayOfWeek='*',
- properties={}, codebases=base.BaseScheduler.DefaultCodebases):
- Timed.__init__(self, name=name, builderNames=builderNames,
- properties=properties, codebases=codebases)
-
- self.minute = minute
- self.hour = hour
- self.dayOfMonth = dayOfMonth
- self.month = month
- self.dayOfWeek = dayOfWeek
-
- try:
- croniter
- except NameError:
- config.error("python-dateutil required for scheduler %s '%s'." %
- (self.__class__.__name__, self.name))
-
- def _timeToCron(self, time, isDayOfWeek = False):
- if isinstance(time, int):
- if isDayOfWeek:
- time = (time + 1) % 7 # Convert from Mon = 0 format to Sun = 0 format for use in croniter
- return time
-
- if isinstance(time, basestring):
- return time
-
- if isDayOfWeek:
- time = [ (t + 1) % 7 for t in time ] # Conversion for croniter (see above)
-
- return ','.join([ str(s) for s in time ]) # Convert the list to a string
-
- def getNextBuildTime(self, lastActuated):
- dateTime = lastActuated or self.now()
- sched = '%s %s %s %s %s' % (self._timeToCron(self.minute),
- self._timeToCron(self.hour),
- self._timeToCron(self.dayOfMonth),
- self._timeToCron(self.month),
- self._timeToCron(self.dayOfWeek, True))
- cron = croniter.croniter(sched, dateTime)
- nextdate = cron.get_next(float)
- return defer.succeed(nextdate)
-
-class Nightly(NightlyBase):
- compare_attrs = (NightlyBase.compare_attrs
- + ('branch', 'onlyIfChanged', 'fileIsImportant',
- 'change_filter', 'onlyImportant',))
-
- class NoBranch: pass
- def __init__(self, name, builderNames, minute=0, hour='*',
- dayOfMonth='*', month='*', dayOfWeek='*',
- branch=NoBranch, fileIsImportant=None, onlyIfChanged=False,
- properties={}, change_filter=None, onlyImportant=False,
- codebases = base.BaseScheduler.DefaultCodebases):
- NightlyBase.__init__(self, name=name, builderNames=builderNames,
- minute=minute, hour=hour, dayOfWeek=dayOfWeek, dayOfMonth=dayOfMonth,
- properties=properties, codebases=codebases)
-
- # If True, only important changes will be added to the buildset.
- self.onlyImportant = onlyImportant
-
- if fileIsImportant and not callable(fileIsImportant):
- config.error(
- "fileIsImportant must be a callable")
-
- if branch is Nightly.NoBranch:
- config.error(
- "Nightly parameter 'branch' is required")
-
- self.branch = branch
- self.onlyIfChanged = onlyIfChanged
- self.fileIsImportant = fileIsImportant
- self.change_filter = filter.ChangeFilter.fromSchedulerConstructorArgs(
- change_filter=change_filter)
- self.reason = "The Nightly scheduler named '%s' triggered this build" % self.name
-
- def startTimedSchedulerService(self):
- if self.onlyIfChanged:
- return self.startConsumingChanges(fileIsImportant=self.fileIsImportant,
- change_filter=self.change_filter,
- onlyImportant=self.onlyImportant)
- else:
- return self.master.db.schedulers.flushChangeClassifications(self.objectid)
-
- def gotChange(self, change, important):
- # both important and unimportant changes on our branch are recorded, as
- # we will include all such changes in any buildsets we start. Note
- # that we must check the branch here because it is not included in the
- # change filter.
- if change.branch != self.branch:
- return defer.succeed(None) # don't care about this change
- return self.master.db.schedulers.classifyChanges(
- self.objectid, { change.number : important })
-
- @defer.inlineCallbacks
- def startBuild(self):
- scheds = self.master.db.schedulers
- # if onlyIfChanged is True, then we will skip this build if no
- # important changes have occurred since the last invocation
- if self.onlyIfChanged:
- classifications = \
- yield scheds.getChangeClassifications(self.objectid)
-
- # see if we have any important changes
- for imp in classifications.itervalues():
- if imp:
- break
- else:
- log.msg(("Nightly Scheduler <%s>: skipping build " +
- "- No important changes on configured branch") % self.name)
- return
-
- changeids = sorted(classifications.keys())
- yield self.addBuildsetForChanges(reason=self.reason,
- changeids=changeids)
-
- max_changeid = changeids[-1] # (changeids are sorted)
- yield scheds.flushChangeClassifications(self.objectid,
- less_than=max_changeid+1)
- else:
- # start a build of the latest revision, whatever that is
- yield self.addBuildsetForLatest(reason=self.reason,
- branch=self.branch)
-
-class NightlyTriggerable(NightlyBase):
- implements(ITriggerableScheduler)
- def __init__(self, name, builderNames, minute=0, hour='*',
- dayOfMonth='*', month='*', dayOfWeek='*',
- properties={}, codebases=base.BaseScheduler.DefaultCodebases):
- NightlyBase.__init__(self, name=name, builderNames=builderNames, minute=minute, hour=hour,
- dayOfWeek=dayOfWeek, dayOfMonth=dayOfMonth, properties=properties, codebases=codebases)
-
- self._lastTrigger = None
- self.reason = "The NightlyTriggerable scheduler named '%s' triggered this build" % self.name
-
- def startService(self):
- NightlyBase.startService(self)
-
- # get the scheduler's lastTrigger time (note: only done at startup)
- d = self.getState('lastTrigger', None)
- def setLast(lastTrigger):
- try:
- if lastTrigger:
- assert isinstance(lastTrigger[0], dict)
- self._lastTrigger = (lastTrigger[0], properties.Properties.fromDict(lastTrigger[1]))
- except:
- # If the lastTrigger isn't of the right format, ignore it
- log.msg("NightlyTriggerable Scheduler <%s>: bad lastTrigger: %r" % (self.name, lastTrigger))
- d.addCallback(setLast)
-
- def trigger(self, sourcestamps, set_props=None):
- """Trigger this scheduler with the given sourcestamp ID. Returns a
- deferred that will fire when the buildset is finished."""
- self._lastTrigger = (sourcestamps, set_props)
-
- # record the trigger in the db
- if set_props:
- propsDict = set_props.asDict()
- else:
- propsDict = {}
- d = self.setState('lastTrigger',
- (sourcestamps, propsDict))
-
- ## Trigger expects a callback with the success of the triggered
- ## build, if waitForFinish is True.
- ## Just return SUCCESS, to indicate that the trigger was succesful,
- ## don't want for the nightly to run.
- return d.addCallback(lambda _: buildstep.SUCCESS)
-
- @defer.inlineCallbacks
- def startBuild(self):
- if self._lastTrigger is None:
- defer.returnValue(None)
-
- (sourcestamps, set_props) = self._lastTrigger
- self._lastTrigger = None
- yield self.setState('lastTrigger', None)
-
- # properties for this buildset are composed of our own properties,
- # potentially overridden by anything from the triggering build
- props = properties.Properties()
- props.updateFromProperties(self.properties)
- if set_props:
- props.updateFromProperties(set_props)
-
- yield self.addBuildsetForSourceStampSetDetails(reason=self.reason, sourcestamps=sourcestamps,
- properties=props)
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/triggerable.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/triggerable.py
deleted file mode 100644
index a50e120e..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/triggerable.py
+++ /dev/null
@@ -1,94 +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 failure
-from twisted.internet import defer
-from buildbot.interfaces import ITriggerableScheduler
-from buildbot.schedulers import base
-from buildbot.process.properties import Properties
-
-class Triggerable(base.BaseScheduler):
- implements(ITriggerableScheduler)
-
- compare_attrs = base.BaseScheduler.compare_attrs
-
- def __init__(self, name, builderNames, properties={}, **kwargs):
- base.BaseScheduler.__init__(self, name, builderNames, properties,
- **kwargs)
- self._waiters = {}
- self._bsc_subscription = None
- self.reason = "Triggerable(%s)" % name
-
- def trigger(self, sourcestamps = None, set_props=None):
- """Trigger this scheduler with the optional given list of sourcestamps
- Returns a deferred that will fire when the buildset is finished."""
- # properties for this buildset are composed of our own properties,
- # potentially overridden by anything from the triggering build
- props = Properties()
- props.updateFromProperties(self.properties)
- if set_props:
- props.updateFromProperties(set_props)
-
- # note that this does not use the buildset subscriptions mechanism, as
- # the duration of interest to the caller is bounded by the lifetime of
- # this process.
- d = self.addBuildsetForSourceStampSetDetails(self.reason,
- sourcestamps, props)
- def setup_waiter((bsid,brids)):
- d = defer.Deferred()
- self._waiters[bsid] = (d, brids)
- self._updateWaiters()
- return d
- d.addCallback(setup_waiter)
- return d
-
- def stopService(self):
- # cancel any outstanding subscription
- if self._bsc_subscription:
- self._bsc_subscription.unsubscribe()
- self._bsc_subscription = None
-
- # and errback any outstanding deferreds
- if self._waiters:
- msg = 'Triggerable scheduler stopped before build was complete'
- for d, brids in self._waiters.values():
- d.errback(failure.Failure(RuntimeError(msg)))
- self._waiters = {}
-
- return base.BaseScheduler.stopService(self)
-
-
- def _updateWaiters(self):
- if self._waiters and not self._bsc_subscription:
- self._bsc_subscription = \
- self.master.subscribeToBuildsetCompletions(
- self._buildsetComplete)
- elif not self._waiters and self._bsc_subscription:
- self._bsc_subscription.unsubscribe()
- self._bsc_subscription = None
-
- def _buildsetComplete(self, bsid, result):
- if bsid not in self._waiters:
- return
-
- # pop this bsid from the waiters list, and potentially unsubscribe
- # from completion notifications
- d, brids = self._waiters.pop(bsid)
- self._updateWaiters()
-
- # fire the callback to indicate that the triggered build is complete
- d.callback((result, brids))
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/trysched.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/trysched.py
deleted file mode 100644
index 79179ba8..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/schedulers/trysched.py
+++ /dev/null
@@ -1,304 +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 twisted.internet import defer
-from twisted.python import log
-from twisted.protocols import basic
-
-from buildbot import pbutil
-from buildbot.util.maildir import MaildirService
-from buildbot.util import json
-from buildbot.util import netstrings
-from buildbot.process.properties import Properties
-from buildbot.schedulers import base
-from buildbot.status.buildset import BuildSetStatus
-
-
-class TryBase(base.BaseScheduler):
-
- def filterBuilderList(self, builderNames):
- """
- Make sure that C{builderNames} is a subset of the configured
- C{self.builderNames}, returning an empty list if not. If
- C{builderNames} is empty, use C{self.builderNames}.
-
- @returns: list of builder names to build on
- """
-
- # self.builderNames is the configured list of builders
- # available for try. If the user supplies a list of builders,
- # it must be restricted to the configured list. If not, build
- # on all of the configured builders.
- if builderNames:
- for b in builderNames:
- if not b in self.builderNames:
- log.msg("%s got with builder %s" % (self, b))
- log.msg(" but that wasn't in our list: %s"
- % (self.builderNames,))
- return []
- else:
- builderNames = self.builderNames
- return builderNames
-
-
-class BadJobfile(Exception):
- pass
-
-
-class JobdirService(MaildirService):
- # NOTE: tightly coupled with Try_Jobdir, below
-
- def messageReceived(self, filename):
- f = self.moveToCurDir(filename)
- return self.parent.handleJobFile(filename, f)
-
-
-class Try_Jobdir(TryBase):
-
- compare_attrs = TryBase.compare_attrs + ('jobdir',)
-
- def __init__(self, name, builderNames, jobdir,
- properties={}):
- TryBase.__init__(self, name=name, builderNames=builderNames,
- properties=properties)
- self.jobdir = jobdir
- self.watcher = JobdirService()
- self.watcher.setServiceParent(self)
-
- def startService(self):
- # set the watcher's basedir now that we have a master
- jobdir = os.path.join(self.master.basedir, self.jobdir)
- self.watcher.setBasedir(jobdir)
- for subdir in "cur new tmp".split():
- if not os.path.exists(os.path.join(jobdir, subdir)):
- os.mkdir(os.path.join(jobdir, subdir))
- TryBase.startService(self)
-
- def parseJob(self, f):
- # jobfiles are serialized build requests. Each is a list of
- # serialized netstrings, in the following order:
- # format version number:
- # "1" the original
- # "2" introduces project and repository
- # "3" introduces who
- # "4" introduces comment
- # "5" introduces properties and JSON serialization of values after
- # version
- # jobid: arbitrary string, used to find the buildSet later
- # branch: branch name, "" for default-branch
- # baserev: revision, "" for HEAD
- # patch_level: usually "1"
- # patch_body: patch to be applied for build
- # repository
- # project
- # who: user requesting build
- # comment: comment from user about diff and/or build
- # builderNames: list of builder names
- # properties: dict of build properties
- p = netstrings.NetstringParser()
- f.seek(0,2)
- if f.tell() > basic.NetstringReceiver.MAX_LENGTH:
- raise BadJobfile("The patch size is greater that NetStringReceiver.MAX_LENGTH. Please Set this higher in the master.cfg")
- f.seek(0,0)
- try:
- p.feed(f.read())
- except basic.NetstringParseError:
- raise BadJobfile("unable to parse netstrings")
- if not p.strings:
- raise BadJobfile("could not find any complete netstrings")
- ver = p.strings.pop(0)
-
- v1_keys = ['jobid', 'branch', 'baserev', 'patch_level', 'patch_body']
- v2_keys = v1_keys + ['repository', 'project']
- v3_keys = v2_keys + ['who']
- v4_keys = v3_keys + ['comment']
- keys = [v1_keys, v2_keys, v3_keys, v4_keys]
- # v5 introduces properties and uses JSON serialization
-
- parsed_job = {}
-
- def extract_netstrings(p, keys):
- for i, key in enumerate(keys):
- parsed_job[key] = p.strings[i]
-
- def postprocess_parsed_job():
- # apply defaults and handle type casting
- parsed_job['branch'] = parsed_job['branch'] or None
- parsed_job['baserev'] = parsed_job['baserev'] or None
- parsed_job['patch_level'] = int(parsed_job['patch_level'])
- for key in 'repository project who comment'.split():
- parsed_job[key] = parsed_job.get(key, '')
- parsed_job['properties'] = parsed_job.get('properties', {})
-
- if ver <= "4":
- i = int(ver) - 1
- extract_netstrings(p, keys[i])
- parsed_job['builderNames'] = p.strings[len(keys[i]):]
- postprocess_parsed_job()
- elif ver == "5":
- try:
- parsed_job = json.loads(p.strings[0])
- except ValueError:
- raise BadJobfile("unable to parse JSON")
- postprocess_parsed_job()
- else:
- raise BadJobfile("unknown version '%s'" % ver)
- return parsed_job
-
- def handleJobFile(self, filename, f):
- try:
- parsed_job = self.parseJob(f)
- builderNames = parsed_job['builderNames']
- except BadJobfile:
- log.msg("%s reports a bad jobfile in %s" % (self, filename))
- log.err()
- return defer.succeed(None)
-
- # Validate/fixup the builder names.
- builderNames = self.filterBuilderList(builderNames)
- if not builderNames:
- log.msg(
- "incoming Try job did not specify any allowed builder names")
- return defer.succeed(None)
-
- who = ""
- if parsed_job['who']:
- who = parsed_job['who']
-
- comment = ""
- if parsed_job['comment']:
- comment = parsed_job['comment']
-
- d = self.master.db.sourcestampsets.addSourceStampSet()
-
- def addsourcestamp(setid):
- self.master.db.sourcestamps.addSourceStamp(
- sourcestampsetid=setid,
- branch=parsed_job['branch'],
- revision=parsed_job['baserev'],
- patch_body=parsed_job['patch_body'],
- patch_level=parsed_job['patch_level'],
- patch_author=who,
- patch_comment=comment,
- patch_subdir='', # TODO: can't set this remotely - #1769
- project=parsed_job['project'],
- repository=parsed_job['repository'])
- return setid
-
- d.addCallback(addsourcestamp)
-
- def create_buildset(setid):
- reason = "'try' job"
- if parsed_job['who']:
- reason += " by user %s" % parsed_job['who']
- properties = parsed_job['properties']
- requested_props = Properties()
- requested_props.update(properties, "try build")
- return self.addBuildsetForSourceStamp(
- ssid=None, setid=setid,
- reason=reason, external_idstring=parsed_job['jobid'],
- builderNames=builderNames, properties=requested_props)
- d.addCallback(create_buildset)
- return d
-
-
-class Try_Userpass_Perspective(pbutil.NewCredPerspective):
- def __init__(self, scheduler, username):
- self.scheduler = scheduler
- self.username = username
-
- @defer.inlineCallbacks
- def perspective_try(self, branch, revision, patch, repository, project,
- builderNames, who="", comment="", properties={}):
- db = self.scheduler.master.db
- log.msg("user %s requesting build on builders %s" % (self.username,
- builderNames))
-
- # build the intersection of the request and our configured list
- builderNames = self.scheduler.filterBuilderList(builderNames)
- if not builderNames:
- return
-
- reason = "'try' job"
-
- if who:
- reason += " by user %s" % who
-
- if comment:
- reason += " (%s)" % comment
-
- sourcestampsetid = yield db.sourcestampsets.addSourceStampSet()
-
- yield db.sourcestamps.addSourceStamp(
- branch=branch, revision=revision, repository=repository,
- project=project, patch_level=patch[0], patch_body=patch[1],
- patch_subdir='', patch_author=who or '',
- patch_comment=comment or '',
- sourcestampsetid=sourcestampsetid)
- # note: no way to specify patch subdir - #1769
-
- requested_props = Properties()
- requested_props.update(properties, "try build")
- (bsid, brids) = yield self.scheduler.addBuildsetForSourceStamp(
- setid=sourcestampsetid, reason=reason,
- properties=requested_props, builderNames=builderNames)
-
- # return a remotely-usable BuildSetStatus object
- bsdict = yield db.buildsets.getBuildset(bsid)
-
- bss = BuildSetStatus(bsdict, self.scheduler.master.status)
- from buildbot.status.client import makeRemote
- defer.returnValue(makeRemote(bss))
-
- def perspective_getAvailableBuilderNames(self):
- # Return a list of builder names that are configured
- # for the try service
- # This is mostly intended for integrating try services
- # into other applications
- return self.scheduler.listBuilderNames()
-
-
-class Try_Userpass(TryBase):
- compare_attrs = ('name', 'builderNames', 'port', 'userpass', 'properties')
-
- def __init__(self, name, builderNames, port, userpass,
- properties={}):
- TryBase.__init__(self, name=name, builderNames=builderNames,
- properties=properties)
- self.port = port
- self.userpass = userpass
-
- def startService(self):
- TryBase.startService(self)
-
- # register each user/passwd with the pbmanager
- def factory(mind, username):
- return Try_Userpass_Perspective(self, username)
- self.registrations = []
- for user, passwd in self.userpass:
- self.registrations.append(
- self.master.pbmanager.register(
- self.port, user, passwd, factory))
-
- def stopService(self):
- d = defer.maybeDeferred(TryBase.stopService, self)
-
- def unreg(_):
- return defer.gatherResults(
- [reg.unregister() for reg in self.registrations])
- d.addCallback(unreg)
- return d