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