Attachment 'Vote.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 
   7     Usage:
   8         [[Vote(pageName, voteTitle, candidate1, ...)]]
   9 
  10     E.g:
  11         [[Vote(MyBlog, Do polls work?, yes)]]
  12     
  13     Just like Martin's Vote macro, except you must specify the name of the
  14     page on which to vote "appears."  Without this information, when a user
  15     votes from an included page, after pressing the Vote button they are
  16     returned to the included page, not the main page.  Also different is
  17     that the current number of votes is hidden until the user has voted.
  18     Lastly, it is possible to have a poll that only has one choice, which
  19     is kind of funny.  The remainder of the description is Martin's:
  20 
  21     You can have multiple votes on one page (so long as the titles are unique).
  22     You can add candidates after a vote has started, but note that renaming 
  23     candidates will lose the votes (and not allow users to recast their votes).
  24     Changing the vote title creates a new vote.
  25 
  26     Vote data is stored in data_dir/pages/pagename/votes 
  27     (i.e. alongside the attachments directory for a page).
  28 
  29     You can customise the appearance by defining the following CSS styles:
  30         table.vote 
  31         td.votelogin (for "must login" message)
  32 '''
  33 
  34 from MoinMoin import user, webapi, wikiutil, config
  35 import os
  36 import pickle
  37 import string
  38 
  39 
  40 def getVotesDir(macro):
  41     """ Get directory where votes on this page are stored.
  42     """
  43     pagename = macro.formatter.page.page_name
  44     return os.path.join(config.data_dir, "pages", pagename, "votes")
  45 
  46 
  47 def makeFilename(voteName):
  48     voteName = string.translate(voteName, string.maketrans('\\/:*?"<>|', 'xxxxxxxxx'), string.whitespace) # any I've missed?
  49     return voteName+".pik"
  50 
  51 
  52 def loadVotes(macro,voteName):
  53     try:
  54         f = open(os.path.join(getVotesDir(macro), makeFilename(voteName)), 'r')
  55         return pickle.load(f)
  56     except:
  57         return {}
  58 
  59 
  60 def saveVotes(macro,voteName, votes):
  61     votesDir = getVotesDir(macro)
  62     if not os.path.isdir(votesDir): 
  63         os.makedirs(votesDir) #need mode?
  64 
  65     f = open(os.path.join(votesDir, makeFilename(voteName)), 'w')
  66     pickle.dump(votes, f)
  67 
  68 
  69 def countVotes(votes):
  70     results = {}
  71     for v in votes.values():
  72         results.setdefault(v, 0)
  73         results[v] = results[v] + 1
  74 
  75     return results
  76 
  77 
  78 def execute(macro, args):
  79     args = string.split(args, ",")
  80     args = map(string.strip, args)
  81 
  82     if len(args) < 3: return macro.formatter.rawHTML('<pre>[[Vote: Insufficient macro arguments]]</pre>')
  83 
  84     pageName = args[0]
  85     voteName = args[1]
  86     candidates = args[2:]
  87 
  88     form = macro.form
  89     votes = loadVotes(macro,voteName)
  90     voter = macro.request.user.name
  91 
  92     # votes are stored in a dictionary as {user: candidate} to avoid duplicate votes
  93     # (a voter could switch their vote but this UI doesn't expose that facility)
  94     if form.has_key('vote') and form.has_key('voteName') and voter:
  95         if form['voteName'][0] == voteName:
  96             votes[voter] = form['vote'][0]
  97             try:
  98                saveVotes(macro, voteName, votes)
  99             except:
 100                return macro.formatter.rawHTML('<a id="voteform"><pre>[[Vote: failed to store vote]]</pre>')
 101 
 102     # generate dictionary {candidate: numvotes}
 103     results = countVotes(votes)
 104 
 105     hasVoted = voter in votes
 106 
 107     # spit out votes table (as part of a form if the user hasn't voted yet)
 108     html = ''
 109     if not hasVoted:
 110         voteButton = '<td><INPUT type="radio" name="vote" value="%s">vote</td>'
 111         html += '''
 112             <form method="get" action="%(scriptname)s/%(pageName)s#voteform">\n
 113             <input type="hidden" name="voteName" value="%(voteName)s">
 114             ''' % {'scriptname': r'/cgi-bin/moin.cgi', 'pageName': pageName, 'voteName': voteName}
 115     else:
 116         voteButton = ''
 117 
 118     html += '<a id="voteform"><table class="vote"><tr><th colspan="2">%s</th></tr>' % voteName
 119 
 120     for candidate in candidates:
 121         button = voteButton and (voteButton % candidate)
 122         if not hasVoted:
 123             button = '<td><INPUT type="radio" name="vote" value="%s">%s</td>' % (candidate, candidate)
 124             count = ''
 125         else:
 126             button = candidate
 127             count = results.setdefault(candidate, 0)
 128         html += '<tr><td>%s</td><td>%s</td></tr>\n' % (button, count)
 129 
 130     if not voter and not hasVoted:
 131         html += '<tr><td colspan="3" class="votelogin">You need to login to vote</td></tr>'
 132 
 133     html += '</table>\n'
 134 
 135     if not hasVoted:
 136         html += '<input type="submit" value="Vote">\n</form>\n'
 137         
 138     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.
  • [get | view] (2003-12-07 18:15:54, 0.4 KB) [[attachment:Color.py]]
  • [get | view] (2003-12-07 18:15:54, 1.3 KB) [[attachment:Nav.py]]
  • [get | view] (2003-12-07 18:15:54, 0.7 KB) [[attachment:Up.py]]
  • [get | view] (2004-03-04 18:39:13, 4.6 KB) [[attachment:Vote.py]]
  • [get | view] (2003-12-07 18:15:54, 4.6 KB) [[attachment:Vote2.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.