43
43
def getAffiliationBadges(persons):
44
44
"""Return the badges for the type of affiliation each person has.
46
The return value is a list of namedtuples: BadgeDetails(url, alt_text)
46
The return value is a list of namedtuples:
47
BadgeDetails(url, label, role)
48
49
If a person has no affiliation with this object, their entry is None.
51
BadgeDetails = namedtuple('BadgeDetails', ('url', 'alt_text'))
52
BadgeDetails = namedtuple('BadgeDetails', ('url', 'label', 'role'))
54
55
@adapter(Interface)
55
56
class PillarAffiliation(object):
56
57
"""Default affiliation adapter.
58
Subclasses may need to override getPillar() in order to provide the pillar
59
entity for which affiliation is to be determined. The default is just to
60
use the context object directly.
59
Subclasses may need to override getPillars() in order to provide the
60
pillar entities for which affiliation is to be determined. A given context
61
may supply for than one pillar for which affiliation can be determined.
62
The default is just to use the context object directly.
63
65
implements(IHasAffiliation)
74
76
def __init__(self, context):
75
77
self.context = context
80
def _getAffiliation(self, person, pillar):
82
def getIconUrl(self, pillar):
83
if (IHasIcon.providedBy(self.context)
84
and self.context.icon is not None):
85
icon_url = self.context.icon.getURL()
87
if IHasIcon.providedBy(pillar) and pillar.icon is not None:
88
icon_url = pillar.icon.getURL()
90
if IDistribution.providedBy(pillar):
91
return "/@@/distribution-badge"
93
return "/@@/product-badge"
95
def _getAffiliation(self, person, pillars):
81
96
""" Return the affiliation information for a person, if any.
83
98
Subclasses will override this method to perform specific affiliation
85
The return result is a list of tuples (pillar displayanme, role).
100
The return result is a list of AffiliationRecord.
89
def _getAffiliationTeamRoles(self, pillar):
104
def _getAffiliationTeamRoles(self, pillars):
90
105
""" Return teams for which a person needs to belong, if affiliated.
92
107
A person is affiliated with a pillar if they are in the list of
93
108
drivers or are the maintainer.
96
(pillar.displayname, 'maintainer'): [pillar.owner],
97
(pillar.displayname, 'driver'): pillar.drivers}
111
for pillar in pillars:
113
self.getIconUrl(pillar),
114
pillar.displayname, 'maintainer')] = [pillar.owner]
116
self.getIconUrl(pillar),
117
pillar.displayname, 'driver')] = pillar.drivers
100
120
def getAffiliationBadges(self, persons):
105
125
_getAffiliationTeamRoles
106
126
2. Specific affiliation checks as performed by _getAffiliation
108
pillar = self.getPillar()
128
pillars = self.getPillars()
111
131
# We find the teams to check for participation..
112
affiliation_team_details = self._getAffiliationTeamRoles(pillar)
132
affiliation_team_details = self._getAffiliationTeamRoles(pillars)
113
133
teams_to_check = set()
114
134
for teams in affiliation_team_details.values():
115
135
teams_to_check.update(teams)
119
139
for person in persons:
120
140
# Specific affiliations
121
affiliations = self._getAffiliation(person, pillar)
141
badges = self._getAffiliation(person, pillars)
122
142
# Generic, team based affiliations
123
143
affiliated_teams = people_teams.get(person, [])
124
144
for affiliated_team in affiliated_teams:
125
for affiliation, teams in affiliation_team_details.items():
145
for badge, teams in affiliation_team_details.items():
126
146
if affiliated_team in teams:
127
affiliations.append(affiliation)
130
150
result.append([])
133
def getIconUrl(context, pillar, default_url):
134
if IHasIcon.providedBy(context) and context.icon is not None:
135
icon_url = context.icon.getURL()
137
if IHasIcon.providedBy(pillar) and pillar.icon is not None:
138
icon_url = pillar.icon.getURL()
142
if IDistribution.providedBy(pillar):
143
default_icon_url = "/@@/distribution-badge"
145
default_icon_url = "/@@/product-badge"
146
icon_url = getIconUrl(self.context, pillar, default_icon_url)
148
153
# Sort the affiliation list according the the importance of each
149
154
# affiliation role.
151
key=lambda affiliation_rec:
152
self.affiliation_priorities.get(affiliation_rec[1], 10))
154
for affiliation in affiliations:
155
alt_text = "%s %s" % affiliation
156
badges.append(BadgeDetails(icon_url, alt_text))
157
self.affiliation_priorities.get(badge.role, 10))
157
158
result.append(badges)
161
162
class BugTaskPillarAffiliation(PillarAffiliation):
162
163
"""An affiliation adapter for bug tasks."""
164
return self.context.pillar
164
def getPillars(self):
166
bug = self.context.bug
167
for bugtask in bug.bugtasks:
168
result.append(bugtask.pillar)
166
def _getAffiliationTeamRoles(self, pillar):
171
def _getAffiliationTeamRoles(self, pillars):
167
172
""" A person is affiliated with a bugtask based on (in order):
168
173
- owner of bugtask pillar
169
174
- driver of bugtask pillar
171
176
- security contact of bugtask pillar
173
178
super_instance = super(BugTaskPillarAffiliation, self)
174
result = super_instance._getAffiliationTeamRoles(pillar)
175
result[(pillar.displayname, 'bug supervisor')] = (
176
[pillar.bug_supervisor])
177
result[(pillar.displayname, 'security contact')] = (
178
[pillar.security_contact])
179
result = super_instance._getAffiliationTeamRoles(pillars)
180
for pillar in pillars:
182
self.getIconUrl(pillar),
184
'bug supervisor')] = [pillar.bug_supervisor]
186
self.getIconUrl(pillar),
188
'security contact')] = [pillar.security_contact]
182
192
class BranchPillarAffiliation(BugTaskPillarAffiliation):
183
193
"""An affiliation adapter for branches."""
186
return self.context.product or self.context.distribution
195
def getPillars(self):
196
return [self.context.product or self.context.distribution]
188
198
def getBranch(self):
189
199
return self.context
191
def _getAffiliation(self, person, pillar):
201
def _getAffiliation(self, person, pillars):
192
202
super_instance = super(BranchPillarAffiliation, self)
193
result = super_instance._getAffiliation(person, pillar)
194
if self.getBranch().isPersonTrustedReviewer(person):
195
result.append((pillar.displayname, 'trusted reviewer'))
203
result = super_instance._getAffiliation(person, pillars)
204
for pillar in pillars:
205
if self.getBranch().isPersonTrustedReviewer(person):
206
result.append(BadgeDetails(
207
self.getIconUrl(pillar),
208
pillar.displayname, 'trusted reviewer'))
199
212
class CodeReviewVotePillarAffiliation(BranchPillarAffiliation):
200
213
"""An affiliation adapter for CodeReviewVotes."""
215
def getPillars(self):
203
216
"""Return the target branch'pillar."""
204
217
branch = self.getBranch()
205
return branch.product or branch.distribution
218
return [branch.product or branch.distribution]
207
220
def getBranch(self):
208
221
return self.context.branch_merge_proposal.target_branch
211
224
class DistroSeriesPillarAffiliation(PillarAffiliation):
212
225
"""An affiliation adapter for distroseries."""
214
return self.context.distribution
226
def getPillars(self):
227
return [self.context.distribution]
217
230
class ProductSeriesPillarAffiliation(PillarAffiliation):
218
231
"""An affiliation adapter for productseries."""
220
return self.context.product
232
def getPillars(self):
233
return [self.context.product]
223
236
class SpecificationPillarAffiliation(PillarAffiliation):
224
237
"""An affiliation adapter for blueprints."""
226
return (self.context.target)
238
def getPillars(self):
239
return [self.context.target]
229
242
class QuestionPillarAffiliation(PillarAffiliation):
235
248
- driver of question target
239
return self.context.product or self.context.distribution
251
def getPillars(self):
252
return [self.context.product or self.context.distribution]
241
def _getAffiliation(self, person, pillar):
242
result = (super(QuestionPillarAffiliation, self)
243
._getAffiliation(person, pillar))
254
def _getAffiliation(self, person, pillars):
255
super_instance = super(QuestionPillarAffiliation, self)
256
result = super_instance._getAffiliation(person, pillars)
244
257
target = self.context.target
245
258
if IDistributionSourcePackage.providedBy(target):
246
259
question_targets = (target, target.distribution)
249
262
questions_person = IQuestionsPerson(person)
250
263
for target in questions_person.getDirectAnswerQuestionTargets():
251
264
if target in question_targets:
252
result.append((target.displayname, 'answer contact'))
267
self.getIconUrl(pillars[0]),
268
target.displayname, 'answer contact'))
253
269
for target in questions_person.getTeamAnswerQuestionTargets():
254
270
if target in question_targets:
255
result.append((target.displayname, 'answer contact'))
273
self.getIconUrl(pillars[0]),
274
target.displayname, 'answer contact'))