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
129
130
131
132
133
134
135
136
|
# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
__all__ = [
'KarmaActionEditView',
'KarmaActionSetNavigation',
'KarmaContextTopContributorsView',
]
from operator import attrgetter
from zope.component import getUtility
from lp import _
from lp.app.browser.launchpadform import (
action,
LaunchpadEditFormView,
)
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.karma import (
IKarmaAction,
IKarmaActionSet,
)
from lp.registry.interfaces.product import IProduct
from lp.registry.interfaces.projectgroup import IProjectGroup
from lp.services.propertycache import cachedproperty
from lp.services.webapp import (
canonical_url,
Navigation,
)
from lp.services.webapp.publisher import LaunchpadView
TOP_CONTRIBUTORS_LIMIT = 20
class KarmaActionSetNavigation(Navigation):
usedfor = IKarmaActionSet
def traverse(self, name):
return self.context.getByName(name)
class KarmaActionView(LaunchpadView):
"""View class for the index of karma actions."""
page_title = 'Actions that give people karma'
class KarmaActionEditView(LaunchpadEditFormView):
schema = IKarmaAction
field_names = ["name", "category", "points", "title", "summary"]
@property
def label(self):
"""See `LaunchpadFormView`."""
return 'Edit %s karma action' % self.context.title
@property
def page_title(self):
"""The page title."""
return self.label
@property
def cancel_url(self):
"""See `LaunchpadFormView`."""
return canonical_url(getUtility(IKarmaActionSet))
@action(_("Change"), name="change")
def change_action(self, action, data):
self.updateContextFromData(data)
self.next_url = self.cancel_url
class KarmaContextContributor:
def __init__(self, person, karmavalue):
self.person = person
self.karmavalue = karmavalue
class KarmaContextTopContributorsView(LaunchpadView):
"""List this KarmaContext's top contributors."""
@property
def page_title(self):
return "Top %s Contributors" % self.context.title
def initialize(self):
context = self.context
if IProduct.providedBy(context):
self.context_name = 'Project'
elif IDistribution.providedBy(context):
self.context_name = 'Distribution'
elif IProjectGroup.providedBy(context):
self.context_name = 'Project Group'
else:
raise AssertionError(
"Context is not a Product, Project group or Distribution: %r"
% context)
def _getTopContributorsWithLimit(self, limit=None):
results = self.context.getTopContributors(limit=limit)
contributors = [KarmaContextContributor(person, karmavalue)
for person, karmavalue in results]
return sorted(
contributors, key=attrgetter('karmavalue'), reverse=True)
def getTopContributors(self):
return self._getTopContributorsWithLimit(limit=TOP_CONTRIBUTORS_LIMIT)
def getTopFiveContributors(self):
return self._getTopContributorsWithLimit(limit=5)
@cachedproperty
def top_contributors_by_category(self):
contributors_by_category = {}
limit = TOP_CONTRIBUTORS_LIMIT
results = self.context.getTopContributorsGroupedByCategory(
limit=limit)
for category, people_and_karma in results.items():
contributors = []
for person, karmavalue in people_and_karma:
contributors.append(KarmaContextContributor(
person, karmavalue))
contributors.sort(key=attrgetter('karmavalue'), reverse=True)
contributors_by_category[category.title] = contributors
return contributors_by_category
@property
def sorted_categories(self):
return sorted(self.top_contributors_by_category.keys())
|