This patch adds the ability to make fully anonymous polls, simply by the use of pattern (*) at the end of the poll question:
Index: pollmacro/trunk/tracpoll/tracpoll.py
===================================================================
--- pollmacro/trunk/tracpoll/tracpoll.py (revision 11672)
+++ pollmacro/trunk/tracpoll/tracpoll.py (working copy)
@@ -1,3 +1,4 @@
+import hashlib
import os
import re
import pickle
@@ -49,7 +50,7 @@
finally:
fd.close()
- def populate(self, req):
+ def populate(self, req, isAnonymousPoll):
""" Update poll based on HTTP request. """
if req.args.get('poll', '') == self.key:
vote = req.args.get('vote', '')
@@ -58,13 +59,15 @@
if vote not in self.votes:
raise TracError('No such vote %s' % vote)
username = req.authname or 'anonymous'
+ if isAnonymousPoll:
+ username = hashlib.sha1(username).hexdigest()
for v, voters in self.votes.items():
if username in voters:
self.votes[v].remove(username)
self.votes[vote] = self.votes[vote] + [username]
self.save()
- def render(self, env, req):
+ def render(self, env, req, isAnonymousPoll):
out = StringIO()
can_vote = req.perm.has_permission('POLL_VOTE')
if can_vote:
@@ -76,6 +79,8 @@
' <ul>\n'
% escape(self.title))
username = req.authname or 'anonymous'
+ if isAnonymousPoll:
+ username = hashlib.sha1(username).hexdigest()
for id, style, vote in self.vote_defs:
hid = escape(str(id))
out.write('<li%s>\n' % (style and ' class="%s"' % style or ''))
@@ -90,12 +95,15 @@
else:
out.write(vote)
if self.votes[id]:
- out.write(' <span class="voters">(<span class="voter">' +
- '</span>, <span class="voter">'.join(self.votes[id]) +
- '</span>)</span>')
+ if isAnonymousPoll:
+ out.write(' <span class="voters">(%s)</span>' % len(self.votes[id]))
+ else:
+ out.write(' <span class="voters">(<span class="voter">' +
+ '</span>, <span class="voter">'.join(self.votes[id]) +
+ '</span>)</span>')
out.write('</li>\n')
if can_vote:
out.write('<input type="submit" value="Vote"/>')
else:
out.write("<br/><i>You don't have permission to vote. You may need to login.</i>")
out.write(' </ul>\n</fieldset>\n')
@@ -128,6 +136,7 @@
'Path where poll pickle dumps should be stored.')
def expand_macro(self, formatter, name, content):
+ isAnonymousPoll = False
req = formatter.req
if not content:
return system_message("A title must be provided as the first argument to the poll macro")
@@ -136,9 +145,11 @@
if len(content) < 2:
return system_message("One or more options must be provided to vote on.")
title = content.pop(0)
- return self.render_poll(req, title, content)
+ if title.endswith('(*)'):
+ isAnonymousPoll = True
+ return self.render_poll(req, title, content, isAnonymousPoll)
- def render_poll(self, req, title, votes):
+ def render_poll(self, req, title, votes, isAnonymousPoll):
add_stylesheet(req, 'poll/css/poll.css')
if not req.perm.has_permission('POLL_VIEW'):
return ''
@@ -184,8 +195,8 @@
poll = Poll(self.base_dir, title, all_votes)
if req.perm.has_permission('POLL_VOTE'):
- poll.populate(req)
- return poll.render(self.env, req)
+ poll.populate(req, isAnonymousPoll)
+ return poll.render(self.env, req, isAnonymousPoll)
# IPermissionRequestor methods
def get_permission_actions(self):