Package buildbot :: Package schedulers :: Module base
[frames] | no frames]

Source Code for Module buildbot.schedulers.base

  1  # ***** BEGIN LICENSE BLOCK ***** 
  2  # Version: MPL 1.1/GPL 2.0/LGPL 2.1 
  3  # 
  4  # The contents of this file are subject to the Mozilla Public License Version 
  5  # 1.1 (the "License"); you may not use this file except in compliance with 
  6  # the License. You may obtain a copy of the License at 
  7  # http://www.mozilla.org/MPL/ 
  8  # 
  9  # Software distributed under the License is distributed on an "AS IS" basis, 
 10  # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 11  # for the specific language governing rights and limitations under the 
 12  # License. 
 13  # 
 14  # The Original Code is Mozilla-specific Buildbot steps. 
 15  # 
 16  # The Initial Developer of the Original Code is 
 17  # Mozilla Foundation. 
 18  # Portions created by the Initial Developer are Copyright (C) 2009 
 19  # the Initial Developer. All Rights Reserved. 
 20  # 
 21  # Contributor(s): 
 22  #   Brian Warner <warner@lothar.com> 
 23  # 
 24  # Alternatively, the contents of this file may be used under the terms of 
 25  # either the GNU General Public License Version 2 or later (the "GPL"), or 
 26  # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 
 27  # in which case the provisions of the GPL or the LGPL are applicable instead 
 28  # of those above. If you wish to allow use of your version of this file only 
 29  # under the terms of either the GPL or the LGPL, and not to allow others to 
 30  # use your version of this file under the terms of the MPL, indicate your 
 31  # decision by deleting the provisions above and replace them with the notice 
 32  # and other provisions required by the GPL or the LGPL. If you do not delete 
 33  # the provisions above, a recipient may use your version of this file under 
 34  # the terms of any one of the MPL, the GPL or the LGPL. 
 35  # 
 36  # ***** END LICENSE BLOCK ***** 
 37   
 38  from zope.interface import implements 
 39  from twisted.application import service 
 40   
 41  from buildbot import interfaces 
 42  from buildbot.process.properties import Properties 
 43  from buildbot.util import ComparableMixin, NotABranch 
 44  from buildbot.schedulers import filter 
 45   
46 -class _None:
47 pass
48
49 -class BaseScheduler(service.MultiService, ComparableMixin):
50 implements(interfaces.IScheduler) 51 # subclasses must set .compare_attrs 52 53 upstream_name = None # set to be notified about upstream buildsets 54
55 - def __init__(self, name, builderNames, properties):
56 service.MultiService.__init__(self) 57 self.name = name 58 self.properties = Properties() 59 self.properties.update(properties, "Scheduler") 60 self.properties.setProperty("scheduler", name, "Scheduler") 61 errmsg = ("The builderNames= argument to Scheduler must be a list " 62 "of Builder description names (i.e. the 'name' key of the " 63 "Builder specification dictionary)") 64 assert isinstance(builderNames, (list, tuple)), errmsg 65 for b in builderNames: 66 assert isinstance(b, str), errmsg 67 self.builderNames = builderNames
68 # I will acquire a .schedulerid value before I'm started 69
70 - def compareToOther(self, them):
71 # like ComparableMixin.__cmp__, but only used by our manager 72 # TODO: why?? why not use __cmp__? 73 result = cmp(type(self), type(them)) 74 if result: 75 return result 76 result = cmp(self.__class__, them.__class__) 77 if result: 78 return result 79 assert self.compare_attrs == them.compare_attrs 80 self_list = [getattr(self, name, _None) for name in self.compare_attrs] 81 them_list = [getattr(them, name, _None) for name in self.compare_attrs] 82 return cmp(self_list, them_list)
83
84 - def get_initial_state(self, max_changeid):
85 # override this if you pay attention to Changes, probably to: 86 #return {"last_processed": max_changeid} 87 return {}
88
89 - def get_state(self, t):
90 return self.parent.db.scheduler_get_state(self.schedulerid, t)
91
92 - def set_state(self, t, state):
93 self.parent.db.scheduler_set_state(self.schedulerid, t, state)
94
95 - def listBuilderNames(self):
96 return self.builderNames
97
98 - def getPendingBuildTimes(self):
99 return []
100
101 - def create_buildset(self, ssid, reason, t, props=None, builderNames=None):
102 db = self.parent.db 103 if props is None: 104 props = self.properties 105 if builderNames is None: 106 builderNames = self.builderNames 107 bsid = db.create_buildset(ssid, reason, props, builderNames, t) 108 # notify downstream schedulers so they can watch for it to complete 109 self.parent.publish_buildset(self.name, bsid, t) 110 return bsid
111
112 -class ClassifierMixin:
113 """ 114 Mixin to classify changes using self.change_filter, a filter.ChangeFilter instance. 115 """ 116
117 - def make_filter(self, change_filter=None, branch=NotABranch, categories=None):
118 if change_filter: 119 if (branch is not NotABranch or categories is not None): 120 raise RuntimeError("cannot specify both change_filter and either branch or categories") 121 self.change_filter = change_filter 122 return 123 124 # build a change filter from the deprecated category and branch args 125 cfargs = {} 126 if branch is not NotABranch: cfargs['branch'] = branch 127 if categories: cfargs['category'] = categories 128 self.change_filter = filter.ChangeFilter(**cfargs)
129
130 - def classify_changes(self, t):
131 db = self.parent.db 132 cm = self.parent.change_svc 133 state = self.get_state(t) 134 state_changed = False 135 last_processed = state.get("last_processed", None) 136 137 if last_processed is None: 138 last_processed = state['last_processed'] = cm.getLatestChangeNumberNow(t) 139 state_changed = True 140 141 changes = cm.getChangesGreaterThan(last_processed, t) 142 for c in changes: 143 if self.change_filter.filter_change(c): 144 important = True 145 if self.fileIsImportant: 146 important = self.fileIsImportant(c) 147 db.scheduler_classify_change(self.schedulerid, c.number, 148 bool(important), t) 149 # now that we've recorded a decision about each, we can update the 150 # last_processed record 151 if changes: 152 max_changeid = max([c.number for c in changes]) 153 state["last_processed"] = max_changeid # retain other keys 154 state_changed = True 155 156 if state_changed: 157 self.set_state(t, state)
158