-
Notifications
You must be signed in to change notification settings - Fork 1
/
project.py
128 lines (109 loc) · 4.62 KB
/
project.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from buildbot import scheduler
from buildbot.schedulers.filter import ChangeFilter as BaseChangeFilter
from buildbot.config import BuilderConfig
from memoize import memoize, const_property
import util
class AnyBranchScheduler(scheduler.AnyBranchScheduler):
def __repr__(self):
import pprint
return 'AnyBranchScheduler %r=' % self.name + pprint.pformat(self.__dict__)
class multimap(dict):
"""
A lazy dict of lists (sort of like a C++ std::multimap).
Accessing a key not already in the dict creates a corresponding
element whose value is the empty list.
"""
def __getitem__(self, key):
return self.setdefault(key, [])
def slave_property_match(slave, include, exclude):
"""Returns true iff the slave has all properties in include and none in exclude"""
return (all(slave.features.get(x) for x in include) and
not any(slave.features.get(x) for x in exclude))
class Project(object):
__all_slaves = None
treeStableTime = 30
"""
A software project
"""
def __init__(
self,
name, # the project's name, a string
repositories, # a sequence of repository.Repository's
build_procedures, # a sequence of procedure.BuildProcedure's
include_features=[], # a sequence of features that all testing slaves must posses
exclude_features=[], # a sequence of features that testing slaves must not posses
make_change_filter=None, # a function called on this project to produce a suitable ChangeFilter
status=[] # a sequence of status reporters for this project
):
self.name = name
self.repositories = repositories
self.build_procedures = build_procedures
self.include_features = include_features
self.exclude_features = exclude_features
self.status = status
if make_change_filter:
self.change_filter = make_change_filter(self)
else:
self.change_filter = self.ChangeFilter()
def __str__(self):
return 'Project %s (slaves=%s)' % (self.name,self.slaves)
def __uses_slave(self, slave):
"""Predicate returning True iff the given slave is eligible for use by this Project"""
return slave_property_match(slave, self.include_features, self.exclude_features)
def select_slaves(self, slaves):
"""Given a list of all eligible slaves, select the ones on which this project will build"""
self.__all_slaves = slaves
def __match_any_repository(self, url):
return any(r.match_url(url) for r in self.repositories)
def ChangeFilter(self, *args, **kw):
"""The default change filter builds all changes in the given repositories"""
return BaseChangeFilter(
repository_fn=self.__match_any_repository,
*args, **kw)
@const_property
def slaves(self):
"""A list of the slaves used by this project"""
return [s for s in self.__all_slaves if self.__uses_slave(s)]
@const_property
def platforms(self):
"""A dict mapping platforms to lists of slaves"""
r = multimap()
for s in self.slaves:
for p in s.platforms(self.include_features):
r[p].append(s)
return r
@memoize
def builder(self, platform, procedure):
"""Returns a builder for this project on the named platform using a given BuildProcedure"""
id = self.name+'-'+str(platform)+'-'+procedure.name
return BuilderConfig(
name=id,
slavenames=[s.slavename for s in self.platforms[platform]],
properties=dict(platform),
category=self.name,
builddir=id,
factory=procedure)
@const_property
def builders(self):
"""A list of this project's builders"""
return [
self.builder(platform,procedure)
for platform in self.platforms
for procedure in self.build_procedures]
@const_property
def schedulers(self):
"""A list of this project's schedulers"""
# We need a scheduler for each build procedure
return [
AnyBranchScheduler(
name=self.name+'-'+procedure.name+'-scheduler',
change_filter=self.change_filter,
treeStableTimer=self.treeStableTime,
builderNames=[
self.builder(platform,procedure).name
for platform in self.platforms
])
for procedure in self.build_procedures
]
def from_module(m):
return util.init_from_module(Project, m)