~launchpad-pqm/launchpad/devel

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
TranslationsOverview
====================

This class provides a basic overview of the Launchpad Translations component.
It includes data such as projects which have so far received the most
translations and provides an easy way to figure out which projects a certain
person has most translated for.

In order to make live updates to the KarmaCache table, we sometimes log
in here as testadmin.  In real life the updates would be performed by
cronscripts/foaf-update-karma-cache.py, but that would slow down this
test too much.

    >>> import transaction
    >>> from zope.component import getUtility
    >>> from lp.registry.interfaces.distribution import IDistributionSet
    >>> from lp.registry.interfaces.karma import IKarmaCacheManager
    >>> from lp.registry.interfaces.person import IPersonSet
    >>> from lp.registry.interfaces.product import IProductSet
    >>> from lp.registry.model.karma import KarmaCategory
    >>> from lp.registry.model.sourcepackagename import SourcePackageName
    >>> from lp.translations.interfaces.translationsoverview import (
    ...     ITranslationsOverview)
    >>> from canonical.testing.layers import LaunchpadZopelessLayer
    >>> karmacachemanager = getUtility(IKarmaCacheManager)
    >>> person_set = getUtility(IPersonSet)
    >>> product_set = getUtility(IProductSet)

    >>> overview = getUtility(ITranslationsOverview)

    >>> def start_karma_update():
    ...     """Prepare for update to karma cache."""
    ...     transaction.commit()
    ...     LaunchpadZopelessLayer.switchDbUser('testadmin')

    >>> def finish_karma_update():
    ...     """Return to normal after updating karma cache."""
    ...     transaction.commit()
    ...     LaunchpadZopelessLayer.switchDbUser('launchpad')

ITranslationOverview defines two constants regulating minimum and maximum
contribution weights.

    >>> overview.MINIMUM_SIZE
    10
    >>> overview.MAXIMUM_SIZE
    18


_normalizeSizes
---------------

This private method accepts a list of tuples (object, size) and
normalizes `size` values into the range [MINIMUM_SIZE, MAXIMUM_SIZE].

    >>> test_list = [('one', 3), ('two', 0), ('three', 1)]
    >>> from zope.security.proxy import removeSecurityProxy
    >>> naked_overview = removeSecurityProxy(overview)
    >>> result = naked_overview._normalizeSizes(test_list, 0, 3)
    >>> for pillar in result:
    ...     print "%s: %d" % (pillar['pillar'], pillar['weight'])
    one: 18
    two: 10
    three: 13


Getting the most translated pillars
-----------------------------------

Set Up
......

The following demo assumes the test data has official_translations set.
Let's set that up.

    >>> from lp.app.enums import ServiceUsage
    >>> evolution = getUtility(IProductSet).getByName('evolution')
    >>> evolution.translations_usage = ServiceUsage.LAUNCHPAD
    >>> alsa = getUtility(IProductSet).getByName('alsa-utils')
    >>> alsa.translations_usage = ServiceUsage.LAUNCHPAD
    >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
    >>> ubuntu.translations_usage = ServiceUsage.LAUNCHPAD
    >>> transaction.commit()

Using getMostTranslatedPillars
..............................

Method getMostTranslatedPillars() returns a list of dicts listing
pillars with most translations karma so far, along with a relative
weight for each of the pillars in the range of [overview.MINIMUM_SIZE,
overview.MAXIMUM_SIZE].

    >>> def display_pillars(pillars):
    ...     for pillar in pillars:
    ...         print "%s: %d" % (
    ...             pillar['pillar'].displayname, pillar['weight'])
    >>> display_pillars(overview.getMostTranslatedPillars())
    Evolution: 14

Adding some translations karma attributed to Carlos will make
alsa-utils displayed among the top translated pillars as well.

    >>> carlos = person_set.getByName('carlos')
    >>> translations = KarmaCategory.byName('translations')
    >>> alsa_utils = product_set.getByName('alsa-utils')

    >>> start_karma_update()
    >>> cache_entry = karmacachemanager.new(
    ...     120, carlos.id, translations.id, product_id=alsa_utils.id)
    >>> finish_karma_update()

    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: 10
    Evolution: 18

When karma is increased for alsa-utils, it will get more weight than
Evolution.

    >>> start_karma_update()
    >>> cache_entry = karmacachemanager.updateKarmaValue(
    ...     1020, carlos.id, translations.id, product_id=alsa_utils.id)
    >>> finish_karma_update()

    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: 18
    Evolution: 10

Adding a little bit of karma to upstart will put it in the list as well.

    >>> from lp.app.enums import ServiceUsage

    >>> start_karma_update()
    >>> upstart = product_set.getByName('upstart')
    >>> upstart_id = upstart.id
    >>> naked_upstart = removeSecurityProxy(upstart)
    >>> naked_upstart.translations_usage = ServiceUsage.LAUNCHPAD
    >>> cache_entry = karmacachemanager.new(
    ...     50, carlos.id, translations.id, product_id=upstart_id)
    >>> finish_karma_update()

    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: 18
    Evolution: 13
    Upstart: 10

Distributions with a lot of translation contributions show in the same
list as well.

    >>> start_karma_update()
    >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu")
    >>> evolution_sourcepackagename = SourcePackageName.byName("evolution")
    >>> cache_entry = karmacachemanager.new(
    ...     5150, carlos.id, translations.id, distribution_id=ubuntu.id,
    ...     sourcepackagename_id=evolution_sourcepackagename.id)
    >>> finish_karma_update()
    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: 15
    Evolution: 12
    Ubuntu: 18
    Upstart: 10

Changing the range of the contribution weights relative project weights will
automatically adjust as well.

    >>> removeSecurityProxy(overview).MINIMUM_SIZE = 20
    >>> removeSecurityProxy(overview).MAXIMUM_SIZE = 24
    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: 23
    Evolution: 21
    Ubuntu: 24
    Upstart: 20

If we pass the `limit` parameter to getMostTranslatedPillars method,
we change the default maximum number of returned entries.

    >>> display_pillars(overview.getMostTranslatedPillars(3))
    alsa-utils: 22
    Evolution: 20
    Ubuntu: 24


Zero karma
----------

Sometimes a pillar appears to be listed in the karma cache with zero
karma.  Our algorithm takes the logarithm of its karma, but it's
properly armoured against the occurrence of karmaless projects.

    >>> start_karma_update()
    >>> from canonical.database.sqlbase import cursor
    >>> cur = cursor()
    >>> cur.execute("""
    ...     UPDATE KarmaCache
    ...     SET karmavalue = 0
    ...     WHERE product = %d
    ...     """ % upstart_id)
    >>> cur.rowcount
    1
    >>> finish_karma_update()

    >>> display_pillars(overview.getMostTranslatedPillars())
    alsa-utils: ...
    Evolution: ...
    Ubuntu: ...