2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
1 |
Polls |
2 |
===== |
|
3 |
||
4 |
In Launchpad, we have teams as a way to group free software |
|
5 |
developers/contributors usually based on the free software |
|
6 |
product/project/distribution they're involved in. This is the case with teams |
|
7 |
like the 'Gnome Team' and the 'Ubuntu Team'. These teams often have leaders |
|
8 |
whose ellection depends on the vote of all members, and this is one of the |
|
9 |
reasons why we teams can have polls attached to them. |
|
10 |
||
11666.3.1
by Curtis Hovey
Merged apocalypse-0 into this branch to fix translations and codehosting. |
11 |
>>> import pytz |
12 |
>>> from datetime import datetime, timedelta |
|
13 |
>>> from zope.component import getUtility |
|
14 |
>>> from canonical.database.sqlbase import flush_database_updates |
|
14600.1.2
by Curtis Hovey
Updated callsites to import from lp.testing, where the code has been for years. |
15 |
>>> from lp.testing import login |
11716.1.6
by Curtis Hovey
Converted glob imports in doctests to import for the true module. |
16 |
>>> from lp.registry.interfaces.person import IPersonSet |
11716.1.15
by Curtis Hovey
Fixed multiline import statements in doctests. |
17 |
>>> from lp.registry.interfaces.poll import ( |
11716.1.12
by Curtis Hovey
Sorted imports in doctests. |
18 |
... IPollSubset, |
19 |
... PollAlgorithm, |
|
20 |
... PollSecrecy, |
|
21 |
... ) |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
22 |
|
11666.3.1
by Curtis Hovey
Merged apocalypse-0 into this branch to fix translations and codehosting. |
23 |
>>> team = getUtility(IPersonSet).getByName('ubuntu-team') |
24 |
>>> member = getUtility(IPersonSet).getByName('stevea') |
|
25 |
>>> member2 = getUtility(IPersonSet).getByName('jdub') |
|
26 |
>>> member3 = getUtility(IPersonSet).getByName('kamion') |
|
27 |
>>> member4 = getUtility(IPersonSet).getByName('name16') |
|
28 |
>>> member5 = getUtility(IPersonSet).getByName('limi') |
|
29 |
>>> nonmember = getUtility(IPersonSet).getByName('justdave') |
|
30 |
>>> now = datetime.now(pytz.timezone('UTC')) |
|
31 |
>>> onesec = timedelta(seconds=1) |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
32 |
|
2865.2.7
by Celso Providelo
Integrating DB tweaks required for upload-and-queue and breezy-autotest, renaming and fixing tests. |
33 |
We need to login with one of the administrators of the team named |
34 |
'ubuntu-team' to be able to create/edit polls. |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
35 |
>>> login('colin.watson@ubuntulinux.com') |
36 |
||
37 |
First we get an object implementing IPollSubset, which is the set of polls for |
|
38 |
a given team (in our case, the 'Ubuntu Team') |
|
39 |
>>> pollsubset = IPollSubset(team) |
|
40 |
||
41 |
Now we create a new poll on this team. |
|
42 |
>>> opendate = datetime(2005, 01, 01, tzinfo=pytz.timezone('UTC')) |
|
43 |
>>> closedate = opendate + timedelta(weeks=2) |
|
2219
by Canonical.com Patch Queue Manager
Some fixes as per Steve review. Do not use Subsets to traverse; instead do the traversal by consuming items from the traversal stack. r=SteveA |
44 |
>>> title = "2005 Leader's Elections" |
45 |
>>> proposition = "Who's going to be the next leader?" |
|
46 |
>>> type = PollAlgorithm.SIMPLE |
|
47 |
>>> secrecy = PollSecrecy.SECRET |
|
48 |
>>> allowspoilt = True |
|
49 |
>>> poll = pollsubset.new("leader-election", title, proposition, opendate, |
|
2491
by Canonical.com Patch Queue Manager
Simple and Condorcet polls (although the latter is disabled for now) for teams. r=BjornT |
50 |
... closedate, secrecy, allowspoilt, type) |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
51 |
|
52 |
Now we test the if the poll is open or closed in some specific dates. |
|
53 |
>>> poll.isOpen(when=opendate) |
|
54 |
True |
|
55 |
>>> poll.isOpen(when=opendate - onesec) |
|
56 |
False |
|
57 |
>>> poll.isOpen(when=closedate) |
|
58 |
True |
|
59 |
>>> poll.isOpen(when=closedate + onesec) |
|
60 |
False |
|
61 |
||
62 |
To know what polls are open/closed/not-yet-opened in a team, you can use the |
|
63 |
methods of PollSubset. |
|
64 |
Here we'll query using three different dates: |
|
65 |
||
66 |
Query for open polls in the exact second the poll is opening. |
|
67 |
>>> [p.name for p in pollsubset.getOpenPolls(when=opendate)] |
|
12156.3.1
by Curtis Hovey
Restored polls so that they can be used by a handful of important teams once a year. |
68 |
[u'leader-election', u'never-closes', u'never-closes2', u'never-closes3', |
69 |
u'never-closes4'] |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
70 |
|
71 |
Query for closed polls, one second after the poll closes. |
|
72 |
>>> [p.name for p in pollsubset.getClosedPolls(when=closedate + onesec)] |
|
2491
by Canonical.com Patch Queue Manager
Simple and Condorcet polls (although the latter is disabled for now) for teams. r=BjornT |
73 |
[u'director-2004', u'leader-2004', u'leader-election'] |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
74 |
|
75 |
Query for not-yet-opened polls, one second before the poll opens. |
|
76 |
>>> [p.name for p in pollsubset.getNotYetOpenedPolls(when=opendate - onesec)] |
|
12156.3.1
by Curtis Hovey
Restored polls so that they can be used by a handful of important teams once a year. |
77 |
[u'leader-election', u'not-yet-opened'] |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
78 |
|
79 |
All polls must have a set of options for people to choose, and they'll always |
|
80 |
start with zero options. We're responsible for adding new ones. |
|
12156.3.1
by Curtis Hovey
Restored polls so that they can be used by a handful of important teams once a year. |
81 |
>>> poll.getAllOptions().count() |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
82 |
0 |
83 |
||
84 |
Let's add some options to this poll, so people can start voting. :) |
|
2736.1.11
by Mark Shuttleworth
poll system fixes |
85 |
>>> will = poll.newOption('wgraham', 'Will Graham') |
86 |
>>> jack = poll.newOption('jcrawford', 'Jack Crawford') |
|
87 |
>>> francis = poll.newOption('fd', 'Francis Dolarhyde') |
|
88 |
>>> [o.title for o in poll.getActiveOptions()] |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
89 |
[u'Francis Dolarhyde', u'Jack Crawford', u'Will Graham'] |
90 |
||
91 |
Now, what happens if the poll is already open and, let's say, Francis Dolarhyde |
|
2219
by Canonical.com Patch Queue Manager
Some fixes as per Steve review. Do not use Subsets to traverse; instead do the traversal by consuming items from the traversal stack. r=SteveA |
92 |
is convicted and thus becomes ineligible? We'll have to mark that option as |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
93 |
inactive, so people can't vote on it. |
94 |
>>> francis.active = False |
|
95 |
>>> flush_database_updates() |
|
2736.1.11
by Mark Shuttleworth
poll system fixes |
96 |
>>> [o.title for o in poll.getActiveOptions()] |
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
97 |
[u'Jack Crawford', u'Will Graham'] |
98 |
||
2491
by Canonical.com Patch Queue Manager
Simple and Condorcet polls (although the latter is disabled for now) for teams. r=BjornT |
99 |
If the poll is not yet opened, it's possible to simply remove a given option. |
100 |
>>> poll.removeOption(will, when=opendate - onesec) |
|
2736.1.11
by Mark Shuttleworth
poll system fixes |
101 |
>>> [o.title for o in poll.getAllOptions()] |
2491
by Canonical.com Patch Queue Manager
Simple and Condorcet polls (although the latter is disabled for now) for teams. r=BjornT |
102 |
[u'Francis Dolarhyde', u'Jack Crawford'] |
103 |
||
104 |
Any member of the team this poll refers to is eligible to vote, if the poll is |
|
105 |
still open. |
|
106 |
||
107 |
>>> vote1 = poll.storeSimpleVote(member, jack, when=opendate) |
|
108 |
>>> vote2 = poll.storeSimpleVote(member2, None, when=opendate) |
|
109 |
||
110 |
||
111 |
Now we create a Condorcet poll on this team and add some options to it, so |
|
112 |
people can start voting. |
|
113 |
||
114 |
>>> title = "2005 Director's Elections" |
|
115 |
>>> proposition = "Who's going to be the next director?" |
|
116 |
>>> type = PollAlgorithm.CONDORCET |
|
117 |
>>> secrecy = PollSecrecy.SECRET |
|
118 |
>>> allowspoilt = True |
|
119 |
>>> poll2 = pollsubset.new("director-election", title, proposition, opendate, |
|
120 |
... closedate, secrecy, allowspoilt, type) |
|
2736.1.11
by Mark Shuttleworth
poll system fixes |
121 |
>>> a = poll2.newOption('A', 'Option A') |
122 |
>>> b = poll2.newOption('B', 'Option B') |
|
123 |
>>> c = poll2.newOption('C', 'Option C') |
|
124 |
>>> d = poll2.newOption('D', 'Option D') |
|
2491
by Canonical.com Patch Queue Manager
Simple and Condorcet polls (although the latter is disabled for now) for teams. r=BjornT |
125 |
|
126 |
>>> options = {b: 1, d: 2, c: 3} |
|
127 |
>>> votes = poll2.storeCondorcetVote(member, options, when=opendate) |
|
128 |
>>> options = {d: 1, b: 2} |
|
129 |
>>> votes = poll2.storeCondorcetVote(member2, options, when=opendate) |
|
130 |
>>> options = {a: 1, c: 2, b: 3} |
|
131 |
>>> votes = poll2.storeCondorcetVote(member3, options, when=opendate) |
|
132 |
>>> options = {a: 1} |
|
133 |
>>> votes = poll2.storeCondorcetVote(member4, options, when=opendate) |
|
134 |
>>> for row in poll2.getPairwiseMatrix(): |
|
135 |
... print row |
|
136 |
[None, 2L, 2L, 2L] |
|
137 |
[2L, None, 2L, 2L] |
|
138 |
[1L, 1L, None, 1L] |
|
139 |
[2L, 1L, 2L, None] |
|
2162
by Canonical.com Patch Queue Manager
cleanup and portlet love [r=stevea] |
140 |