43
42
def getAffiliationBadges(persons):
44
43
"""Return the badges for the type of affiliation each person has.
46
The return value is a list of namedtuples:
47
BadgeDetails(url, label, role)
45
The return value is a list of namedtuples: BadgeDetails(url, alt_text)
49
47
If a person has no affiliation with this object, their entry is None.
52
BadgeDetails = namedtuple('BadgeDetails', ('url', 'label', 'role'))
50
BadgeDetails = namedtuple('BadgeDetails', ('url', 'alt_text'))
55
53
@adapter(Interface)
56
54
class PillarAffiliation(object):
57
55
"""Default affiliation adapter.
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.
57
Subclasses may need to override getPillar() in order to provide the pillar
58
entity for which affiliation is to be determined. The default is just to
59
use the context object directly.
65
62
implements(IHasAffiliation)
67
# We rank the affiliations from most important to least important.
68
# Unlisted roles are given a rank of 10.
69
affiliation_priorities = {
73
'security contact': 4,
76
64
def __init__(self, context):
77
65
self.context = context
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):
70
def _getAffiliationDetails(self, person, pillar):
96
71
""" Return the affiliation information for a person, if any.
98
Subclasses will override this method to perform specific affiliation
100
The return result is a list of AffiliationRecord.
104
def _getAffiliationTeamRoles(self, pillars):
105
""" Return teams for which a person needs to belong, if affiliated.
107
73
A person is affiliated with a pillar if they are in the list of
108
74
drivers or are the maintainer.
75
The return result is a list of tuples (pillar displayanme, role).
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
78
if person.inTeam(pillar.owner):
79
result.append((pillar.displayname, 'maintainer'))
80
for driver in pillar.drivers:
81
if person.inTeam(driver):
82
result.append((pillar.displayname, 'driver'))
120
86
def getAffiliationBadges(self, persons):
121
87
""" Return the affiliation badge details for people given a context.
123
There are 2 ways we check for affiliation:
124
1. Generic membership checks of particular teams as returned by
125
_getAffiliationTeamRoles
126
2. Specific affiliation checks as performed by _getAffiliation
128
pillars = self.getPillars()
89
pillar = self.getPillar()
131
# We find the teams to check for participation..
132
affiliation_team_details = self._getAffiliationTeamRoles(pillars)
133
teams_to_check = set()
134
for teams in affiliation_team_details.values():
135
teams_to_check.update(teams)
136
# We gather the participation for the persons.
137
people_teams = find_team_participations(persons, teams_to_check)
139
91
for person in persons:
140
# Specific affiliations
141
badges = self._getAffiliation(person, pillars)
142
# Generic, team based affiliations
143
affiliated_teams = people_teams.get(person, [])
144
for affiliated_team in affiliated_teams:
145
for badge, teams in affiliation_team_details.items():
146
if affiliated_team in teams:
92
affiliation_details = self._getAffiliationDetails(person, pillar)
93
if not affiliation_details:
153
# Sort the affiliation list according the the importance of each
157
self.affiliation_priorities.get(badge.role, 10))
97
def getIconUrl(context, pillar, default_url):
98
if IHasIcon.providedBy(context) and context.icon is not None:
99
icon_url = context.icon.getURL()
101
if IHasIcon.providedBy(pillar) and pillar.icon is not None:
102
icon_url = pillar.icon.getURL()
106
if IDistribution.providedBy(pillar):
107
default_icon_url = "/@@/distribution-badge"
109
default_icon_url = "/@@/product-badge"
110
icon_url = getIconUrl(self.context, pillar, default_icon_url)
112
for affiliation in affiliation_details:
113
alt_text = "%s %s" % affiliation
114
badges.append(BadgeDetails(icon_url, alt_text))
158
115
result.append(badges)
162
119
class BugTaskPillarAffiliation(PillarAffiliation):
163
120
"""An affiliation adapter for bug tasks."""
164
def getPillars(self):
166
bug = self.context.bug
167
for bugtask in bug.bugtasks:
168
result.append(bugtask.pillar)
122
return self.context.pillar
171
def _getAffiliationTeamRoles(self, pillars):
124
def _getAffiliationDetails(self, person, pillar):
172
125
""" A person is affiliated with a bugtask based on (in order):
173
126
- owner of bugtask pillar
174
127
- driver of bugtask pillar
175
128
- bug supervisor of bugtask pillar
176
129
- security contact of bugtask pillar
178
super_instance = super(BugTaskPillarAffiliation, self)
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]
131
result = super(BugTaskPillarAffiliation, self)._getAffiliationDetails(
133
if person.inTeam(pillar.bug_supervisor):
134
result.append((pillar.displayname, 'bug supervisor'))
135
if person.inTeam(pillar.security_contact):
136
result.append((pillar.displayname, 'security contact'))
192
140
class BranchPillarAffiliation(BugTaskPillarAffiliation):
193
141
"""An affiliation adapter for branches."""
195
def getPillars(self):
196
pillar = self.context.product or self.context.distribution
198
# This is a +junk branch.
144
return self.context.product or self.context.distribution
202
146
def getBranch(self):
203
147
return self.context
205
def _getAffiliation(self, person, pillars):
149
def _getAffiliationDetails(self, person, pillar):
206
150
super_instance = super(BranchPillarAffiliation, self)
207
result = super_instance._getAffiliation(person, pillars)
208
for pillar in pillars:
209
if self.getBranch().isPersonTrustedReviewer(person):
210
result.append(BadgeDetails(
211
self.getIconUrl(pillar),
212
pillar.displayname, 'trusted reviewer'))
151
result = super_instance._getAffiliationDetails(person, pillar)
152
if self.getBranch().isPersonTrustedReviewer(person):
153
result.append((pillar.displayname, 'trusted reviewer'))
216
157
class CodeReviewVotePillarAffiliation(BranchPillarAffiliation):
217
158
"""An affiliation adapter for CodeReviewVotes."""
219
def getPillars(self):
220
161
"""Return the target branch'pillar."""
221
162
branch = self.getBranch()
222
return [branch.product or branch.distribution]
163
return branch.product or branch.distribution
224
165
def getBranch(self):
225
166
return self.context.branch_merge_proposal.target_branch
228
169
class DistroSeriesPillarAffiliation(PillarAffiliation):
229
170
"""An affiliation adapter for distroseries."""
230
def getPillars(self):
231
return [self.context.distribution]
172
return self.context.distribution
234
175
class ProductSeriesPillarAffiliation(PillarAffiliation):
235
176
"""An affiliation adapter for productseries."""
236
def getPillars(self):
237
return [self.context.product]
178
return self.context.product
240
181
class SpecificationPillarAffiliation(PillarAffiliation):
241
182
"""An affiliation adapter for blueprints."""
242
def getPillars(self):
243
return [self.context.target]
184
return (self.context.target)
246
187
class QuestionPillarAffiliation(PillarAffiliation):
247
"""An affiliation adapter for questions.
249
A person is affiliated with a question based on (in order):
250
- answer contact for question target
251
- owner of question target
252
- driver of question target
255
def getPillars(self):
256
return [self.context.product or self.context.distribution]
258
def _getAffiliation(self, person, pillars):
259
super_instance = super(QuestionPillarAffiliation, self)
260
result = super_instance._getAffiliation(person, pillars)
188
"""An affiliation adapter for questions."""
190
return self.context.product or self.context.distribution
192
def _getAffiliationDetails(self, person, pillar):
193
""" A person is affiliated with a question based on (in order):
194
- answer contact for question target
195
- owner of question target
196
- driver of question target
198
result = (super(QuestionPillarAffiliation, self)
199
._getAffiliationDetails(person, pillar))
261
200
target = self.context.target
262
201
if IDistributionSourcePackage.providedBy(target):
263
202
question_targets = (target, target.distribution)