Attachment 'Vote_1.3.py'
Download 1 #format python
2 '''
3 Simple Vote macro for MoinMoin.
4 Author: Martin Stone <martins@evos.net>
5 Hacked by: John Cocula (john@cocula.com)
6 Thomas Waldmann
7 Updated by: Akshat Aranya (aaranya@gmail.com)
8
9 Usage:
10 [[Vote(pageName, voteTitle, candidate1, ...)]]
11
12 E.g:
13 [[Vote(MyBlog, Do polls work?, yes)]]
14
15 Just like Martin's Vote macro, except you must specify the name of the
16 page on which to vote "appears." Without this information, when a user
17 votes from an included page, after pressing the Vote button they are
18 returned to the included page, not the main page. Also different is
19 that the current number of votes is hidden until the user has voted.
20 Lastly, it is possible to have a poll that only has one choice, which
21 is kind of funny. The remainder of the description is Martin's:
22
23 You can have multiple votes on one page (so long as the titles are unique).
24 You can add candidates after a vote has started, but note that renaming
25 candidates will lose the votes (and not allow users to recast their votes).
26 Changing the vote title creates a new vote.
27
28 Vote data is stored in data_dir/pages/pagename/votes
29 (i.e. alongside the attachments directory for a page).
30
31 You can customise the appearance by defining the following CSS styles:
32 table.vote
33 td.votelogin (for "must login" message)
34 '''
35
36 import os, pickle
37 from MoinMoin import wikiutil
38 from MoinMoin.util import filesys
39
40 def makeFilename(thisPage, voteName):
41 votesDir = thisPage.getPagePath("votes")
42 if not os.path.exists(votesDir):
43 filesys.makeDirs(votesDir)
44 voteName = wikiutil.quoteWikinameFS(voteName) + '.pik'
45 return os.path.join(votesDir, voteName)
46
47 def loadVotes(thisPage, voteName):
48 votesFile = makeFilename(thisPage, voteName)
49 try:
50 f = open(votesFile, 'r')
51 return pickle.load(f)
52 except: # XXX
53 return {}
54
55 def saveVotes(thisPage, voteName, votes):
56 votesFile = makeFilename(thisPage, voteName)
57 f = open(votesFile, 'w')
58 pickle.dump(votes, f)
59
60 def countVotes(votes):
61 results = {}
62 for v in votes.values():
63 results.setdefault(v, 0)
64 results[v] += 1
65 return results
66
67 def execute(macro, args):
68 args = args.split(",")
69 args = map(unicode.strip, args)
70
71 if len(args) < 3:
72 return macro.formatter.rawHTML('<pre>[[Vote: Insufficient macro arguments]]</pre>')
73
74 pageName = args[0]
75 voteName = args[1]
76 candidates = args[2:]
77
78 form = macro.form
79 request = macro.request
80 if request.user.valid:
81 voter = request.user.name
82 else:
83 voter = ''
84 thisPage = macro.formatter.page
85 votes = loadVotes(thisPage, voteName)
86
87 # votes are stored in a dictionary as {user: candidate} to avoid duplicate votes
88 # (a voter could switch their vote but this UI doesn't expose that facility)
89 if form.has_key('vote') and form.has_key('voteName') and voter:
90 if form['voteName'][0] == voteName:
91 votes[voter] = form['vote'][0]
92 try:
93 saveVotes(thisPage, voteName, votes)
94 except: # XXX
95 return macro.formatter.rawHTML('<a id="voteform"><pre>[[Vote: failed to store vote]]</pre>')
96
97 # generate dictionary {candidate: numvotes}
98 results = countVotes(votes)
99
100 hasVoted = voter in votes
101
102 # spit out votes table (as part of a form if the user hasn't voted yet)
103 html = ''
104 if voter and not hasVoted:
105 voteButton = '<td><input type="radio" name="vote" value="%s">vote</td>'
106 html += '''
107 <form method="get" action="%(url)s#voteform">\n
108 <input type="hidden" name="voteName" value="%(voteName)s">
109 ''' % {
110 'url': thisPage.url(request),
111 'voteName': voteName,
112 }
113 else:
114 voteButton = ''
115
116 html += '<a id="voteform"><table class="vote"><tr><th colspan="2">%s</th></tr>' % voteName
117
118 for candidate in candidates:
119 button = voteButton and (voteButton % candidate)
120 if voter:
121 if hasVoted:
122 button = candidate
123 count = results.setdefault(candidate, 0)
124 else:
125 button = '<td><input type="radio" name="vote" value="%s">%s</td>' % (candidate, candidate)
126 count = '???'
127 else:
128 button = candidate
129 count = '???'
130 html += '<tr><td>%s</td><td>%s</td></tr>\n' % (button, count)
131
132 if not voter:
133 html += '<tr><td colspan="3" class="votelogin">You need to login to vote</td></tr>'
134
135 html += '</table>\n'
136 html += '</a>\n'
137
138 if voter and not hasVoted:
139 html += '<input type="submit" value="Vote">\n</form>\n'
140
141 return macro.formatter.rawHTML(html)
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.