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

Source Code for Module buildbot.schedulers.base

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16  from zope.interface import implements 
 17  from twisted.application import service 
 18   
 19  from buildbot import interfaces 
 20  from buildbot.process.properties import Properties 
 21  from buildbot.util import ComparableMixin, NotABranch 
 22  from buildbot.schedulers import filter 
 23   
24 -class _None:
25 pass
26
27 -class BaseScheduler(service.MultiService, ComparableMixin):
28 implements(interfaces.IScheduler) 29 # subclasses must set .compare_attrs 30 31 upstream_name = None # set to be notified about upstream buildsets 32
33 - def __init__(self, name, builderNames, properties):
34 service.MultiService.__init__(self) 35 self.name = name 36 self.properties = Properties() 37 self.properties.update(properties, "Scheduler") 38 self.properties.setProperty("scheduler", name, "Scheduler") 39 errmsg = ("The builderNames= argument to Scheduler must be a list " 40 "of Builder description names (i.e. the 'name' key of the " 41 "Builder specification dictionary)") 42 assert isinstance(builderNames, (list, tuple)), errmsg 43 for b in builderNames: 44 assert isinstance(b, str), errmsg 45 self.builderNames = builderNames
46 # I will acquire a .schedulerid value before I'm started 47
48 - def compareToOther(self, them):
49 # like ComparableMixin.__cmp__, but only used by our manager 50 # TODO: why?? why not use __cmp__? 51 result = cmp(type(self), type(them)) 52 if result: 53 return result 54 result = cmp(self.__class__, them.__class__) 55 if result: 56 return result 57 assert self.compare_attrs == them.compare_attrs 58 self_list = [getattr(self, name, _None) for name in self.compare_attrs] 59 them_list = [getattr(them, name, _None) for name in self.compare_attrs] 60 return cmp(self_list, them_list)
61
62 - def get_initial_state(self, max_changeid):
63 # override this if you pay attention to Changes, probably to: 64 #return {"last_processed": max_changeid} 65 return {}
66
67 - def get_state(self, t):
68 return self.parent.db.scheduler_get_state(self.schedulerid, t)
69
70 - def set_state(self, t, state):
71 self.parent.db.scheduler_set_state(self.schedulerid, t, state)
72
73 - def listBuilderNames(self):
74 return self.builderNames
75
76 - def getPendingBuildTimes(self):
77 return []
78
79 - def create_buildset(self, ssid, reason, t, props=None, builderNames=None):
80 db = self.parent.db 81 if props is None: 82 props = self.properties 83 if builderNames is None: 84 builderNames = self.builderNames 85 bsid = db.create_buildset(ssid, reason, props, builderNames, t) 86 # notify downstream schedulers so they can watch for it to complete 87 self.parent.publish_buildset(self.name, bsid, t) 88 return bsid
89
90 -class ClassifierMixin:
91 """ 92 Mixin to classify changes using self.change_filter, a filter.ChangeFilter instance. 93 """ 94
95 - def make_filter(self, change_filter=None, branch=NotABranch, categories=None):
96 if change_filter: 97 if (branch is not NotABranch or categories is not None): 98 raise RuntimeError("cannot specify both change_filter and either branch or categories") 99 self.change_filter = change_filter 100 return 101 102 # build a change filter from the deprecated category and branch args 103 cfargs = {} 104 if branch is not NotABranch: cfargs['branch'] = branch 105 if categories: cfargs['category'] = categories 106 self.change_filter = filter.ChangeFilter(**cfargs)
107
108 - def classify_changes(self, t):
109 db = self.parent.db 110 cm = self.parent.change_svc 111 state = self.get_state(t) 112 state_changed = False 113 last_processed = state.get("last_processed", None) 114 115 if last_processed is None: 116 last_processed = state['last_processed'] = cm.getLatestChangeNumberNow(t) 117 state_changed = True 118 119 changes = cm.getChangesGreaterThan(last_processed, t) 120 for c in changes: 121 if self.change_filter.filter_change(c): 122 important = True 123 if self.fileIsImportant: 124 important = self.fileIsImportant(c) 125 db.scheduler_classify_change(self.schedulerid, c.number, 126 bool(important), t) 127 # now that we've recorded a decision about each, we can update the 128 # last_processed record 129 if changes: 130 max_changeid = max([c.number for c in changes]) 131 state["last_processed"] = max_changeid # retain other keys 132 state_changed = True 133 134 if state_changed: 135 self.set_state(t, state)
136