[Fedora Elections] #44: Rework FAS integration
by fedora-badges
#44: Rework FAS integration
-------------------------+-----------------------------
Reporter: pingou | Owner: nigelj
Type: enhancement | Status: new
Priority: major | Milestone: Future Release
Component: General | Version:
Keywords: | Blocked By:
Blocking: |
-------------------------+-----------------------------
At the moment we keep the user's FAS name in memcached but this is not
working so well and quite ofte we're stuck or very slow.
What we could do is add a new table or a new field in the candidate table,
to store locally the FAS name.
This way, when we add/edit candidates, we would query FAS for their name,
store it locally and forget about memcached.
--
Ticket URL: <https://fedorahosted.org/elections/ticket/44>
Fedora Elections <https://fedorahosted.org/elections/>
Fedora Elections
7 years, 2 months
Branch 'develop' - 31 commits - alembic/versions fedora_elections/admin.py fedora_elections/default_config.py fedora_elections/elections.py fedora_elections/forms.py fedora_elections/__init__.py fedora_elections/models.py fedora_elections/templates fedora_elections/utils.py files/fedora-elections.spec tests/test_flask_elections.py tests/test_flask_irc.py tests/test_flask_range_voting.py tests/test_flask_simple_voting.py
by Pierre-YvesChibon
alembic/versions/2b8f5a6f10a4_store_fas_name_locally.py | 27 +++
fedora_elections/__init__.py | 3
fedora_elections/admin.py | 32 +++
fedora_elections/default_config.py | 7
fedora_elections/elections.py | 138 +++++++---------
fedora_elections/forms.py | 6
fedora_elections/models.py | 3
fedora_elections/templates/admin/view_election.html | 1
fedora_elections/templates/index.html | 2
fedora_elections/utils.py | 16 -
files/fedora-elections.spec | 2
tests/test_flask_elections.py | 11 -
tests/test_flask_irc.py | 55 +++++-
tests/test_flask_range_voting.py | 11 +
tests/test_flask_simple_voting.py | 54 +++++-
15 files changed, 228 insertions(+), 140 deletions(-)
New commits:
commit d33ad98b8605f81fe4996635a02741029d29d297
Merge: 20889d6 f79dd09
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Fri Jan 22 15:44:09 2016 +0100
Merge pull request #56 from fedora-infra/lcl_cache_fas
Store locally the candidates' FAS name
commit f79dd094dec24318c35e20d9348449003898bd76
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:54:36 2016 +0100
Add the alembic revision to create the fas_name field in the candidates table
diff --git a/alembic/versions/2b8f5a6f10a4_store_fas_name_locally.py b/alembic/versions/2b8f5a6f10a4_store_fas_name_locally.py
new file mode 100644
index 0000000..6d960df
--- /dev/null
+++ b/alembic/versions/2b8f5a6f10a4_store_fas_name_locally.py
@@ -0,0 +1,27 @@
+"""Store fas_name locally
+
+Revision ID: 2b8f5a6f10a4
+Revises: d07c5ef2d03
+Create Date: 2016-01-21 16:53:38.956503
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '2b8f5a6f10a4'
+down_revision = 'd07c5ef2d03'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ """ Add the fas_name column to the candidates table. """
+ op.add_column(
+ 'candidates',
+ sa.Column('fas_name', sa.Unicode(150), nullable=True)
+ )
+
+
+def downgrade():
+ """ Drop the fas_name column from the candidates table. """
+ op.drop_column('candidates', 'fas_name')
commit e158baa40f360b8e00efccdd5185d613620301ab
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:51:35 2016 +0100
Drop the dependency on dogpile-cache
diff --git a/files/fedora-elections.spec b/files/fedora-elections.spec
index 1fa4d0f..d8619e1 100644
--- a/files/fedora-elections.spec
+++ b/files/fedora-elections.spec
@@ -24,7 +24,6 @@ BuildRequires: python-setuptools
BuildRequires: python-wtforms
BuildRequires: python-nose
BuildRequires: python-coverage
-BuildRequires: python-dogpile-cache
Requires: python-fedora
Requires: python-fedora-flask
@@ -34,7 +33,6 @@ Requires: python-openid
Requires: python-openid-teams
Requires: python-openid-cla
Requires: python-wtforms
-Requires: python-dogpile-cache
# EPEL6
%if ( 0%{?rhel} && 0%{?rhel} == 6 )
commit 8ab35838245e7bce5c303cc537ade5f96e5b1a51
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:50:58 2016 +0100
Drop the cache with dogpile
diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py
index c08a61c..2bd685e 100644
--- a/fedora_elections/__init__.py
+++ b/fedora_elections/__init__.py
@@ -84,8 +84,7 @@ from fedora_elections import models
SESSION = models.create_session(APP.config['DB_URL'])
from fedora_elections import forms
-cache = dogpile.cache.make_region()
-cache.configure(**APP.config['DOGPILE_CACHE'])
+
from fedora_elections.utils import build_name_map
diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py
index e887840..979dd9d 100644
--- a/fedora_elections/default_config.py
+++ b/fedora_elections/default_config.py
@@ -22,10 +22,3 @@ FAS_BASE_URL = 'https://admin.stg.fedoraproject.org/accounts/'
FAS_USERNAME = ''
FAS_PASSWORD = ''
FAS_CHECK_CERT = False
-
-DOGPILE_CACHE = {
- 'backend': 'dogpile.cache.dbm',
- 'arguments': {
- 'filename': '/var/tmp/elections-cache.dbm',
- },
-}
commit b134c1f22ac3d56b2ea13c713f91dd7fd0a416d2
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:50:13 2016 +0100
Drop get_fas_human_name since we store the info in the DB
diff --git a/fedora_elections/utils.py b/fedora_elections/utils.py
index 66ce8cb..a36270f 100644
--- a/fedora_elections/utils.py
+++ b/fedora_elections/utils.py
@@ -11,20 +11,6 @@ def build_name_map(election):
return {}
return dict([
- (str(candidate.id), get_fas_human_name(candidate.name))
+ (str(candidate.id), candidate.fas_name)
for candidate in election.candidates
])
-
-
-(a)fedora_elections.cache.cache_on_arguments()
-def get_fas_human_name(username):
- """ Given a fas username, return the fas human_name if possible.
-
- If the user has their name set to private or they don't exist, we just
- return the given username as a stand-in.
- """
- try:
- return fedora_elections.FAS2.person_by_username(username)['human_name']
- except (KeyError, AuthError), err:
- fedora_elections.APP.logger.debug(err)
- return username
commit 97c32031ddbd18b7af163ae38d00ab81301ea6f7
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:49:52 2016 +0100
In the admin page show the candidate's FAS name next to the name
diff --git a/fedora_elections/templates/admin/view_election.html b/fedora_elections/templates/admin/view_election.html
index c283de7..3448fb0 100644
--- a/fedora_elections/templates/admin/view_election.html
+++ b/fedora_elections/templates/admin/view_election.html
@@ -25,6 +25,7 @@
<ul>
{% for candidate in election.candidates.all() %}
<li>{{ candidate.name }}
+ {% if candidate.fas_name %} ({{ candidate.fas_name }}) {% endif %}
<a href="{{ url_for('admin_edit_candidate',
election_alias=election.alias,
candidate_id=candidate.id) }}">
commit 63770fc488df9f56fc91f07e4ffc491256b4f8e1
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:48:52 2016 +0100
Let's present the candidate's FAS name first if there is one
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index 7d04a90..3c1db97 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -122,7 +122,7 @@ def get_range_voting_form(candidates, max_range):
action = wtforms.HiddenField()
for candidate in candidates:
- title = candidate.name
+ title = candidate.fas_name or candidate.name
if candidate.url:
title = '%s <a href="%s">[Info]</a>' % (title, candidate.url)
field = wtforms.SelectField(
@@ -140,7 +140,7 @@ def get_simple_voting_form(candidates, fasusers):
titles = []
for candidate in candidates:
- title = candidate.name
+ title = candidate.fas_name or candidate.name
if fasusers: # pragma: no cover
# We can't cover FAS integration
try:
@@ -179,7 +179,7 @@ def get_select_voting_form(candidates, max_selection):
action = wtforms.HiddenField()
for candidate in candidates:
- title = candidate.name
+ title = candidate.fas_name or candidate.name
if candidate.url:
title = '%s <a href="%s">[Info]</a>' % (title, candidate.url)
field = wtforms.BooleanField(
commit c65dd9245077fb06cd0e5b219df8967e21f92ddd
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:48:44 2016 +0100
Little style clean up
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 14b777c..4ebd434 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -39,6 +39,7 @@ from fedora_elections import (
)
from fedora_elections.utils import build_name_map
+
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
@@ -122,6 +123,7 @@ def vote(election_alias):
'Unknown election voting type: %s' % election.voting_type)
return safe_redirect_back()
+
def vote_range(election, revote):
votes = models.Vote.of_user_on_election(
SESSION, flask.g.fas_user.username, election.id)
@@ -142,10 +144,10 @@ def vote_range(election, revote):
if form.validate_on_submit():
if form.action.data == 'submit':
candidates = [
- candidate
- for candidate in form
- if candidate and candidate.short_name not in ['csrf_token', 'action']
- ]
+ candidate
+ for candidate in form
+ if candidate and candidate.short_name not in ['csrf_token', 'action']
+ ]
process_vote(candidates, election, votes, revote)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -219,6 +221,7 @@ def vote_select(election, revote):
usernamemap=usernamemap,
nextaction=next_action)
+
def vote_simple(election, revote):
votes = models.Vote.of_user_on_election(
SESSION, flask.g.fas_user.username, election.id)
@@ -371,6 +374,7 @@ def election_results_text(election_alias):
stats=stats,
)
+
def process_vote(candidates, election, votes, revote, cand_name=None, value=None):
for index in range(len(candidates)):
candidate = candidates[index]
commit d33e5283a1897238e31916be0a3b027d1e1c377c
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:48:25 2016 +0100
Store locally the user's FAS name when adding or editing candidates
diff --git a/fedora_elections/admin.py b/fedora_elections/admin.py
index ad7f072..98c877c 100644
--- a/fedora_elections/admin.py
+++ b/fedora_elections/admin.py
@@ -238,9 +238,10 @@ def admin_add_candidate(election_alias):
form = forms.CandidateForm()
if form.validate_on_submit():
+ fas_name = None
if election.candidates_are_fasusers: # pragma: no cover
try:
- FAS2.person_by_username(form.name.data)['human_name']
+ fas_name = FAS2.person_by_username(form.name.data)['human_name']
except (KeyError, AuthError), err:
flask.flash(
'User `%s` does not have a FAS account.'
@@ -253,7 +254,8 @@ def admin_add_candidate(election_alias):
candidate = models.Candidate(
election=election,
name=form.name.data,
- url=form.url.data
+ url=form.url.data,
+ fas_name=fas_name,
)
SESSION.add(candidate)
@@ -291,9 +293,11 @@ def admin_add_multi_candidate(election_alias):
for entry in form.candidate.data.strip().split("|"):
candidate = entry.split("!")
+ fas_name = None
if election.candidates_are_fasusers: # pragma: no cover
try:
- FAS2.person_by_username(candidate[0])['human_name']
+ fas_name = FAS2.person_by_username(
+ candidate[0])['human_name']
except (KeyError, AuthError), err:
SESSION.rollback()
flask.flash(
@@ -308,7 +312,8 @@ def admin_add_multi_candidate(election_alias):
if len(candidate) == 1:
cand = models.Candidate(
election=election,
- name=candidate[0])
+ name=candidate[0],
+ fas_name=fas_name)
SESSION.add(cand)
candidates_name.append(cand.name)
# With url
@@ -316,7 +321,8 @@ def admin_add_multi_candidate(election_alias):
cand = models.Candidate(
election=election,
name=candidate[0],
- url=candidate[1])
+ url=candidate[1],
+ fas_name=fas_name)
SESSION.add(cand)
candidates_name.append(cand.name)
else:
@@ -357,6 +363,22 @@ def admin_edit_candidate(election_alias, candidate_id):
form = forms.CandidateForm(obj=candidate)
if form.validate_on_submit():
form.populate_obj(candidate)
+
+ fas_name = None
+ if election.candidates_are_fasusers: # pragma: no cover
+ try:
+ candidate.fas_name = FAS2.person_by_username(
+ candidate[0])['human_name']
+ except (KeyError, AuthError), err:
+ SESSION.rollback()
+ flask.flash(
+ 'User `%s` does not have a FAS account.'
+ % candidate[0], 'error')
+ return flask.redirect(flask.url_for(
+ 'admin_edit_candidate',
+ election_alias=election_alias,
+ candidate_id=candidate_id))
+
SESSION.commit()
flask.flash('Candidate "%s" saved' % candidate.name)
fedmsgshim.publish(
commit 10b484ebb7c437bd84a83ee221359c7e2f562e68
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Jan 21 16:47:55 2016 +0100
Add a fas_name field to the candidate table where the fas_name is stored
diff --git a/fedora_elections/models.py b/fedora_elections/models.py
index 31d6fea..e7d9d3d 100644
--- a/fedora_elections/models.py
+++ b/fedora_elections/models.py
@@ -263,6 +263,7 @@ class Candidate(BASE):
nullable=False)
# FAS username if candidates_are_fasusers
name = sa.Column(sa.Unicode(150), nullable=False)
+ fas_name = sa.Column(sa.Unicode(150), nullable=True)
url = sa.Column(sa.Unicode(250))
election = relationship(
commit 20889d67f5fc1f7f81ab5987fdf819e3093a44f9
Merge: 03d775b f132a47
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Thu Oct 8 09:57:42 2015 +0200
Merge pull request #55 from NerdsvilleCEO/fix_candidate_modification_bug
Candidate modification revote bug
commit f132a478397eebac23bba987a4aa323a75a907ef
Author: Joshua Santos <Nerdsville(a)nerdsville.net>
Date: Thu Oct 8 00:55:03 2015 -0700
Remove Trailing Spaces :)
diff --git a/tests/test_flask_range_voting.py b/tests/test_flask_range_voting.py
index 5107af2..494c6e5 100644
--- a/tests/test_flask_range_voting.py
+++ b/tests/test_flask_range_voting.py
@@ -312,7 +312,7 @@ class FlaskRangeElectionstests(ModelFlasktests):
self.assertEqual(votes[1].value, 0)
self.assertEqual(votes[2].value, 2)
#Let's not do repetition of what is tested above we aren't testing the
- #functionality of voting as that has already been asserted
+ #functionality of voting as that has already been asserted
obj = fedora_elections.models.Candidate( # id:16
election_id=3,
commit 7e54b8a9a5b74d3090848642a915d9b60157b654
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Sat Oct 3 21:39:19 2015 -0700
Add range voting revote candidate modification test
diff --git a/tests/test_flask_range_voting.py b/tests/test_flask_range_voting.py
index c18aca9..5107af2 100644
--- a/tests/test_flask_range_voting.py
+++ b/tests/test_flask_range_voting.py
@@ -312,13 +312,23 @@ class FlaskRangeElectionstests(ModelFlasktests):
self.assertEqual(votes[1].value, 0)
self.assertEqual(votes[2].value, 2)
#Let's not do repetition of what is tested above we aren't testing the
- #functionality of voting as that has already been asserted
+ #functionality of voting as that has already been asserted
+
+ obj = fedora_elections.models.Candidate( # id:16
+ election_id=3,
+ name='Josh',
+ url='https://fedoraproject.org/wiki/User:Nerdsville',
+ )
+ self.session.add(obj)
+ self.session.commit()
+
#Next, we need to try revoting
newdata = {
'4': 2,
'5': 1,
'6': 1,
+ '16': 0,
'action': 'submit',
'csrf_token': csrf_token,
}
@@ -336,6 +346,7 @@ class FlaskRangeElectionstests(ModelFlasktests):
self.assertEqual(votes[0].value, 2)
self.assertEqual(votes[1].value, 1)
self.assertEqual(votes[2].value, 1)
+ self.assertEqual(votes[3].value, 0)
#If we haven't failed yet, HOORAY!
commit 677dff9bb60e5827ef29e2d58517927f6dde8db5
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Fri Sep 25 14:48:12 2015 -0700
Fix logic to apply for any index
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 339645f..14b777c 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -374,7 +374,7 @@ def election_results_text(election_alias):
def process_vote(candidates, election, votes, revote, cand_name=None, value=None):
for index in range(len(candidates)):
candidate = candidates[index]
- if revote and (index+1 == len(votes)):
+ if revote and (index+1 <= len(votes)):
vote = votes[index]
if value is not None:
vote.candidate_id = candidate.data
commit 689aa799bd94fa2ed419868ddc17f818c8291b7b
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Fri Sep 25 14:30:21 2015 -0700
Candidate modification revote bug
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 4b65e75..339645f 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -374,7 +374,7 @@ def election_results_text(election_alias):
def process_vote(candidates, election, votes, revote, cand_name=None, value=None):
for index in range(len(candidates)):
candidate = candidates[index]
- if revote:
+ if revote and (index+1 == len(votes)):
vote = votes[index]
if value is not None:
vote.candidate_id = candidate.data
commit 03d775bf5b66b91a6569aafe026fcfad2fa1e28d
Merge: c4e93d5 49d2f75
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Fri Sep 25 10:26:15 2015 +0200
Merge pull request #54 from NerdsvilleCEO/add-simple-revote
Add simple revote
commit 49d2f75a3e57f6e543dbbc66f63b123cc347a67a
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Thu Sep 24 10:24:25 2015 -0700
Prefer UTC time over now()
diff --git a/fedora_elections/models.py b/fedora_elections/models.py
index b3e72cc..31d6fea 100644
--- a/fedora_elections/models.py
+++ b/fedora_elections/models.py
@@ -136,7 +136,7 @@ class Election(BASE):
@property
def locked(self):
- return datetime.now() >= self.start_date
+ return datetime.utcnow() >= self.start_date
@classmethod
def search(cls, session, alias=None, shortdesc=None,
commit f1fc0829ef765296d96252c595f8d320b438cdde
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Thu Sep 24 10:24:14 2015 -0700
Prefer UTC time over now()
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index c35a5d7..4b65e75 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -392,7 +392,7 @@ def process_vote(candidates, election, votes, revote, cand_name=None, value=None
new_vote = models.Vote(
election_id=election.id,
voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
+ timestamp=datetime.utcnow(),
candidate_id=cand_id,
value= value if value else int(candidate.data),
)
commit a526590d90408b738bb3346eb5a2611b4144e78d
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 16:36:11 2015 -0400
Cleanup
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 03c6821..c35a5d7 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -238,7 +238,7 @@ def vote_simple(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- process_vote(candidates, election, votes, revote, None, 1)
+ process_vote(candidates, election, votes, revote, value=1)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -376,13 +376,13 @@ def process_vote(candidates, election, votes, revote, cand_name=None, value=None
candidate = candidates[index]
if revote:
vote = votes[index]
- if value == 1:
+ if value is not None:
vote.candidate_id = candidate.data
else:
vote.value = value if value else int(candidate.data)
SESSION.add(vote)
else:
- if value == 1:
+ if value is not None:
cand_id = candidate.data
elif cand_name:
cand_id = cand_name[candidate.short_name]
commit 211eb0456f1d312ebf16f12833b87168508d75db
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 11:32:57 2015 -0400
Fix final failed test
diff --git a/tests/test_flask_elections.py b/tests/test_flask_elections.py
index 90a0230..fd24ce9 100644
--- a/tests/test_flask_elections.py
+++ b/tests/test_flask_elections.py
@@ -155,17 +155,6 @@ class FlaskElectionstests(ModelFlasktests):
'<input type="hidden" name="action" value="preview" />'
in output.data)
- user = FakeUser(['voters'], username='toshio')
- with user_set(fedora_elections.APP, user):
-
- # Election in progress
- output = self.app.get(
- '/vote/test_election3', follow_redirects=True)
- self.assertTrue(
- 'class="message">You have already voted in the election!</'
- in output.data)
- self.assertTrue('<h3>Current elections</h3>' in output.data)
-
def test_election_results(self):
""" Test the election_results function - the preview part. """
output = self.app.get(
commit 9abdca3fd5cc0343f5f5b32ef6a5f161e2d66590
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 11:28:00 2015 -0400
Further cleanup :)
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 6eac5f7..03c6821 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -200,7 +200,7 @@ def vote_select(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- process_vote_by_cand_name(candidates, cand_name, election, votes, revote)
+ process_vote(candidates, election, votes, revote, cand_name)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -238,22 +238,7 @@ def vote_simple(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- for index in range(len(candidates)):
- candidate = candidates[index]
- if revote:
- vote = votes[index]
- vote.candidate_id = candidate.data
- SESSION.add(vote)
- else:
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=candidate.data,
- value=1,
- )
- SESSION.add(new_vote)
- SESSION.commit()
+ process_vote(candidates, election, votes, revote, None, 1)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -290,7 +275,7 @@ def vote_irc(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- process_vote_by_cand_name(candidates, cand_name, election, votes, revote)
+ process_vote(candidates, election, votes, revote, cand_name)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -386,38 +371,30 @@ def election_results_text(election_alias):
stats=stats,
)
-def process_vote(candidates, election, votes, revote):
+def process_vote(candidates, election, votes, revote, cand_name=None, value=None):
for index in range(len(candidates)):
candidate = candidates[index]
if revote:
vote = votes[index]
- vote.value = int(candidate.data)
+ if value == 1:
+ vote.candidate_id = candidate.data
+ else:
+ vote.value = value if value else int(candidate.data)
SESSION.add(vote)
else:
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=candidate.short_name,
- value=int(candidate.data),
- )
- SESSION.add(new_vote)
- SESSION.commit()
+ if value == 1:
+ cand_id = candidate.data
+ elif cand_name:
+ cand_id = cand_name[candidate.short_name]
+ else:
+ cand_id = candidate.short_name
-def process_vote_by_cand_name(candidates, cand_name, election, votes, revote):
- for index in range(len(candidates)):
- candidate = candidates[index]
- if revote:
- vote = votes[index]
- vote.value = int(candidate.data)
- SESSION.add(vote)
- else:
new_vote = models.Vote(
election_id=election.id,
voter=flask.g.fas_user.username,
timestamp=datetime.now(),
- candidate_id=cand_name[candidate.short_name],
- value=int(candidate.data),
+ candidate_id=cand_id,
+ value= value if value else int(candidate.data),
)
SESSION.add(new_vote)
SESSION.commit()
commit 92ae688e1d2a907480d51b4417c33628941062af
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 10:49:36 2015 -0400
Else for revote logic
diff --git a/fedora_elections/templates/index.html b/fedora_elections/templates/index.html
index c944703..5d15ef8 100644
--- a/fedora_elections/templates/index.html
+++ b/fedora_elections/templates/index.html
@@ -32,10 +32,11 @@
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Vote now!
</a>
- {% endif %}
+ {% else %}
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Change your vote!
</a>
+ {% endif %}
{% endif %}
</td>
</tr>
commit 436ce71fe918cb7d47fa065964e0acc9217186ec
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 10:41:50 2015 -0400
Update tests
diff --git a/tests/test_flask_simple_voting.py b/tests/test_flask_simple_voting.py
index 1eaa339..c0ea957 100644
--- a/tests/test_flask_simple_voting.py
+++ b/tests/test_flask_simple_voting.py
@@ -55,14 +55,6 @@ class FlaskSimpleElectionstests(ModelFlasktests):
self.setup_db()
- user = FakeUser(['packager'], username='toshio')
- with user_set(fedora_elections.APP, user):
- output = self.app.get(
- '/vote/test_election5', follow_redirects=True)
- self.assertTrue(
- 'class="message">You have already voted in the election!</'
- in output.data)
-
user = FakeUser(['packager'], username='pingou')
with user_set(fedora_elections.APP, user):
output = self.app.get(
@@ -244,6 +236,52 @@ class FlaskSimpleElectionstests(ModelFlasktests):
self.assertTrue('<h3>Next 1 elections</h3>' in output.data)
self.assertTrue('<h3>Last 2 elections</h3>' in output.data)
+ def test_vote_simple_revote(self):
+ """ Test the vote_simple function - the re-voting part. """
+ #First we need to vote
+ self.setup_db()
+
+ user = FakeUser(['voters'], username='nerdsville')
+ with user_set(fedora_elections.APP, user):
+ retrieve_csrf = self.app.post('/vote/test_election5')
+ csrf_token = retrieve_csrf.data.split(
+ 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
+ # Valid input
+ data = {
+ 'candidate': 8,
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+
+ self.app.post('/vote/test_election5', data=data, follow_redirects=True)
+ vote = fedora_elections.models.Vote
+ votes = vote.of_user_on_election(self.session, "nerdsville", '5')
+ self.assertEqual(votes[0].candidate_id, 8)
+ #Let's not do repetition of what is tested above we aren't testing the
+ #functionality of voting as that has already been asserted
+
+ #Next, we need to try revoting
+ # Valid input
+ newdata = {
+ 'candidate': 9,
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+ output = self.app.post('/vote/test_election5', data=newdata, follow_redirects=True)
+ #Next, we need to check if the vote has been recorded
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ 'class="message">Your vote has been recorded. Thank you!</'
+ in output.data)
+ self.assertTrue('<h3>Current elections</h3>' in output.data)
+ self.assertTrue('<h3>Next 1 elections</h3>' in output.data)
+ self.assertTrue('<h3>Last 2 elections</h3>' in output.data)
+ vote = fedora_elections.models.Vote
+ votes = vote.of_user_on_election(self.session, "nerdsville", '5')
+ self.assertEqual(votes[0].candidate_id, 9)
+
+ #If we haven't failed yet, HOORAY!
+
if __name__ == '__main__':
SUITE = unittest.TestLoader().loadTestsFromTestCase(
commit 5e2964bdd72a8bc40b7707b67d44cd9549d32b12
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 10:41:40 2015 -0400
No need to check if revote exists anymore
diff --git a/fedora_elections/templates/index.html b/fedora_elections/templates/index.html
index abfcdd1..c944703 100644
--- a/fedora_elections/templates/index.html
+++ b/fedora_elections/templates/index.html
@@ -32,11 +32,10 @@
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Vote now!
</a>
- {% elif election.voting_type != "simple" %}
+ {% endif %}
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Change your vote!
</a>
- {% endif %}
{% endif %}
</td>
</tr>
commit f0660ec8291325607f2657c4ee077bae025afd81
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 10:39:20 2015 -0400
Add simple revoting
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 3ccc00e..6eac5f7 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -112,7 +112,7 @@ def vote(election_alias):
if election.voting_type.startswith('range'):
return vote_range(election, revote)
elif election.voting_type == 'simple':
- return vote_simple(election)
+ return vote_simple(election, revote)
elif election.voting_type == 'select':
return vote_select(election, revote)
elif election.voting_type == 'irc':
@@ -219,9 +219,9 @@ def vote_select(election, revote):
usernamemap=usernamemap,
nextaction=next_action)
-def vote_simple(election):
+def vote_simple(election, revote):
votes = models.Vote.of_user_on_election(
- SESSION, flask.g.fas_user.username, election.id, count=True)
+ SESSION, flask.g.fas_user.username, election.id)
num_candidates = election.candidates.count()
@@ -233,20 +233,27 @@ def vote_simple(election):
if form.validate_on_submit():
if form.action.data == 'submit':
- for candidate in form:
- if candidate.short_name in ['csrf_token', 'action']:
- continue
-
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=candidate.data,
- value=1,
- )
- SESSION.add(new_vote)
- SESSION.commit()
-
+ candidates = [
+ candidate
+ for candidate in form
+ if candidate and candidate.short_name not in ['csrf_token', 'action']
+ ]
+ for index in range(len(candidates)):
+ candidate = candidates[index]
+ if revote:
+ vote = votes[index]
+ vote.candidate_id = candidate.data
+ SESSION.add(vote)
+ else:
+ new_vote = models.Vote(
+ election_id=election.id,
+ voter=flask.g.fas_user.username,
+ timestamp=datetime.now(),
+ candidate_id=candidate.data,
+ value=1,
+ )
+ SESSION.add(new_vote)
+ SESSION.commit()
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
commit c4e93d5d01b0f1136423e60443741348f64c625a
Merge: 258625a b97dcc0
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Sep 1 16:37:11 2015 +0200
Merge pull request #52 from NerdsvilleCEO/refactor
Some cleanup/refactoring
commit b97dcc099fe54bf9a6cec86898423c61ac86049b
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 10:22:54 2015 -0400
Some cleanup/refactoring
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 2ca8800..3ccc00e 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -146,23 +146,7 @@ def vote_range(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- for index in range(len(candidates)):
- candidate = candidates[index]
- if revote:
- vote = votes[index]
- vote.value = candidate.data
- SESSION.add(vote)
- else:
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=candidate.short_name,
- value=candidate.data,
- )
- SESSION.add(new_vote)
- SESSION.commit()
-
+ process_vote(candidates, election, votes, revote)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -202,14 +186,12 @@ def vote_select(election, revote):
max_selection=max_selection)
if form.validate_on_submit():
-
- cnt = 0
- for candidate in form:
- if candidate.short_name in ['csrf_token', 'action']:
- continue
- if candidate.data:
- cnt += 1
- if cnt > max_selection:
+ cnt = [
+ candidate
+ for candidate in form
+ if candidate.data and candidate.short_name not in ['csrf_token', 'action']
+ ]
+ if len(cnt) > max_selection:
flask.flash('Too many candidates submitted', 'error')
else:
if form.action.data == 'submit':
@@ -218,22 +200,7 @@ def vote_select(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- for index in range(len(candidates)):
- candidate = candidates[index]
- if revote:
- vote = votes[index]
- vote.value = int(candidate.data)
- SESSION.add(vote)
- else:
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=cand_name[candidate.short_name],
- value=int(candidate.data),
- )
- SESSION.add(new_vote)
- SESSION.commit()
+ process_vote_by_cand_name(candidates, cand_name, election, votes, revote)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -252,7 +219,6 @@ def vote_select(election, revote):
usernamemap=usernamemap,
nextaction=next_action)
-
def vote_simple(election):
votes = models.Vote.of_user_on_election(
SESSION, flask.g.fas_user.username, election.id, count=True)
@@ -317,22 +283,7 @@ def vote_irc(election, revote):
for candidate in form
if candidate and candidate.short_name not in ['csrf_token', 'action']
]
- for index in range(len(candidates)):
- candidate = candidates[index]
- if revote:
- vote = votes[index]
- vote.value = int(candidate.data)
- SESSION.add(vote)
- else:
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=cand_name[candidate.short_name],
- value=int(candidate.data),
- )
- SESSION.add(new_vote)
- SESSION.commit()
+ process_vote_by_cand_name(candidates, cand_name, election, votes, revote)
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
@@ -427,3 +378,39 @@ def election_results_text(election_alias):
usernamemap=usernamemap,
stats=stats,
)
+
+def process_vote(candidates, election, votes, revote):
+ for index in range(len(candidates)):
+ candidate = candidates[index]
+ if revote:
+ vote = votes[index]
+ vote.value = int(candidate.data)
+ SESSION.add(vote)
+ else:
+ new_vote = models.Vote(
+ election_id=election.id,
+ voter=flask.g.fas_user.username,
+ timestamp=datetime.now(),
+ candidate_id=candidate.short_name,
+ value=int(candidate.data),
+ )
+ SESSION.add(new_vote)
+ SESSION.commit()
+
+def process_vote_by_cand_name(candidates, cand_name, election, votes, revote):
+ for index in range(len(candidates)):
+ candidate = candidates[index]
+ if revote:
+ vote = votes[index]
+ vote.value = int(candidate.data)
+ SESSION.add(vote)
+ else:
+ new_vote = models.Vote(
+ election_id=election.id,
+ voter=flask.g.fas_user.username,
+ timestamp=datetime.now(),
+ candidate_id=cand_name[candidate.short_name],
+ value=int(candidate.data),
+ )
+ SESSION.add(new_vote)
+ SESSION.commit()
commit 258625ae57f4205afa88fa111e8e929ae47b3465
Merge: 8dfa932 24d827d
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Tue Sep 1 15:20:55 2015 +0200
Merge pull request #51 from NerdsvilleCEO/add-irc-revote
Add irc revote
commit 24d827d00633b1320b6d6e1c8b7839eb094e5852
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 06:49:06 2015 -0400
Modify template condition
diff --git a/fedora_elections/templates/index.html b/fedora_elections/templates/index.html
index c796319..abfcdd1 100644
--- a/fedora_elections/templates/index.html
+++ b/fedora_elections/templates/index.html
@@ -32,7 +32,7 @@
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Vote now!
</a>
- {% elif election.voting_type == 'range' or election.voting_type == 'select' %}
+ {% elif election.voting_type != "simple" %}
<a href="{{ url_for('vote', election_alias=election.alias) }}">
Change your vote!
</a>
commit abb42bcbb8748f3df10a681d11095c351d6bfa7a
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 06:46:47 2015 -0400
Add IRC Revote tests
diff --git a/tests/test_flask_irc.py b/tests/test_flask_irc.py
index 9c45fa4..4fc6b69 100644
--- a/tests/test_flask_irc.py
+++ b/tests/test_flask_irc.py
@@ -55,14 +55,6 @@ class FlaskIrcElectionstests(ModelFlasktests):
self.setup_db()
- user = FakeUser(['packager'], username='toshio')
- with user_set(fedora_elections.APP, user):
- output = self.app.get(
- '/vote/test_election7', follow_redirects=True)
- self.assertTrue(
- 'class="message">You have already voted in the election!</'
- in output.data)
-
user = FakeUser(['packager'], username='nerdsville')
with user_set(fedora_elections.APP, user):
output = self.app.get(
@@ -151,6 +143,53 @@ class FlaskIrcElectionstests(ModelFlasktests):
self.assertTrue('<h3>Next 1 elections</h3>' in output.data)
self.assertTrue('<h3>Last 2 elections</h3>' in output.data)
+ def test_vote_irc_revote(self):
+ """ Test the vote_irc function - the re-voting part. """
+ #First we need to vote
+ self.setup_db()
+
+ user = FakeUser(['voters'], username='nerdsville')
+ with user_set(fedora_elections.APP, user):
+ retrieve_csrf = self.app.post('/vote/test_election7')
+ csrf_token = retrieve_csrf.data.split(
+ 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
+ # Valid input
+ data = {
+ 'Kevin': -1,
+ 'Toshio': 1,
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+ self.app.post('/vote/test_election7', data=data, follow_redirects=True)
+ vote = fedora_elections.models.Vote
+ votes = vote.of_user_on_election(self.session, "nerdsville", '7')
+ self.assertEqual(votes[0].value, 1)
+ self.assertEqual(votes[1].value, -1)
+ #Let's not do repetition of what is tested above we aren't testing the
+ #functionality of voting as that has already been asserted
+
+ #Next, we need to try revoting
+ newdata = {
+ 'Kevin': 1,
+ 'Toshio': -1,
+ 'action': 'submit',
+ 'csrf_token': csrf_token,
+ }
+ output = self.app.post('/vote/test_election7', data=newdata, follow_redirects=True)
+ #Next, we need to check if the vote has been recorded
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue(
+ 'class="message">Your vote has been recorded. Thank you!</'
+ in output.data)
+ self.assertTrue('<h3>Current elections</h3>' in output.data)
+ self.assertTrue('<h3>Next 1 elections</h3>' in output.data)
+ self.assertTrue('<h3>Last 2 elections</h3>' in output.data)
+ vote = fedora_elections.models.Vote
+ votes = vote.of_user_on_election(self.session, "nerdsville", '7')
+ self.assertEqual(votes[0].value, -1)
+ self.assertEqual(votes[1].value, 1)
+
+ #If we haven't failed yet, HOORAY!
if __name__ == '__main__':
SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskIrcElectionstests)
commit d1499f0d4a7a4df5f98b532de837aa7b1f1e9af8
Author: Joshua Santos <nerdsville(a)nerdsville.net>
Date: Tue Sep 1 06:46:28 2015 -0400
Add IRC Revoting
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index f37cbfa..2ca8800 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -116,7 +116,7 @@ def vote(election_alias):
elif election.voting_type == 'select':
return vote_select(election, revote)
elif election.voting_type == 'irc':
- return vote_irc(election)
+ return vote_irc(election, revote)
else: # pragma: no cover
flask.flash(
'Unknown election voting type: %s' % election.voting_type)
@@ -296,9 +296,9 @@ def vote_simple(election):
nextaction=next_action)
-def vote_irc(election):
+def vote_irc(election, revote):
votes = models.Vote.of_user_on_election(
- SESSION, flask.g.fas_user.username, election.id, count=True)
+ SESSION, flask.g.fas_user.username, election.id)
cand_name = {}
for candidate in election.candidates:
@@ -312,18 +312,27 @@ def vote_irc(election):
fasusers=election.candidates_are_fasusers)
if form.validate_on_submit():
if form.action.data == 'submit':
- for candidate in form:
- if candidate.short_name in ['csrf_token', 'action']:
- continue
- new_vote = models.Vote(
- election_id=election.id,
- voter=flask.g.fas_user.username,
- timestamp=datetime.now(),
- candidate_id=cand_name[candidate.short_name],
- value=candidate.data,
- )
- SESSION.add(new_vote)
- SESSION.commit()
+ candidates = [
+ candidate
+ for candidate in form
+ if candidate and candidate.short_name not in ['csrf_token', 'action']
+ ]
+ for index in range(len(candidates)):
+ candidate = candidates[index]
+ if revote:
+ vote = votes[index]
+ vote.value = int(candidate.data)
+ SESSION.add(vote)
+ else:
+ new_vote = models.Vote(
+ election_id=election.id,
+ voter=flask.g.fas_user.username,
+ timestamp=datetime.now(),
+ candidate_id=cand_name[candidate.short_name],
+ value=int(candidate.data),
+ )
+ SESSION.add(new_vote)
+ SESSION.commit()
flask.flash("Your vote has been recorded. Thank you!")
return safe_redirect_back()
8 years, 3 months