This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git

commit a1d7f7357b499f32972a02347cc3bd4fb0af685c
Author: Daniel Gruno <[email protected]>
AuthorDate: Sun Jan 26 12:24:47 2025 +0100

    Python 3 compatibility updates
    
    - hashlib now only accepts bytestrings, so we'll set up a wrapper in
    constants for auto-converting.
    - izip no longer exists, zip to be used instead
    - fix import paths
    - multipart boundary must be bytestring
    - cmp no longer exists, sorted() now needs a wrapper via functools
---
 pysteve/lib/constants.py          |  6 +++++-
 pysteve/lib/election.py           | 20 ++++++++++----------
 pysteve/lib/form.py               |  3 ++-
 pysteve/lib/plugins/stv.py        | 15 ++++++++-------
 pysteve/lib/voter.py              |  6 +++---
 pysteve/www/cgi-bin/rest_voter.py |  7 ++++---
 6 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/pysteve/lib/constants.py b/pysteve/lib/constants.py
index 4a101bb..402abc1 100644
--- a/pysteve/lib/constants.py
+++ b/pysteve/lib/constants.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 
-
+import hashlib
 VOTE_TYPES = (
     
 )
@@ -24,6 +24,10 @@ DB_TYPES = (
     
 )
 
+def hexdigest(data: str):
+    """Wrapper for hashlib.sha224().hexdigest that handles encoding"""
+    return hashlib.sha224(data.encode("utf-8")).hexdigest()
+
 def appendVote(*types):
     """ Append a new type of voting to the list"""
     global VOTE_TYPES
diff --git a/pysteve/lib/election.py b/pysteve/lib/election.py
index 84a2061..cc3fe36 100644
--- a/pysteve/lib/election.py
+++ b/pysteve/lib/election.py
@@ -19,7 +19,7 @@ import json
 import os
 import random
 import time
-from itertools import izip
+#from itertools import izip
 
 try:
     from __main__ import config
@@ -28,9 +28,9 @@ except:
     config = configparser.RawConfigParser()
     config.read("%s/../../../steve.cfg" % (os.path.dirname(__file__)))
     
-import constants, voter
-from plugins import *
-from backends import *
+from lib import constants, voter
+from lib.plugins import *
+from lib.backends import *
 
 
 
@@ -88,7 +88,7 @@ def createElection(eid, title, owner, monitors, starts, ends, 
isopen):
             'monitors': monitors,
             'starts': starts,
             'ends': ends,
-            'hash': hashlib.sha512("%f-stv-%s" % (time.time(), 
os.environ['REMOTE_ADDR'] if 'REMOTE_ADDR' in os.environ else 
random.randint(1,99999999999))).hexdigest(),
+            'hash': constants.hexdigest("%f-stv-%s" % (time.time(), 
os.environ['REMOTE_ADDR'] if 'REMOTE_ADDR' in os.environ else 
random.randint(1,99999999999)), method=hashlib.sha512),
             'open': isopen
         }
     backend.election_create(eid, basedata)
@@ -122,9 +122,9 @@ def vote(electionID, issueID, voterID, vote):
     basedata = getBasedata(electionID)
     issueData = getIssue(electionID, issueID)
     if basedata and issueData:
-        xhash = hashlib.sha224(electionID + ":" + voterID).hexdigest()
-        vhash = hashlib.sha224(xhash + issueID).hexdigest()
-        votehash = hashlib.sha224(basedata['hash'] + issueID + voterID + 
vote).hexdigest()
+        xhash = constants.hexdigest(electionID + ":" + voterID)
+        vhash = constants.hexdigest(xhash + issueID)
+        votehash = constants.hexdigest(basedata['hash'] + issueID + voterID + 
vote)
         
         # Vote verification
         voteType = getVoteType(issueData)
@@ -182,10 +182,10 @@ def getHash(electionID):
         votes = getVotes(electionID, issue)
         ihash += issuedata['hash']
         output.append("Issue #%s: %s\n- Checksum: %s\n- Votes cast: %u\n" % 
(issue, issuedata['title'], issuedata['hash'], len(votes)))
-    tothash = hashlib.sha224(ihash).hexdigest()
+    tothash = constants.hexdigest(ihash)
     output.insert(0, ("You are receiving this data because you are listed as a 
monitor for this election.\nThe following data shows the state of the election 
data on disk. If any of these checksums change, especially the main checksum, 
then the election has been edited (rigged?) after invites were sent 
out.\n\nMain Election Checksum : %s\n\n" % tothash))
     output.append("\nYou can monitor votes and recasts online at: 
%s/monitor.html?%s" % (config.get("general", "rooturl"), electionID))
     return tothash, "\n".join(output)
 
 def createIssue(electionID, issueID, data):
-    backend.issue_create(electionID, issueID, data)
\ No newline at end of file
+    backend.issue_create(electionID, issueID, data)
diff --git a/pysteve/lib/form.py b/pysteve/lib/form.py
index 9b0520f..31ce381 100644
--- a/pysteve/lib/form.py
+++ b/pysteve/lib/form.py
@@ -19,7 +19,8 @@ import cgi
 
 ctype, pdict = cgi.parse_header(os.environ['CONTENT_TYPE'] if 'CONTENT_TYPE' 
in os.environ else "")
 if ctype == 'multipart/form-data':
-    xform = cgi.parse_multipart(sys.stdin, pdict)
+    pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
+    xform = cgi.parse_multipart(sys.stdin, pdict, encoding="utf-8")
 else:
     xform = cgi.FieldStorage();
 
diff --git a/pysteve/lib/plugins/stv.py b/pysteve/lib/plugins/stv.py
index af74e54..3807790 100644
--- a/pysteve/lib/plugins/stv.py
+++ b/pysteve/lib/plugins/stv.py
@@ -27,6 +27,7 @@ BILLIONTH = 0.000000001
 
 
 from lib import constants
+import functools
 
 debug = []
 
@@ -137,7 +138,7 @@ class CandidateList(object):
 
   def print_results(self):
     for c in self.l:
-      print '%-40s%selected' % (c.name, c.status == ELECTED and ' ' or ' not ')
+      print ('%-40s%selected' % (c.name, c.status == ELECTED and ' ' or ' not 
'))
 
   def dbg_display_tables(self, excess):
     total = excess
@@ -147,7 +148,6 @@ class CandidateList(object):
     debug.append('%-20s %15s %15.9f' %( 'Non-transferable', ' ', excess))
     debug.append('%-20s %15s %15.9f' % ( 'Total', ' ', total))
 
-
 class Candidate(object):
   def __init__(self, name, rand, ahead):
     self.name = name
@@ -170,11 +170,12 @@ class Candidate(object):
     assert quota is not None
     self.weight = (self.weight * quota) / self.vote
 
-  def __cmp__(self, other):
-    if self.ahead < other.ahead:
+  @staticmethod
+  def cmp(a,b):
+    if a.ahead < b.ahead:
       return -1
-    if self.ahead == other.ahead:
-      return cmp(self.vote, other.vote)
+    if a.ahead == b.ahead:
+        return (a.vote > b.vote) - (a.vote < b.vote)
     return 1
 
 
@@ -227,7 +228,7 @@ def calc_totals(votes, candidates):
 
 
 def calc_aheads(candidates):
-  c_sorted = sorted(candidates.l)
+  c_sorted = sorted(candidates.l, key=functools.cmp_to_key(Candidate.cmp))
   last = 0
   for i in range(1, len(c_sorted)+1):
     if i == len(c_sorted) or c_sorted[last] != c_sorted[i]:
diff --git a/pysteve/lib/voter.py b/pysteve/lib/voter.py
index dbc7242..e6007c6 100644
--- a/pysteve/lib/voter.py
+++ b/pysteve/lib/voter.py
@@ -33,13 +33,13 @@ from lib import constants, election
 backend = constants.initBackend(config)
 
 def get(election, basedata, uid):
-    xhash = hashlib.sha512(basedata['hash'] + uid).hexdigest()
+    xhash = constants.hexdigest(basedata['hash'] + uid, method=hashlib.sha512)
     return backend.voter_get_uid(election, xhash)
     
     
 def add(election, basedata, PID):
-    uid = hashlib.sha224("%s%s%s%s" % (PID, basedata['hash'], time.time(), 
random.randint(1,99999999))).hexdigest()
-    xhash = hashlib.sha512(basedata['hash'] + uid).hexdigest()
+    uid = constants.hexdigest("%s%s%s%s" % (PID, basedata['hash'], 
time.time(), random.randint(1,99999999)))
+    xhash = constants.hexdigest(basedata['hash'] + uid, method=hashlib.sha512)
     backend.voter_add(election, PID, xhash)
     return uid, xhash
     
diff --git a/pysteve/www/cgi-bin/rest_voter.py 
b/pysteve/www/cgi-bin/rest_voter.py
index 7b2fb12..ae951cb 100755
--- a/pysteve/www/cgi-bin/rest_voter.py
+++ b/pysteve/www/cgi-bin/rest_voter.py
@@ -36,11 +36,12 @@ if 'SCRIPT_FILENAME' in os.environ:
 config = configparser.RawConfigParser()
 config.read(path + '/../../steve.cfg')
 
+
 # Some quick paths
 homedir = config.get("general", "homedir")
 pathinfo = os.environ['PATH_INFO'] if 'PATH_INFO' in os.environ else None
 
-from lib import response, voter, election, form
+from lib import response, voter, election, form, constants
 
 
 whoami = os.environ['REMOTE_USER'] if 'REMOTE_USER' in os.environ else None
@@ -145,7 +146,7 @@ if pathinfo:
                             response.respond(500, {'message': invalid})
                         else:
                             votehash = election.vote(electionID, issueID, 
voterID, vote)
-                            voteuid = hashlib.sha224(voterID).hexdigest()
+                            voteuid = constants.hexdigest(voterID)
                             # Catch proxy-emails
                             m = re.match(r"^(.+@.*?[a-zA-Z])-[^.]+$", email)
                             if m:
@@ -198,4 +199,4 @@ if pathinfo:
     else:
         response.respond(400, {'message': 'Invalid action supplied'})
 else:
-    response.respond(500, {'message': 'No path info supplied, aborting'})
\ No newline at end of file
+    response.respond(500, {'message': 'No path info supplied, aborting'})

Reply via email to