fedora_elections/__init__.py | 5 +++ fedora_elections/default_config.py | 7 ++++ fedora_elections/elections.py | 53 +++++++------------------------------ fedora_elections/forms.py | 2 - fedora_elections/utils.py | 30 ++++++++++++++++++++ requirements.txt | 1 tests/test_flask_elections.py | 1 tests/test_flask_range_voting.py | 3 +- tests/test_flask_select_voting.py | 3 +- tests/test_flask_simple_voting.py | 3 +- tests/test_vote.py | 10 +++--- 11 files changed, 66 insertions(+), 52 deletions(-)
New commits: commit 300f48a2ba7813b095cfe8be519aed11d7751cea Author: Pierre-Yves Chibon pingou@pingoured.fr Date: Thu Nov 20 11:52:46 2014 +0100
Add missing encoding information
diff --git a/fedora_elections/utils.py b/fedora_elections/utils.py index e6fd08c..66ce8cb 100644 --- a/fedora_elections/utils.py +++ b/fedora_elections/utils.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import fedora_elections
from fedora.client import AuthError
commit 0b8cc3a062d71c556447976dacea7ad31158024e Author: Pierre-Yves Chibon pingou@pingoured.fr Date: Thu Nov 20 11:52:39 2014 +0100
pep8 clean up
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py index b8f3d8d..9ec8df8 100644 --- a/fedora_elections/elections.py +++ b/fedora_elections/elections.py @@ -297,9 +297,9 @@ def vote_irc(election): num_candidates = election.candidates.count()
next_action = 'confirm' - form=forms.get_irc_voting_form( - candidates=election.candidates, - fasusers=election.candidates_are_fasusers) + form = forms.get_irc_voting_form( + candidates=election.candidates, + fasusers=election.candidates_are_fasusers) if form.validate_on_submit(): if form.action.data == 'submit': for candidate in form: @@ -351,7 +351,8 @@ def election_results(election_alias): "embargoed pending formal announcement.") return safe_redirect_back()
- if is_authenticated() and (is_admin(flask.g.fas_user) \ + if is_authenticated() and ( + is_admin(flask.g.fas_user) or is_election_admin(flask.g.fas_user, election.id)): flask.flash( "Check out the <a href='%s'>Text version</a> " @@ -370,6 +371,7 @@ def election_results(election_alias): stats=stats, )
+ @APP.route('/results/<election_alias>/text') def election_results_text(election_alias): election = get_valid_election(election_alias, ended=True) diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py index 7150564..2603973 100644 --- a/fedora_elections/forms.py +++ b/fedora_elections/forms.py @@ -167,7 +167,7 @@ def get_irc_voting_form(candidates, fasusers): for candidate in candidates: field = wtforms.SelectField( candidate.name, - choices=[('0',0),('1',1),('-1',-1)] + choices=[('0', 0), ('1', 1), ('-1', -1)] ) setattr(IrcVoting, candidate.name, field)
diff --git a/tests/test_flask_elections.py b/tests/test_flask_elections.py index 2d7c5d0..90a0230 100644 --- a/tests/test_flask_elections.py +++ b/tests/test_flask_elections.py @@ -361,7 +361,6 @@ candidates for running this elections! self.assertTrue('<h3>Current elections</h3>' in output.data)
- if __name__ == '__main__': SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskElectionstests) unittest.TextTestRunner(verbosity=2).run(SUITE) diff --git a/tests/test_flask_range_voting.py b/tests/test_flask_range_voting.py index 0cc94fd..d0be838 100644 --- a/tests/test_flask_range_voting.py +++ b/tests/test_flask_range_voting.py @@ -298,5 +298,6 @@ class FlaskRangeElectionstests(ModelFlasktests):
if __name__ == '__main__': - SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskRangeElectionstests) + SUITE = unittest.TestLoader().loadTestsFromTestCase( + FlaskRangeElectionstests) unittest.TextTestRunner(verbosity=2).run(SUITE) diff --git a/tests/test_flask_select_voting.py b/tests/test_flask_select_voting.py index cc248b3..73d2ca0 100644 --- a/tests/test_flask_select_voting.py +++ b/tests/test_flask_select_voting.py @@ -170,5 +170,6 @@ class FlaskSimpleElectionstests(ModelFlasktests):
if __name__ == '__main__': - SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskSimpleElectionstests) + SUITE = unittest.TestLoader().loadTestsFromTestCase( + FlaskSimpleElectionstests) unittest.TextTestRunner(verbosity=2).run(SUITE) diff --git a/tests/test_flask_simple_voting.py b/tests/test_flask_simple_voting.py index aa28980..1eaa339 100644 --- a/tests/test_flask_simple_voting.py +++ b/tests/test_flask_simple_voting.py @@ -246,5 +246,6 @@ class FlaskSimpleElectionstests(ModelFlasktests):
if __name__ == '__main__': - SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskSimpleElectionstests) + SUITE = unittest.TestLoader().loadTestsFromTestCase( + FlaskSimpleElectionstests) unittest.TextTestRunner(verbosity=2).run(SUITE) diff --git a/tests/test_vote.py b/tests/test_vote.py index 8d15279..92f1e71 100644 --- a/tests/test_vote.py +++ b/tests/test_vote.py @@ -178,11 +178,11 @@ class Votetests(Modeltests):
# Election 7
- obj = models.Vote( #id:1 - election_id=7, - voter='toshio', - candidate_id=12, - value='1', + obj = models.Vote( # id:1 + election_id=7, + voter='toshio', + candidate_id=12, + value='1', ) self.session.add(obj) self.session.commit()
commit 9b299fa5a70ff8abc1dccdce62354a135a14d17d Merge: 6ff26d1 6eca259 Author: Pierre-Yves Chibon pingou@pingoured.fr Date: Thu Nov 20 11:47:52 2014 +0100
Merge pull request #36 from fedora-infra/feature/cache
Use dogpile.cache to vastly speed up the app.
commit 6eca25955d33d427bd6893705deeb9876dc58e2f Author: Ralph Bean rbean@redhat.com Date: Mon Nov 17 20:57:39 2014 -0500
Use dogpile.cache to vastly speed up the app.
Currently, every page load in the voting process requires that the elections make ``N`` queries to FAS where ``N`` is the number of candidates. It's being really slow in production tonight with the opening of the Council election.
This should add some generic caching so that we can use an on-disk .dbm cache if we like or alternatively memcached.
Tested locally.
diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py index 131f320..0cde879 100644 --- a/fedora_elections/__init__.py +++ b/fedora_elections/__init__.py @@ -38,6 +38,8 @@ from fedora.client import AuthError, AppError from fedora.client.fas2 import AccountSystem from flask.ext.fas_openid import FAS
+import dogpile.cache + import fedora_elections.fedmsgshim import fedora_elections.proxy
@@ -64,6 +66,9 @@ 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']) +
def is_authenticated(): ''' Return a boolean specifying if the user is authenticated or not. diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py index 979dd9d..e887840 100644 --- a/fedora_elections/default_config.py +++ b/fedora_elections/default_config.py @@ -22,3 +22,10 @@ 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', + }, +} diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py index 2ad0e1e..b8f3d8d 100644 --- a/fedora_elections/elections.py +++ b/fedora_elections/elections.py @@ -37,6 +37,7 @@ from fedora_elections import ( APP, SESSION, FAS2, is_authenticated, is_admin, is_election_admin, is_safe_url, safe_redirect_back, ) +from fedora_elections.utils import build_name_map
def login_required(f): @@ -166,16 +167,7 @@ def vote_range(election): flask.flash("Please confirm your vote!") next_action = 'vote'
- usernamemap = {} - if (election.candidates_are_fasusers): # pragma: no cover - for candidate in election.candidates: - try: - usernamemap[str(candidate.id)] = \ - FAS2.person_by_username(candidate.name)['human_name'] - except (KeyError, AuthError), err: - APP.logger.debug(err) - # User has their name set to private or user doesn't exist. - usernamemap[str(candidate.id)] = candidate.name + usernamemap = build_name_map(election)
return flask.render_template( 'vote_range.html', @@ -239,16 +231,7 @@ def vote_select(election): flask.flash("Please confirm your vote!") next_action = 'vote'
- usernamemap = {} - if (election.candidates_are_fasusers): # pragma: no cover - for candidate in election.candidates: - try: - usernamemap[candidate.name] = \ - FAS2.person_by_username(candidate.name)['human_name'] - except (KeyError, AuthError), err: - APP.logger.debug(err) - # User has their name set to private or user doesn't exist. - usernamemap[candidate.name] = candidate.name + usernamemap = build_name_map(election)
return flask.render_template( 'vote_simple.html', @@ -376,15 +359,7 @@ def election_results(election_alias): 'election_results_text', election_alias=election.alias) )
- usernamemap = {} - if (election.candidates_are_fasusers): # pragma: no cover - for candidate in election.candidates: - try: - usernamemap[candidate.id] = \ - FAS2.person_by_username(candidate.name)['human_name'] - except (KeyError, AuthError): - # User has their name set to private or user doesn't exist. - usernamemap[candidate.id] = candidate.name + usernamemap = build_name_map(election)
stats = models.Vote.get_election_stats(SESSION, election.id)
@@ -408,15 +383,7 @@ def election_results_text(election_alias): "The text results are only available to the admins", "error") return safe_redirect_back()
- usernamemap = {} - if (election.candidates_are_fasusers): # pragma: no cover - for candidate in election.candidates: - try: - usernamemap[candidate.id] = \ - FAS2.person_by_username(candidate.name)['human_name'] - except (KeyError, AuthError): - # User has their name set to private or user doesn't exist. - usernamemap[candidate.id] = candidate.name + usernamemap = build_name_map(election)
stats = models.Vote.get_election_stats(SESSION, election.id)
diff --git a/fedora_elections/utils.py b/fedora_elections/utils.py new file mode 100644 index 0000000..e6fd08c --- /dev/null +++ b/fedora_elections/utils.py @@ -0,0 +1,28 @@ +import fedora_elections + +from fedora.client import AuthError + + +def build_name_map(election): + """ Returns a mapping of candidate ids to fas human_names. """ + if not election.candidates_are_fasusers: + return {} + + return dict([ + (str(candidate.id), get_fas_human_name(candidate.name)) + for candidate in election.candidates + ]) + + +@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 diff --git a/requirements.txt b/requirements.txt index 7bff0c9..a62a392 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ python-openid-cla python-openid-teams SQLAlchemy wtforms +dogpile.cache
elections-devel@lists.stg.fedorahosted.org