Polls ===== In Launchpad, we have teams as a way to group free software developers/contributors usually based on the free software product/project/distribution they're involved in. This is the case with teams like the 'Gnome Team' and the 'Ubuntu Team'. These teams often have leaders whose ellection depends on the vote of all members, and this is one of the reasons why we teams can have polls attached to them. >>> import pytz >>> from datetime import datetime, timedelta >>> from zope.component import getUtility >>> from lp.services.database.sqlbase import flush_database_updates >>> from lp.testing import login >>> from lp.registry.interfaces.person import IPersonSet >>> from lp.registry.interfaces.poll import ( ... IPollSubset, ... PollAlgorithm, ... PollSecrecy, ... ) >>> team = getUtility(IPersonSet).getByName('ubuntu-team') >>> member = getUtility(IPersonSet).getByName('stevea') >>> member2 = getUtility(IPersonSet).getByName('jdub') >>> member3 = getUtility(IPersonSet).getByName('kamion') >>> member4 = getUtility(IPersonSet).getByName('name16') >>> member5 = getUtility(IPersonSet).getByName('limi') >>> nonmember = getUtility(IPersonSet).getByName('justdave') >>> now = datetime.now(pytz.timezone('UTC')) >>> onesec = timedelta(seconds=1) We need to login with one of the administrators of the team named 'ubuntu-team' to be able to create/edit polls. >>> login('colin.watson@ubuntulinux.com') First we get an object implementing IPollSubset, which is the set of polls for a given team (in our case, the 'Ubuntu Team') >>> pollsubset = IPollSubset(team) Now we create a new poll on this team. >>> opendate = datetime(2005, 01, 01, tzinfo=pytz.timezone('UTC')) >>> closedate = opendate + timedelta(weeks=2) >>> title = "2005 Leader's Elections" >>> proposition = "Who's going to be the next leader?" >>> type = PollAlgorithm.SIMPLE >>> secrecy = PollSecrecy.SECRET >>> allowspoilt = True >>> poll = pollsubset.new("leader-election", title, proposition, opendate, ... closedate, secrecy, allowspoilt, type) Now we test the if the poll is open or closed in some specific dates. >>> poll.isOpen(when=opendate) True >>> poll.isOpen(when=opendate - onesec) False >>> poll.isOpen(when=closedate) True >>> poll.isOpen(when=closedate + onesec) False To know what polls are open/closed/not-yet-opened in a team, you can use the methods of PollSubset. Here we'll query using three different dates: Query for open polls in the exact second the poll is opening. >>> [p.name for p in pollsubset.getOpenPolls(when=opendate)] [u'leader-election', u'never-closes', u'never-closes2', u'never-closes3', u'never-closes4'] Query for closed polls, one second after the poll closes. >>> [p.name for p in pollsubset.getClosedPolls(when=closedate + onesec)] [u'director-2004', u'leader-2004', u'leader-election'] Query for not-yet-opened polls, one second before the poll opens. >>> [p.name for p in pollsubset.getNotYetOpenedPolls(when=opendate - onesec)] [u'leader-election', u'not-yet-opened'] All polls must have a set of options for people to choose, and they'll always start with zero options. We're responsible for adding new ones. >>> poll.getAllOptions().count() 0 Let's add some options to this poll, so people can start voting. :) >>> will = poll.newOption('wgraham', 'Will Graham') >>> jack = poll.newOption('jcrawford', 'Jack Crawford') >>> francis = poll.newOption('fd', 'Francis Dolarhyde') >>> [o.title for o in poll.getActiveOptions()] [u'Francis Dolarhyde', u'Jack Crawford', u'Will Graham'] Now, what happens if the poll is already open and, let's say, Francis Dolarhyde is convicted and thus becomes ineligible? We'll have to mark that option as inactive, so people can't vote on it. >>> francis.active = False >>> flush_database_updates() >>> [o.title for o in poll.getActiveOptions()] [u'Jack Crawford', u'Will Graham'] If the poll is not yet opened, it's possible to simply remove a given option. >>> poll.removeOption(will, when=opendate - onesec) >>> [o.title for o in poll.getAllOptions()] [u'Francis Dolarhyde', u'Jack Crawford'] Any member of the team this poll refers to is eligible to vote, if the poll is still open. >>> vote1 = poll.storeSimpleVote(member, jack, when=opendate) >>> vote2 = poll.storeSimpleVote(member2, None, when=opendate) Now we create a Condorcet poll on this team and add some options to it, so people can start voting. >>> title = "2005 Director's Elections" >>> proposition = "Who's going to be the next director?" >>> type = PollAlgorithm.CONDORCET >>> secrecy = PollSecrecy.SECRET >>> allowspoilt = True >>> poll2 = pollsubset.new("director-election", title, proposition, opendate, ... closedate, secrecy, allowspoilt, type) >>> a = poll2.newOption('A', 'Option A') >>> b = poll2.newOption('B', 'Option B') >>> c = poll2.newOption('C', 'Option C') >>> d = poll2.newOption('D', 'Option D') >>> options = {b: 1, d: 2, c: 3} >>> votes = poll2.storeCondorcetVote(member, options, when=opendate) >>> options = {d: 1, b: 2} >>> votes = poll2.storeCondorcetVote(member2, options, when=opendate) >>> options = {a: 1, c: 2, b: 3} >>> votes = poll2.storeCondorcetVote(member3, options, when=opendate) >>> options = {a: 1} >>> votes = poll2.storeCondorcetVote(member4, options, when=opendate) >>> for row in poll2.getPairwiseMatrix(): ... print row [None, 2L, 2L, 2L] [2L, None, 2L, 2L] [1L, 1L, None, 1L] [2L, 1L, 2L, None]