From 318d443010954e4da6f0c5e2b8b536e8e9fb058f Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:01:33 +0000
Subject: [PATCH 1/7] Port elections to python3


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py
index 81e4b36..00ff7fa 100644
--- a/fedora_elections/__init__.py
+++ b/fedora_elections/__init__.py
@@ -23,6 +23,7 @@
 #                   Frank Chiulli <fchiulli@fedoraproject.org>
 #                   Pierre-Yves Chibon <pingou@fedoraproject.org>
 #
+from __future__ import unicode_literals, absolute_import
 
 __version__ = '2.7'
 
@@ -36,10 +37,11 @@ import arrow  # noqa
 
 from datetime import datetime, time, timedelta  # noqa
 from functools import wraps  # noqa
-from urlparse import urlparse, urljoin  # noqa
+from six.moves.urllib.parse import urlparse, urljoin, urlencode  # noqa
 
 import flask  # noqa
 import munch  # noqa
+import six  # noqa
 
 from fedora.client import AuthError, AppError  # noqa
 from fedora.client.fas2 import AccountSystem  # noqa
@@ -126,7 +128,7 @@ def is_admin(user, user_groups=None):
         return False
 
     admins = APP.config['FEDORA_ELECTIONS_ADMIN_GROUP']
-    if isinstance(admins, basestring):  # pragma: no cover
+    if isinstance(admins, six.string_types):  # pragma: no cover
         admins = set([admins])
     else:
         admins = set(admins)
@@ -189,7 +191,8 @@ def rjust_filter(text, length):
 
 @APP.template_filter('avatar')
 def avatar_filter(openid, size=64, default='retro'):
-    query = urllib.urlencode({'s': size, 'd': default})
+    query = urlencode({'s': size, 'd': default})
+    openid = openid.encode("utf-8")
     hashhex = hashlib.sha256(openid).hexdigest()
     return "https://seccdn.libravatar.org/avatar/%s?%s" % (hashhex, query)
 
@@ -344,5 +347,5 @@ def auth_logout():
 
 
 # Finalize the import of other controllers
-import admin  # noqa
-import elections  # noqa
+import fedora_elections.admin  # noqa
+import fedora_elections.elections  # noqa
diff --git a/fedora_elections/admin.py b/fedora_elections/admin.py
index c34694d..beab90e 100644
--- a/fedora_elections/admin.py
+++ b/fedora_elections/admin.py
@@ -23,6 +23,7 @@
 #                   Frank Chiulli <fchiulli@fedoraproject.org>
 #                   Pierre-Yves Chibon <pingou@fedoraproject.org>
 #
+from __future__ import unicode_literals, absolute_import
 
 from datetime import datetime, time
 from functools import wraps
diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py
index 6799bf6..938cb53 100644
--- a/fedora_elections/default_config.py
+++ b/fedora_elections/default_config.py
@@ -5,6 +5,7 @@ Fedora elections default configuration.
 '''
 import os
 from datetime import timedelta
+from fedora_elections.mail_logging import MSG_FORMAT, ContextInjector
 
 # Set the time after which the session expires
 PERMANENT_SESSION_LIFETIME = timedelta(hours=1)
@@ -25,6 +26,6 @@ FAS_CHECK_CERT = False
 
 
 OIDC_CLIENT_SECRETS = os.path.join(os.path.dirname(
-    os.path.abspath(__file__)), 'client_secrets.json')
+    os.path.abspath(__file__)), '..', 'client_secrets.json')
 OIDC_SCOPES = ['openid', 'email', 'profile', 'fedora']
 OIDC_OPENID_REALM = 'http://localhost:5005/oidc_callback'
diff --git a/fedora_elections/elections.py b/fedora_elections/elections.py
index 41a2804..a4c98c7 100644
--- a/fedora_elections/elections.py
+++ b/fedora_elections/elections.py
@@ -23,6 +23,7 @@
 #                   Frank Chiulli <fchiulli@fedoraproject.org>
 #                   Pierre-Yves Chibon <pingou@fedoraproject.org>
 #
+from __future__ import unicode_literals, absolute_import
 
 from datetime import datetime
 from functools import wraps
diff --git a/fedora_elections/fedmsgshim.py b/fedora_elections/fedmsgshim.py
index 1285b34..0336d16 100644
--- a/fedora_elections/fedmsgshim.py
+++ b/fedora_elections/fedmsgshim.py
@@ -4,6 +4,7 @@
   :Author: Pierre-Yves Chibon <pingou@pingoured.fr>
 
 """
+from __future__ import unicode_literals, absolute_import
 
 import warnings
 import logging
diff --git a/fedora_elections/forms.py b/fedora_elections/forms.py
index 1c3fb75..8fc90b0 100644
--- a/fedora_elections/forms.py
+++ b/fedora_elections/forms.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import unicode_literals, absolute_import
 
 import flask
 import wtforms
diff --git a/fedora_elections/mail_logging.py b/fedora_elections/mail_logging.py
index 39562ad..c990b0e 100644
--- a/fedora_elections/mail_logging.py
+++ b/fedora_elections/mail_logging.py
@@ -22,6 +22,8 @@
 '''
 Mail handler for logging.
 '''
+from __future__ import unicode_literals, absolute_import
+
 import logging
 import logging.handlers
 
diff --git a/fedora_elections/models.py b/fedora_elections/models.py
index b82af00..b447bb6 100644
--- a/fedora_elections/models.py
+++ b/fedora_elections/models.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import unicode_literals, absolute_import
 
 from datetime import datetime
 
diff --git a/fedora_elections/proxy.py b/fedora_elections/proxy.py
index 8e2e6b1..e53890f 100644
--- a/fedora_elections/proxy.py
+++ b/fedora_elections/proxy.py
@@ -25,6 +25,7 @@ redirects are using ``https``.
 
 Source: http://flask.pocoo.org/snippets/35/ by Peter Hansen
 '''
+from __future__ import unicode_literals, absolute_import
 
 
 class ReverseProxied(object):
diff --git a/fedora_elections/utils.py b/fedora_elections/utils.py
index 4bf23d1..c90460a 100644
--- a/fedora_elections/utils.py
+++ b/fedora_elections/utils.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import unicode_literals, absolute_import
 
 import fedora_elections
 
diff --git a/tests/__init__.py b/tests/__init__.py
index 68b0a3a..49b1449 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -34,6 +34,7 @@ from datetime import date
 from datetime import timedelta
 from functools import wraps
 
+import six
 from contextlib import contextmanager
 from sqlalchemy import create_engine
 from sqlalchemy.orm import sessionmaker
@@ -117,7 +118,7 @@ class ModelFlasktests(Modeltests):
     def setup_db(self):
         """ Add a calendar and some meetings so that we can play with
         something. """
-        from test_vote import Votetests
+        from tests.test_vote import Votetests
         votes = Votetests('test_init_vote')
         votes.session = self.session
         votes.test_init_vote()
@@ -184,7 +185,7 @@ class FakeUser(object):
         :arg groups: list of the groups in which this fake user is
             supposed to be.
         """
-        if isinstance(groups, basestring):
+        if isinstance(groups, six.string_types):
             groups = [groups]
         self.groups = groups
         self.username = username
diff --git a/tests/test_candidate.py b/tests/test_candidate.py
index 90bdc08..aab8751 100644
--- a/tests/test_candidate.py
+++ b/tests/test_candidate.py
@@ -35,7 +35,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 from fedora_elections import models
 from tests import Modeltests, TODAY
-from test_election import Electiontests
+from tests.test_election import Electiontests
 
 
 # pylint: disable=R0904
diff --git a/tests/test_vote.py b/tests/test_vote.py
index 92f1e71..1f9adac 100644
--- a/tests/test_vote.py
+++ b/tests/test_vote.py
@@ -35,7 +35,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(
 
 from fedora_elections import models
 from tests import Modeltests, TODAY
-from test_candidate import Candidatetests
+from tests.test_candidate import Candidatetests
 
 
 # pylint: disable=R0904

From f2569cff1be2705596bf77ae53f747f4c438aa97 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:01:49 +0000
Subject: [PATCH 2/7] Port the tests to python3


---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index 1899954..0645662 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -64,51 +64,57 @@ class Flasktests(ModelFlasktests):
         """ Test the index function. """
         output = self.app.get('/')
         self.assertEqual(output.status_code, 200)
-        self.assertTrue('<title>Fedora elections</title>' in output.data)
-        self.assertFalse('<h3>Current elections</h3>' in output.data)
-        self.assertFalse('<h3>Next' in output.data)
-        self.assertFalse('<h3>Last' in output.data)
-        self.assertTrue('<a href="/login">Log In</a>' in output.data)
+        output_text = output.get_data(as_text=True)
+        self.assertIn('<title>Fedora elections</title>', output_text)
+        self.assertNotIn('<h3>Current elections</h3>', output_text)
+        self.assertNotIn('<h3>Next', output_text)
+        self.assertNotIn('<h3>Last', output_text)
+        self.assertIn('<a href="/login">Log In</a>', output_text)
 
         user = FakeUser([], username='pingou')
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<title>Fedora elections</title>' in output.data)
-            self.assertTrue(
-                '<a class="dropdown-item" href="/logout">log out</a>' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertIn('<title>Fedora elections</title>', output_text)
+            self.assertIn(
+                '<a class="dropdown-item" href="/logout">log out</a>',
+                output_text)
 
     def test_index_filled(self):
         """ Test the index function. """
         self.setup_db()
         output = self.app.get('/')
         self.assertEqual(output.status_code, 200)
-        self.assertTrue('<h2>Elections' in output.data)
-        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
-        self.assertTrue('<a href="/login">Log In</a>' in output.data)
+        output_text = output.get_data(as_text=True)
+        self.assertTrue('<h2>Elections' in output_text)
+        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
+        self.assertTrue('<a href="/login">Log In</a>' in output_text)
 
         user = FakeUser([], username='pingou')
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/')
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<h2>Elections' in output.data)
-            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
-            self.assertTrue('<a class="btn btn-sm btn-primary m-l-2" href="/vote/' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<h2>Elections' in output_text)
+            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
+            self.assertTrue('<a class="btn btn-sm btn-primary m-l-2" href="/vote/' in output_text)
             self.assertTrue(
-                '<a class="dropdown-item" href="/logout">log out</a>' in output.data)
-            self.assertEqual(output.data.count('Vote now!'), 4)
+                '<a class="dropdown-item" href="/logout">log out</a>' in output_text)
+            self.assertEqual(output_text.count('Vote now!'), 4)
 
         user = FakeUser([], username='toshio')
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/')
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<h2>Elections' in output.data)
-            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<h2>Elections' in output_text)
+            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
             self.assertTrue(
-                '<a class="dropdown-item" href="/logout">log out</a>' in output.data)
+                '<a class="dropdown-item" href="/logout">log out</a>' in output_text)
 
     def test_is_admin(self):
         """ Test the is_admin function. """
@@ -208,15 +214,17 @@ class Flasktests(ModelFlasktests):
             flask.g.fas_user = FakeUser(['gitr2spec'])
             output = self.app.get('/login')
             self.assertEqual(output.status_code, 302)
+            output_text = output.get_data(as_text=True)
             self.assertIn(
                 'https://iddev.fedorainfracloud.org/openidc/Authorization?',
-                output.data)
+                output_text)
 
             output = self.app.get('/login?next=http://localhost/')
             self.assertEqual(output.status_code, 302)
+            output_text = output.get_data(as_text=True)
             self.assertIn(
                 'https://iddev.fedorainfracloud.org/openidc/Authorization?',
-                output.data)
+                output_text)
 
         # self.setup_db()
         # user = FakeUser([], username='pingou')
@@ -232,19 +240,21 @@ class Flasktests(ModelFlasktests):
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/logout', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<title>Fedora elections</title>' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<title>Fedora elections</title>' in output_text)
             self.assertTrue(
                 'You have been logged out'
-                in output.data)
+                in output_text)
 
         user = None
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/logout', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<title>Fedora elections</title>' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<title>Fedora elections</title>' in output_text)
             self.assertFalse(
                 'You have been logged out'
-                in output.data)
+                in output_text)
 
     def test_about_election(self):
         """ Test the about_election function. """
@@ -259,26 +269,28 @@ class Flasktests(ModelFlasktests):
         #we get redirected to the main page.
         output = self.app.get('/about/blah', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'The election, blah,  does not exist.'
-            in output.data)
-        self.assertTrue('<h2>Elections' in output.data)
-        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
+            in output_text)
+        self.assertTrue('<h2>Elections' in output_text)
+        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
 
         #test_election does exist, so check if it shows
         # with the correct candidates
         output = self.app.get('/about/test_election')
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
-            '<title>Election Information</title>' in output.data)
+            '<title>Election Information</title>' in output_text)
         self.assertTrue(
             '<a href="https://fedoraproject.org/wiki/User:Toshio">'
-             in output.data)
+             in output_text)
         self.assertTrue(
             '<a href="https://fedoraproject.org/wiki/User:Ralph">'
-            in output.data)
-        self.assertTrue('<a href="/login">Log In</a>' in output.data)
+            in output_text)
+        self.assertTrue('<a href="/login">Log In</a>' in output_text)
 
     def test_archived_election(self):
         """ Test the archived_elections function. """
@@ -287,23 +299,25 @@ class Flasktests(ModelFlasktests):
 
         output = self.app.get('/archives', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'There are no archived elections.'
-            in output.data)
-        self.assertTrue('<title>Fedora elections</title>' in output.data)
-        self.assertTrue('<h2>Elections' in output.data)
+            in output_text)
+        self.assertTrue('<title>Fedora elections</title>' in output_text)
+        self.assertTrue('<h2>Elections' in output_text)
 
         self.setup_db()
 
         output = self.app.get('/archives')
         self.assertEqual(output.status_code, 200)
-        self.assertTrue('<title>Fedora elections</title>' in output.data)
+        output_text = output.get_data(as_text=True)
+        self.assertTrue('<title>Fedora elections</title>' in output_text)
         self.assertTrue(
-            'test election 2 shortdesc' in output.data)
+            'test election 2 shortdesc' in output_text)
         self.assertTrue(
-            'test election shortdesc' in output.data)
-        self.assertEqual(output.data.count('href="/about/'), 2)
-        self.assertTrue('<a href="/login">Log In</a>' in output.data)
+            'test election shortdesc' in output_text)
+        self.assertEqual(output_text.count('href="/about/'), 2)
+        self.assertTrue('<a href="/login">Log In</a>' in output_text)
 
     def test_open_elections(self):
         """ Test the open_elections function. """
@@ -311,33 +325,36 @@ class Flasktests(ModelFlasktests):
 
         output = self.app.get('/')
         self.assertEqual(output.status_code, 200)
-        self.assertTrue('<h2>Elections' in output.data)
-        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
-        self.assertTrue('href="/vote/' in output.data)
-        self.assertTrue('<a href="/login">Log In</a>' in output.data)
+        output_text = output.get_data(as_text=True)
+        self.assertTrue('<h2>Elections' in output_text)
+        self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+        self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
+        self.assertTrue('href="/vote/' in output_text)
+        self.assertTrue('<a href="/login">Log In</a>' in output_text)
 
         user = FakeUser([], username='pingou')
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/')
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<h2>Elections' in output.data)
-            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
-            self.assertTrue('href="/vote/' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<h2>Elections' in output_text)
+            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
+            self.assertTrue('href="/vote/' in output_text)
             self.assertTrue(
-                '<a class="dropdown-item" href="/logout">log out</a>' in output.data)
-            self.assertEqual(output.data.count('Vote now!'), 4)
+                '<a class="dropdown-item" href="/logout">log out</a>' in output_text)
+            self.assertEqual(output_text.count('Vote now!'), 4)
 
         user = FakeUser([], username='toshio')
         with user_set(fedora_elections.APP, user):
             output = self.app.get('/')
             self.assertEqual(output.status_code, 200)
-            self.assertTrue('<h2>Elections' in output.data)
-            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output.data)
-            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output.data)
+            output_text = output.get_data(as_text=True)
+            self.assertTrue('<h2>Elections' in output_text)
+            self.assertTrue('<h4><strong>Open elections</strong></h4>' in output_text)
+            self.assertTrue('<strong>Upcoming elections</strong></h4>' in output_text)
             self.assertTrue(
-                '<a class="dropdown-item" href="/logout">log out</a>' in output.data)
+                '<a class="dropdown-item" href="/logout">log out</a>' in output_text)
 
 if __name__ == '__main__':
     SUITE = unittest.TestLoader().loadTestsFromTestCase(Flasktests)
diff --git a/tests/test_flask_admin.py b/tests/test_flask_admin.py
index 45ebcc6..468d24d 100644
--- a/tests/test_flask_admin.py
+++ b/tests/test_flask_admin.py
@@ -65,8 +65,9 @@ class FlaskAdmintests(ModelFlasktests):
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['elections'])):
                 output = self.app.get('/admin/test_election/')
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output.data)
+                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output_text)
 
     def test_admin_no_cla(self):
         """ Test the admin_new_election function. """
@@ -98,16 +99,17 @@ class FlaskAdmintests(ModelFlasktests):
                     MagicMock(return_value=['elections'])):
                 output = self.app.get('/admin/new')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
 
                 # No csrf provided
                 data = {
@@ -125,16 +127,17 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
 
                 csrf_token = self.get_csrf(output=output)
 
@@ -154,19 +157,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">This field is required.</div>'
-                    in output.data)
+                    in output_text)
 
                 # Invalid alias
                 data = {
@@ -185,19 +189,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">The alias cannot be <code>new</code>.</div>'
-                    in output.data)
+                    in output_text)
 
                 # Invalid: end_date earlier than start_date
                 data = {
@@ -216,19 +221,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertTrue(
                     'class="form-control-feedback">End date must be later than start date.</div>'
-                    in output.data)
+                    in output_text)
 
                 # Invalid: alias already taken
                 data = {
@@ -247,19 +253,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">There is already another election with '
-                    'this alias.</div>' in output.data)
+                    'this alias.</div>' in output_text)
 
                 # Invalid: shortdesc already taken
                 data = {
@@ -278,19 +285,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/new', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    '<h2>Create new election</h2>' in output.data)
+                    '<h2>Create new election</h2>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">There is already another election with '
-                    'this summary.</div>' in output.data)
+                    'this summary.</div>' in output_text)
 
                 # All good  -  max_votes is ignored as it is not a integer
                 data = {
@@ -313,23 +321,24 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/new', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "new_election" added'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
-                    'There are no candidates.' in output.data)
+                    'There are no candidates.' in output_text)
                 self.assertIn(
                     'input class="form-control" id="admin_grp" '
                     'name="admin_grp" type="text" '
-                    'value="sysadmin-main, testers">', output.data)
+                    'value="sysadmin-main, testers">', output_text)
                 self.assertIn(
                     'input class="form-control" id="lgl_voters" '
                     'name="lgl_voters" type="text" '
-                    'value="packager, testers">', output.data)
+                    'value="packager, testers">', output_text)
                 self.assertIn(
                     'input class="form-control" id="max_votes" '
                     'name="max_votes" type="text" '
-                    'value="">', output.data)
+                    'value="">', output_text)
 
                 # All good  -  max_votes is ignored as it is not a integer
                 data = {
@@ -351,23 +360,24 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/new', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "new_election2" added'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
-                    'There are no candidates.' in output.data)
+                    'There are no candidates.' in output_text)
                 self.assertIn(
                     'input class="form-control" id="admin_grp" '
                     'name="admin_grp" type="text" '
-                    'value="sysadmin-main, testers">', output.data)
+                    'value="sysadmin-main, testers">', output_text)
                 self.assertIn(
                     'input class="form-control" id="lgl_voters" '
                     'name="lgl_voters" type="text" '
-                    'value="packager, testers">', output.data)
+                    'value="packager, testers">', output_text)
                 self.assertIn(
                     'input class="form-control" id="max_votes" '
                     'name="max_votes" type="text" '
-                    'value="">', output.data)
+                    'value="">', output_text)
 
     def test_admin_edit_election(self):
         """ Test the admin_edit_election function. """
@@ -390,16 +400,17 @@ class FlaskAdmintests(ModelFlasktests):
                     MagicMock(return_value=['elections'])):
                 output = self.app.get('/admin/test_election/')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'Election Details' in output.data)
+                    'Election Details' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
 
                 data = {
                     'alias': 'test_election',
@@ -416,16 +427,17 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.post('/admin/test_election/', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'Election Details' in output.data)
+                    'Election Details' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
 
                 csrf_token = self.get_csrf()
 
@@ -444,34 +456,36 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'Election Details' in output.data)
+                    'Election Details' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" required type="text" ', output.data)
+                        'name="shortdesc" required type="text" ', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="shortdesc" '
-                        'name="shortdesc" type="text" ', output.data)
+                        'name="shortdesc" type="text" ', output_text)
                 self.assertIn(
                     '<div class="form-control-feedback">This field is required.</div>',
-                    output.data)
+                    output_text)
 
                 # Check election before edit
                 output = self.app.get('/admin/test_election/')
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" '
-                        'value="1">', output.data)
+                        'value="1">', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" '
-                        'value="1">', output.data)
+                        'value="1">', output_text)
 
                 data = {
                     'alias': 'test_election',
@@ -491,21 +505,22 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "test_election" saved'
-                    in output.data)
+                    in output_text)
                 # We edited the seats_elected from 1 to 2
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" '
-                        'value="2">', output.data)
+                        'value="2">', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" '
-                        'value="2">', output.data)
-                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output.data)
+                        'value="2">', output_text)
+                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output_text)
 
     def test_admin_edit_election_admin_groups(self):
         """ Test the admin_edit_election function when editing admin groups.
@@ -536,17 +551,18 @@ class FlaskAdmintests(ModelFlasktests):
                 # Check election before edit
                 output = self.app.get('/admin/test_election2/')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" '
-                        'value="1">', output.data)
+                        'value="1">', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" '
-                        'value="1">', output.data)
-                self.assertTrue('Candidates <span class="label' in output.data)
+                        'value="1">', output_text)
+                self.assertTrue('Candidates <span class="label' in output_text)
 
                 # Add a new admin group: sysadmin-main
                 data = {
@@ -567,24 +583,25 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election2/', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "test_election2" saved'
-                    in output.data)
+                    in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" '
-                        'value="2">', output.data)
+                        'value="2">', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" '
-                        'value="2">', output.data)
+                        'value="2">', output_text)
                 # We edited the admin groups
                 self.assertIn(
                     'input class="form-control" id="admin_grp" '
                     'name="admin_grp" type="text" '
-                    'value="sysadmin-main, testers">', output.data)
+                    'value="sysadmin-main, testers">', output_text)
 
                 # Remove an existing group: testers
                 data = {
@@ -605,24 +622,25 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election2/', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "test_election2" saved'
-                    in output.data)
+                    in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" '
-                        'value="2">', output.data)
+                        'value="2">', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" '
-                        'value="2">', output.data)
+                        'value="2">', output_text)
                 # We edited the admin groups
                 self.assertIn(
                     'input class="form-control" id="admin_grp" '
                     'name="admin_grp" type="text" '
-                    'value="sysadmin-main">', output.data)
+                    'value="sysadmin-main">', output_text)
 
     def test_admin_edit_election_legal_voters(self):
         """ Test the admin_edit_election function when editing legal voters.
@@ -652,23 +670,24 @@ class FlaskAdmintests(ModelFlasktests):
                 # Check election before edit
                 output = self.app.get('/admin/test_election3/')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
-                        'name="seats_elected" required type="text"', output.data)
+                        'name="seats_elected" required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
-                        'name="seats_elected" type="text"', output.data)
+                        'name="seats_elected" type="text"', output_text)
                 self.assertTrue('Candidates <span class="label'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     '<input class="form-control" id="admin_grp" name="admin_grp" type="text" value="">'
-                    in output.data)
+                    in output_text)
                 self.assertIn(
                     'input class="form-control" id="lgl_voters" '
                     'name="lgl_voters" type="text" value="voters">',
-                    output.data)
+                    output_text)
 
                 # Add a new admin group: sysadmin-main
                 data = {
@@ -689,14 +708,15 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election3/', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "test_election3" saved'
-                    in output.data)
+                    in output_text)
                 # We edited the legal_voters
                 self.assertIn(
                     'input class="form-control" id="lgl_voters" '
                     'name="lgl_voters" type="text" '
-                    'value="sysadmin-main, voters">', output.data)
+                    'value="sysadmin-main, voters">', output_text)
 
                 # Remove an existing group: voters
                 data = {
@@ -717,14 +737,15 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election3/', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Election "test_election3" saved'
-                    in output.data)
+                    in output_text)
                 # We edited the legal_voters
                 self.assertIn(
                     'input class="form-control" id="lgl_voters" '
                     'name="lgl_voters" type="text" '
-                    'value="sysadmin-main">', output.data)
+                    'value="sysadmin-main">', output_text)
 
     def test_admin_add_candidate(self):
         """ Test the admin_add_candidate function. """
@@ -746,16 +767,17 @@ class FlaskAdmintests(ModelFlasktests):
                     MagicMock(return_value=['elections'])):
                 output = self.app.get('/admin/test_election/candidates/new')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                self.assertTrue('Add candidate' in output.data)
+                self.assertTrue('Add candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
 
                 data = {
                     'name': 'pingou',
@@ -765,15 +787,16 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/candidates/new', data=data)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Add candidate' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Add candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
 
                 csrf_token = self.get_csrf(output=output)
 
@@ -786,18 +809,19 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/candidates/new', data=data)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Add candidate' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Add candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">This field is required.</div>'
-                    in output.data)
+                    in output_text)
 
                 data = {
                     'name': 'pingou',
@@ -809,10 +833,11 @@ class FlaskAdmintests(ModelFlasktests):
                     '/admin/test_election/candidates/new', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Candidate "pingou" saved'
-                    in output.data)
-                self.assertTrue('Candidates <span class="label label-pill label-default">4</span>' in output.data)
+                    in output_text)
+                self.assertTrue('Candidates <span class="label label-pill label-default">4</span>' in output_text)
 
     def test_admin_add_multi_candidate(self):
         """ Test the admin_add_multi_candidate function. """
@@ -834,16 +859,17 @@ class FlaskAdmintests(ModelFlasktests):
                     MagicMock(return_value=['elections'])):
                 output = self.app.get('/admin/test_election/candidates/new/multi')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                self.assertTrue('Add candidates' in output.data)
+                self.assertTrue('Add candidates' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" required type="text"', output.data)
+                        'name="candidate" required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" type="text"', output.data)
+                        'name="candidate" type="text"', output_text)
 
                 data = {
                     'candidate': 'pingou',
@@ -852,15 +878,16 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/candidates/new/multi', data=data)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Add candidates' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Add candidates' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" required type="text"', output.data)
+                        'name="candidate" required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" type="text"', output.data)
+                        'name="candidate" type="text"', output_text)
 
                 csrf_token = self.get_csrf(output=output)
 
@@ -872,18 +899,19 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/candidates/new/multi', data=data)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Add candidates' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Add candidates' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" required type="text"', output.data)
+                        'name="candidate" required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="candidate" '
-                        'name="candidate" type="text"', output.data)
+                        'name="candidate" type="text"', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">This field is required.</div>'
-                    in output.data)
+                    in output_text)
 
                 data = {
                     'candidate': 'pingou|patrick!https://fedoraproject.org|'
@@ -895,10 +923,11 @@ class FlaskAdmintests(ModelFlasktests):
                     '/admin/test_election/candidates/new/multi', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Added 3 candidates'
-                    in output.data)
-                self.assertTrue('Candidates <span class="label label-pill label-default">6</span>' in output.data)
+                    in output_text)
+                self.assertTrue('Candidates <span class="label label-pill label-default">6</span>' in output_text)
 
     def test_admin_edit_candidate(self):
         """ Test the admin_edit_candidate function. """
@@ -926,31 +955,32 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.get('/admin/test_election/candidates/1/edit')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                self.assertTrue('Edit candidate' in output.data)
+                self.assertTrue('Edit candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
 
                 data = {
                     'name': 'Toshio Kuratomi',
                     'url': 'https://fedoraproject.org/wiki/User:Toshio',
                 }
 
-                self.assertTrue('Edit candidate' in output.data)
+                self.assertTrue('Edit candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
 
                 csrf_token = self.get_csrf(output=output)
 
@@ -962,34 +992,36 @@ class FlaskAdmintests(ModelFlasktests):
                 output = self.app.post(
                     '/admin/test_election/candidates/1/edit', data=data)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Edit candidate' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Edit candidate' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'required type="text"', output.data)
+                        'required type="text"', output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="name" name="name" '
-                        'type="text"', output.data)
+                        'type="text"', output_text)
                 self.assertTrue(
                     '<div class="form-control-feedback">This field is required.</div>'
-                    in output.data)
+                    in output_text)
 
                 # Check election before edit
                 output = self.app.get('/admin/test_election/')
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" value="1"',
-                        output.data)
+                        output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" value="1"',
-                        output.data)
-                self.assertTrue('<div class="list-group-item">Toshio' in output.data)
+                        output_text)
+                self.assertTrue('<div class="list-group-item">Toshio' in output_text)
 
                 data = {
                     'name': 'Toshio Kuratomi',
@@ -1001,11 +1033,12 @@ class FlaskAdmintests(ModelFlasktests):
                     '/admin/test_election/candidates/1/edit', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Candidate "Toshio Kuratomi" saved'
-                    in output.data)
-                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output.data)
-                self.assertTrue('<div class="list-group-item">Toshio' in output.data)
+                    in output_text)
+                self.assertTrue('Candidates <span class="label label-pill label-default">3</span>' in output_text)
+                self.assertTrue('<div class="list-group-item">Toshio' in output_text)
 
     def test_admin_delete_candidate(self):
         """ Test the admin_delete_candidate function. """
@@ -1033,18 +1066,20 @@ class FlaskAdmintests(ModelFlasktests):
 
                 output = self.app.get('/admin/test_election/candidates/1/delete')
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                self.assertTrue('<h2>Delete candidate</h2>' in output.data)
+                self.assertTrue('<h2>Delete candidate</h2>' in output_text)
                 self.assertTrue(
                     'p>Are you sure you want to delete candidate "Toshio"?</p'
-                    in output.data)
+                    in output_text)
 
                 output = self.app.post('/admin/test_election/candidates/1/delete')
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('<h2>Delete candidate</h2>' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('<h2>Delete candidate</h2>' in output_text)
                 self.assertTrue(
                     'p>Are you sure you want to delete candidate "Toshio"?</p'
-                    in output.data)
+                    in output_text)
 
                 csrf_token = self.get_csrf(output=output)
 
@@ -1057,27 +1092,29 @@ class FlaskAdmintests(ModelFlasktests):
                     '/admin/test_election/candidates/1/delete', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
-                self.assertTrue('<h2>test election shortdesc</h2>' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('<h2>test election shortdesc</h2>' in output_text)
                 self.assertTrue(
                     'Could not delete this candidate. Is it '
-                    'already part of an election?' in output.data)
+                    'already part of an election?' in output_text)
 
                 # Check election before edit
                 output = self.app.get('/admin/test_election4/')
-                self.assertTrue('Candidates <span class="label label-pill label-default">2</span>' in output.data)
+                output_text = output.get_data(as_text=True)
+                self.assertTrue('Candidates <span class="label label-pill label-default">2</span>' in output_text)
                 if self.get_wtforms_version() >= (2, 2):
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" required type="text" value="1"',
-                        output.data)
+                        output_text)
                 else:
                     self.assertIn(
                         'input class="form-control" id="seats_elected" '
                         'name="seats_elected" type="text" value="1"',
-                        output.data)
-                self.assertTrue('<div class="list-group-item">Toshio' in output.data)
+                        output_text)
+                self.assertTrue('<div class="list-group-item">Toshio' in output_text)
                 self.assertTrue(
-                    'value="test election 4 shortdesc">' in output.data)
+                    'value="test election 4 shortdesc">' in output_text)
 
                 # Delete one candidate
                 data = {
@@ -1088,13 +1125,14 @@ class FlaskAdmintests(ModelFlasktests):
                     '/admin/test_election4/candidates/10/delete', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Candidate "Toshio" deleted'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
-                    'value="test election 4 shortdesc">' in output.data)
-                self.assertTrue('Candidates <span class="label label-pill label-default">1</span>' in output.data)
-                self.assertFalse('<div class="list-group-item">Toshio' in output.data)
+                    'value="test election 4 shortdesc">' in output_text)
+                self.assertTrue('Candidates <span class="label label-pill label-default">1</span>' in output_text)
+                self.assertFalse('<div class="list-group-item">Toshio' in output_text)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_flask_elections.py b/tests/test_flask_elections.py
index 5400851..09e99cc 100644
--- a/tests/test_flask_elections.py
+++ b/tests/test_flask_elections.py
@@ -49,9 +49,10 @@ class FlaskElectionstests(ModelFlasktests):
         """ Test the vote function without data. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         user = FakeUser(['packager'], username='pingou')
         with user_set(fedora_elections.APP, user, oidc_id_token='foobar'):
@@ -62,17 +63,19 @@ class FlaskElectionstests(ModelFlasktests):
                 self.assertEqual(output.status_code, 302)
 
                 output = self.app.get('/vote/test_election', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'The election, test_election, does not exist.'
-                    in output.data)
+                    in output_text)
 
     def test_vote(self):
         """ Test the vote function. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -84,9 +87,10 @@ class FlaskElectionstests(ModelFlasktests):
 
             output = self.app.get(
                 '/vote/test_election', follow_redirects=True)
+            output_text = output.get_data(as_text=True)
             self.assertTrue(
                 'You must sign the CLA to vote'
-                in output.data)
+                in output_text)
 
         user = FakeUser([], username='pingou')
         with user_set(fedora_elections.APP, user, oidc_id_token='foobar'):
@@ -99,9 +103,10 @@ class FlaskElectionstests(ModelFlasktests):
 
                 output = self.app.get(
                     '/vote/test_election', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'You need to be in one another group than '
-                    'CLA to vote' in output.data)
+                    'CLA to vote' in output_text)
 
         user = FakeUser(['packager'], username='pingou')
         with user_set(fedora_elections.APP, user, oidc_id_token='foobar'):
@@ -115,9 +120,10 @@ class FlaskElectionstests(ModelFlasktests):
                 # Election closed and results open
                 output = self.app.get(
                     '/vote/test_election3', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'You are not among the groups that are '
-                    'allowed to vote for this election' in output.data)
+                    'allowed to vote for this election' in output_text)
 
         user = FakeUser(['voters'], username='pingou')
         with user_set(fedora_elections.APP, user, oidc_id_token='foobar'):
@@ -131,75 +137,84 @@ class FlaskElectionstests(ModelFlasktests):
                 # Election closed and results open
                 output = self.app.get(
                     '/vote/test_election', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     '<span class="label label-danger">Election Closed</span>'
-                    in output.data)
+                    in output_text)
 
                 # Election closed and results are embargoed
                 output = self.app.get(
                     '/vote/test_election2', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     '<span class="label label-danger">Election Closed</span>'
-                    in output.data)
+                    in output_text)
 
                 # Election still pending
                 output = self.app.get(
                     '/vote/test_election4', follow_redirects=True)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Voting has not yet started, sorry.'
-                    in output.data)
+                    in output_text)
 
                 # Election in progress
                 output = self.app.get('/vote/test_election3')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
                 # Election in progress
                 output = self.app.get('/vote/test_election5')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
     def test_election_results(self):
         """ Test the election_results function - the preview part. """
         output = self.app.get(
             '/about/test_election', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'The election, test_election,  does not exist.'
-            in output.data)
+            in output_text)
 
         self.setup_db()
 
         output = self.app.get('/about/test_election')
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             '<th class="nowrap" title="Number of votes received">Votes</th>'
-            in output.data)
+            in output_text)
         self.assertTrue(
             '<h3>Some statistics about this election</h3>'
-            in output.data)
+            in output_text)
 
         output = self.app.get(
             '/about/test_election2', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'The results for this election cannot be viewed because they are '
-            in output.data)
+            in output_text)
 
         user = FakeUser(['packager'], username='toshio')
         with user_set(fedora_elections.APP, user):
             output = self.app.get(
                 '/about/test_election2', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
             self.assertTrue(
                 'The results for this election cannot be viewed because they are '
-                in output.data)
+                in output_text)
 
         user = FakeUser(
             fedora_elections.APP.config['FEDORA_ELECTIONS_ADMIN_GROUP'],
@@ -211,55 +226,60 @@ class FlaskElectionstests(ModelFlasktests):
                 output = self.app.get(
                     '/about/test_election2', follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'You are only seeing these results because you are an admin.'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     'The results for this election are currently embargoed '
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     '<th class="nowrap" title="Number of votes received">Votes</th>'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     '<h3>Some statistics about this election</h3>'
-                    in output.data)
+                    in output_text)
 
         user = FakeUser(['gitr2spec'], username='kevin')
         with user_set(fedora_elections.APP, user):
             output = self.app.get(
                 '/about/test_election3', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
             self.assertTrue(
                 '<span class="label label-success">Election Open</span>'
-                 in output.data)
+                 in output_text)
 
     def test_election_results_text(self):
         """ Test the election_results_text function - the preview part. """
         output = self.app.get(
             '/results/test_election/text', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'The election, test_election, does not exist.'
-            in output.data)
+            in output_text)
 
         self.setup_db()
 
         output = self.app.get(
             '/results/test_election/text', follow_redirects=True)
         self.assertEqual(output.status_code, 200)
+        output_text = output.get_data(as_text=True)
         self.assertTrue(
             'The text results are only available to the '
-            'admins' in output.data)
+            'admins' in output_text)
 
         user = FakeUser(['packager'], username='toshio')
         with user_set(fedora_elections.APP, user):
             output = self.app.get(
                 '/results/test_election2/text', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
             self.assertTrue(
                 'The text results are only available to the '
-                'admins' in output.data)
-            self.assertTrue('<h2>Elections' in output.data)
+                'admins' in output_text)
+            self.assertTrue('<h2>Elections' in output_text)
 
         user = FakeUser(
             fedora_elections.APP.config['FEDORA_ELECTIONS_ADMIN_GROUP'],
@@ -271,6 +291,7 @@ class FlaskElectionstests(ModelFlasktests):
                 output = self.app.get(
                     '/results/test_election/text', follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 exp = """<!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
@@ -307,12 +328,13 @@ candidates for running this elections!
 
 </body>
 </html>"""
-                print(output.data)
-                self.assertEqual(output.data, exp)
+                print(output_text)
+                self.assertEqual(output_text, exp)
 
                 output = self.app.get(
                     '/results/test_election2/text', follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 exp = """<!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
@@ -346,17 +368,18 @@ candidates for running this elections!
 </body>
 </html>"""
 
-                self.assertEqual(output.data, exp)
+                self.assertEqual(output_text, exp)
 
         user = FakeUser(['gitr2spec'], username='kevin')
         with user_set(fedora_elections.APP, user):
             output = self.app.get(
                 '/results/test_election3/text', follow_redirects=True)
             self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
             self.assertTrue(
                 'Sorry but this election is in progress,'
-                ' and you may not see its results yet.' in output.data)
-            self.assertTrue('Open elections' in output.data)
+                ' and you may not see its results yet.' in output_text)
+            self.assertTrue('Open elections' in output_text)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_flask_irc.py b/tests/test_flask_irc.py
index 59fed2a..628ace6 100644
--- a/tests/test_flask_irc.py
+++ b/tests/test_flask_irc.py
@@ -49,9 +49,10 @@ class FlaskIrcElectionstests(ModelFlasktests):
         """ Test the vote_irc function - the preview part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -60,15 +61,15 @@ class FlaskIrcElectionstests(ModelFlasktests):
             with patch(
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['packager'])):
-                output = self.app.get(
-                    '/vote/test_election7')
+                output = self.app.get('/vote/test_election7')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 7 shortdesc' in output.data)
+                    'test election 7 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid vote: No candidate
@@ -78,8 +79,9 @@ class FlaskIrcElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election7', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 7 shortdesc' in output.data)
+                    'test election 7 shortdesc' in output_text)
 
                 # Valid input
                 data = {
@@ -91,22 +93,24 @@ class FlaskIrcElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election7', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 7 shortdesc' in output.data)
+                    'test election 7 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="submit" />'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     'Please confirm your vote!'
-                    in output.data)
+                    in output_text)
 
     def test_vote_irc_process(self):
         """ Test the vote_irc function - the voting part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -125,8 +129,9 @@ class FlaskIrcElectionstests(ModelFlasktests):
                     '/vote/test_election7', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Valid input
@@ -141,10 +146,11 @@ class FlaskIrcElectionstests(ModelFlasktests):
                     '/vote/test_election7', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
 
     def test_vote_irc_revote(self):
         """ Test the vote_irc function - the re-voting part. """
@@ -157,7 +163,8 @@ class FlaskIrcElectionstests(ModelFlasktests):
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['packager'])):
                 retrieve_csrf = self.app.post('/vote/test_election7')
-                csrf_token = retrieve_csrf.data.split(
+                output_text = retrieve_csrf.get_data(as_text=True)
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
                 # Valid input
                 data = {
@@ -184,10 +191,11 @@ class FlaskIrcElectionstests(ModelFlasktests):
                 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)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
                 vote = fedora_elections.models.Vote
                 votes = vote.of_user_on_election(self.session, "nerdsville", '7')
                 self.assertEqual(votes[0].value, -1)
@@ -195,6 +203,7 @@ class FlaskIrcElectionstests(ModelFlasktests):
 
             #If we haven't failed yet, HOORAY!
 
+
 if __name__ == '__main__':
     SUITE = unittest.TestLoader().loadTestsFromTestCase(FlaskIrcElectionstests)
     unittest.TextTestRunner(verbosity=2).run(SUITE)
diff --git a/tests/test_flask_range_voting.py b/tests/test_flask_range_voting.py
index 32477cf..b1592c8 100644
--- a/tests/test_flask_range_voting.py
+++ b/tests/test_flask_range_voting.py
@@ -49,9 +49,10 @@ class FlaskRangeElectionstests(ModelFlasktests):
         """ Test the vote_range function - the preview part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -60,13 +61,13 @@ class FlaskRangeElectionstests(ModelFlasktests):
             with patch(
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['voters'])):
-                output = self.app.get(
-                    '/vote/test_election3')
+                output = self.app.get('/vote/test_election3')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
                 # Invalid candidate id
                 data = {
@@ -78,11 +79,12 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     3)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid candidate id
@@ -96,8 +98,9 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     3)
 
                 # Invalid vote: too low
@@ -111,13 +114,14 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     1)
 
                 # Invalid vote: 2 are too high
@@ -131,13 +135,14 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     2)
 
                 # Invalid vote: Not numeric
@@ -151,13 +156,14 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     1)
 
                 # Valid input
@@ -171,19 +177,21 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 3 shortdesc' in output.data)
+                    'test election 3 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="submit" />'
-                    in output.data)
+                    in output_text)
 
     def test_vote_range_process(self):
         """ Test the vote_range function - the voting part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -202,11 +210,12 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     3)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid vote: invalid username
@@ -219,8 +228,9 @@ class FlaskRangeElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     3)
 
                 # Invalid vote: too low
@@ -235,8 +245,9 @@ class FlaskRangeElectionstests(ModelFlasktests):
                 output = self.app.post(
                     '/vote/test_election3', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     1)
 
                 # Invalid vote: 2 are too high
@@ -251,8 +262,9 @@ class FlaskRangeElectionstests(ModelFlasktests):
                 output = self.app.post(
                     '/vote/test_election3', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     2)
 
                 # Invalid vote: Not numeric
@@ -267,8 +279,9 @@ class FlaskRangeElectionstests(ModelFlasktests):
                 output = self.app.post(
                     '/vote/test_election3', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertEqual(
-                    output.data.count('<div class="form-control-feedback">Not a valid choice</div>'),
+                    output_text.count('<div class="form-control-feedback">Not a valid choice</div>'),
                     1)
 
                 # Valid input
@@ -283,10 +296,11 @@ class FlaskRangeElectionstests(ModelFlasktests):
                 output = self.app.post(
                     '/vote/test_election3', data=data, follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
 
     def test_vote_range_revote(self):
         """ Test the vote_range function - the re-voting part. """
@@ -299,7 +313,7 @@ class FlaskRangeElectionstests(ModelFlasktests):
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['voters'])):
                 retrieve_csrf = self.app.post('/vote/test_election3')
-                csrf_token = retrieve_csrf.data.split(
+                csrf_token = retrieve_csrf.get_data(as_text=True).split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
                 data = {
                     '4': 1,
@@ -338,10 +352,11 @@ class FlaskRangeElectionstests(ModelFlasktests):
                 output = self.app.post('/vote/test_election3', data=newdata, follow_redirects=True)
             #Next, we need to check if the vote has been recorded
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
                 vote = fedora_elections.models.Vote
                 votes = vote.of_user_on_election(self.session, "nerdsville", '3')
                 self.assertEqual(votes[0].value, 2)
diff --git a/tests/test_flask_select_voting.py b/tests/test_flask_select_voting.py
index 8af5fb8..1dc268a 100644
--- a/tests/test_flask_select_voting.py
+++ b/tests/test_flask_select_voting.py
@@ -49,9 +49,10 @@ class FlaskSimpleElectionstests(ModelFlasktests):
         """ Test the vote_select function - the preview part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -60,15 +61,15 @@ class FlaskSimpleElectionstests(ModelFlasktests):
             with patch(
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['packager'])):
-                output = self.app.get(
-                    '/vote/test_election6')
+                output = self.app.get('/vote/test_election6')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 6 shortdesc' in output.data)
+                    'test election 6 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid vote: No candidate
@@ -78,8 +79,9 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election6', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 6 shortdesc' in output.data)
+                    'test election 6 shortdesc' in output_text)
 
                 # Invalid vote: Too many candidates
                 data = {
@@ -91,14 +93,15 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election6', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 6 shortdesc' in output.data)
+                    'test election 6 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     'Too many candidates submitted'
-                    in output.data)
+                    in output_text)
 
                 # Valid input
                 data = {
@@ -109,22 +112,24 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election6', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 6 shortdesc' in output.data)
+                    'test election 6 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="submit" />'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     'Please confirm your vote!'
-                    in output.data)
+                    in output_text)
 
     def test_vote_select_process(self):
         """ Test the vote_select function - the voting part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -143,8 +148,9 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election6', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Valid input
@@ -158,10 +164,11 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election6', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
 
     def test_vote_select_revote(self):
         """ Test the vote_select function - the re-voting part. """
@@ -174,7 +181,7 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['voters'])):
                 retrieve_csrf = self.app.post('/vote/test_election6')
-                csrf_token = retrieve_csrf.data.split(
+                csrf_token = retrieve_csrf.get_data(as_text=True).split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Valid input
@@ -200,10 +207,11 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                 output = self.app.post('/vote/test_election6', data=newdata, follow_redirects=True)
                 #Next, we need to check if the vote has been recorded
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
                 vote = fedora_elections.models.Vote
                 votes = vote.of_user_on_election(self.session, "nerdsville", '6')
                 self.assertEqual(votes[0].value, 1)
diff --git a/tests/test_flask_simple_voting.py b/tests/test_flask_simple_voting.py
index fe694b7..ade65bd 100644
--- a/tests/test_flask_simple_voting.py
+++ b/tests/test_flask_simple_voting.py
@@ -49,9 +49,10 @@ class FlaskSimpleElectionstests(ModelFlasktests):
         """ Test the vote_simple function - the preview part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -60,13 +61,13 @@ class FlaskSimpleElectionstests(ModelFlasktests):
             with patch(
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['voters'])):
-                output = self.app.get(
-                    '/vote/test_election5')
+                output = self.app.get('/vote/test_election5')
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
                 # Invalid vote: No candidate
                 data = {
@@ -75,16 +76,17 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election5', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     'Preview your vote'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid vote: No candidate
@@ -95,14 +97,15 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election5', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     'Preview your vote'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
                 # Invalid vote: Not numeric
                 data = {
@@ -113,11 +116,12 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election5', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="preview" />'
-                    in output.data)
+                    in output_text)
 
 
                 # Valid input
@@ -129,22 +133,24 @@ class FlaskSimpleElectionstests(ModelFlasktests):
 
                 output = self.app.post('/vote/test_election5', data=data)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
-                    'test election 5 shortdesc' in output.data)
+                    'test election 5 shortdesc' in output_text)
                 self.assertTrue(
                     '<input type="hidden" name="action" value="submit" />'
-                    in output.data)
+                    in output_text)
                 self.assertTrue(
                     'Please confirm your vote!'
-                    in output.data)
+                    in output_text)
 
     def test_vote_simple_process(self):
         """ Test the vote_simple function - the voting part. """
         output = self.app.get('/vote/test_election')
         self.assertEqual(output.status_code, 302)
+        output_text = output.get_data(as_text=True)
         self.assertIn(
             '/login?next=http%3A%2F%2Flocalhost%2Fvote%2Ftest_election',
-            output.data)
+            output_text)
 
         self.setup_db()
 
@@ -163,9 +169,9 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election5', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
 
-
-                csrf_token = output.data.split(
+                csrf_token = output_text.split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
 
                 # Invalid candidate id
@@ -179,7 +185,7 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election5', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
-
+                output_text = output.get_data(as_text=True)
 
                 # Invalid vote: too low
                 data = {
@@ -192,7 +198,7 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election5', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
-
+                output_text = output.get_data(as_text=True)
 
                 # Invalid vote: Not numeric
                 data = {
@@ -205,7 +211,7 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election5', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
-
+                output_text = output.get_data(as_text=True)
 
                 # Valid input
                 data = {
@@ -218,10 +224,11 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     '/vote/test_election5', data=data,
                     follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
 
     def test_vote_simple_revote(self):
         """ Test the vote_simple function - the re-voting part. """
@@ -234,7 +241,7 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                     'fedora_elections.OIDC.user_getfield',
                     MagicMock(return_value=['voters'])):
                 retrieve_csrf = self.app.post('/vote/test_election5')
-                csrf_token = retrieve_csrf.data.split(
+                csrf_token = retrieve_csrf.get_data(as_text=True).split(
                     'name="csrf_token" type="hidden" value="')[1].split('">')[0]
                 # Valid input
                 data = {
@@ -260,10 +267,11 @@ class FlaskSimpleElectionstests(ModelFlasktests):
                 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)
+                output_text = output.get_data(as_text=True)
                 self.assertTrue(
                     'Your vote has been recorded.  Thank you!'
-                    in output.data)
-                self.assertTrue('Open elections' in output.data)
+                    in output_text)
+                self.assertTrue('Open elections' in output_text)
                 vote = fedora_elections.models.Vote
                 votes = vote.of_user_on_election(self.session, "nerdsville", '5')
                 self.assertEqual(votes[0].candidate_id, 9)

From 396ee10c3b86f8722f113b35857d4a57331ee19c Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:06:41 +0000
Subject: [PATCH 3/7] Project wide flake8 fixes


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py
index 00ff7fa..030f76f 100644
--- a/fedora_elections/__init__.py
+++ b/fedora_elections/__init__.py
@@ -214,13 +214,14 @@ def set_session():  # pragma: no-cover
     flask.session.permanent = True
 
     if OIDC.user_loggedin:
-        if not hasattr(flask.session, 'fas_user') or not flask.session.fas_user:
+        if not hasattr(flask.session, 'fas_user') \
+                or not flask.session.fas_user:
             flask.session.fas_user = munch.Munch({
                 'username': OIDC.user_getfield('nickname'),
                 'email': OIDC.user_getfield('email') or '',
                 'timezone': OIDC.user_getfield('zoneinfo'),
-                'cla_done': \
-                    'http://admin.fedoraproject.org/accounts/cla/done' \
+                'cla_done':
+                    'http://admin.fedoraproject.org/accounts/cla/done'
                     in (OIDC.user_getfield('cla') or []),
             })
         flask.g.fas_user = flask.session.fas_user
diff --git a/fedora_elections/fedmsgshim.py b/fedora_elections/fedmsgshim.py
index 0336d16..51bba88 100644
--- a/fedora_elections/fedmsgshim.py
+++ b/fedora_elections/fedmsgshim.py
@@ -6,7 +6,6 @@
 """
 from __future__ import unicode_literals, absolute_import
 
-import warnings
 import logging
 
 import fedora_messaging.api
diff --git a/fedora_elections/utils.py b/fedora_elections/utils.py
index c90460a..0d50999 100644
--- a/fedora_elections/utils.py
+++ b/fedora_elections/utils.py
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals, absolute_import
 
-import fedora_elections
-
 
 def build_name_map(election):
     """ Returns a mapping of candidate ids to fas human_names. """

From cc5a75ee050e796a255ba0f3dd786a3b9ffab62e Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:16:31 +0000
Subject: [PATCH 4/7] Make election's logging configuration configurable


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/fedora_elections/__init__.py b/fedora_elections/__init__.py
index 030f76f..c782d8f 100644
--- a/fedora_elections/__init__.py
+++ b/fedora_elections/__init__.py
@@ -48,7 +48,6 @@ from fedora.client.fas2 import AccountSystem  # noqa
 from flask_oidc import OpenIDConnect  # noqa
 
 import fedora_elections.fedmsgshim  # noqa
-import fedora_elections.mail_logging  # noqa
 import fedora_elections.proxy  # noqa
 
 APP = flask.Flask(__name__)
@@ -59,18 +58,8 @@ if 'FEDORA_ELECTIONS_CONFIG' in os.environ:  # pragma: no cover
 # set up FAS
 OIDC = OpenIDConnect(APP, credentials_store=flask.session)
 
-# Set up the logging
-if not APP.debug:
-    APP.logger.addHandler(fedora_elections.mail_logging.get_mail_handler(
-        smtp_server=APP.config.get('SMTP_SERVER', '127.0.0.1'),
-        mail_admin=APP.config.get('MAIL_ADMIN', 'admin@fedoraproject.org')
-    ))
-
-# Log to stderr as well
-STDERR_LOG = logging.StreamHandler(sys.stderr)
-STDERR_LOG.setLevel(logging.INFO)
-APP.logger.addHandler(STDERR_LOG)
-
+logging.basicConfig()
+logging.config.dictConfig(APP.config.get("LOGGING") or {"version": 1})
 LOG = APP.logger
 
 APP.wsgi_app = fedora_elections.proxy.ReverseProxied(APP.wsgi_app)
diff --git a/fedora_elections/default_config.py b/fedora_elections/default_config.py
index 938cb53..42c6d44 100644
--- a/fedora_elections/default_config.py
+++ b/fedora_elections/default_config.py
@@ -29,3 +29,71 @@ OIDC_CLIENT_SECRETS = os.path.join(os.path.dirname(
     os.path.abspath(__file__)), '..', 'client_secrets.json')
 OIDC_SCOPES = ['openid', 'email', 'profile', 'fedora']
 OIDC_OPENID_REALM = 'http://localhost:5005/oidc_callback'
+
+LOGGING = {
+    "version": 1,
+    "disable_existing_loggers": False,
+    "formatters": {
+        "standard": {
+            "format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
+        },
+        "email_format": {"format": MSG_FORMAT},
+    },
+    "filters": {"myfilter": {"()": ContextInjector}},
+    "handlers": {
+        "console": {
+            "level": "DEBUG",
+            "formatter": "standard",
+            "class": "logging.StreamHandler",
+            "stream": "ext://sys.stdout",
+        },
+        "email": {
+            "level": "ERROR",
+            "formatter": "email_format",
+            "class": "logging.handlers.SMTPHandler",
+            "mailhost": "localhost",
+            "fromaddr": "elections@localhost",
+            "toaddrs": "elections@localhost",
+            "subject": "ERROR on elections",
+            "filters": ["myfilter"],
+        },
+    },
+    # The root logger configuration; this is a catch-all configuration
+    # that applies to all log messages not handled by a different logger
+    "root": {
+        "level": "DEBUG",
+        "handlers": ["console"]
+    },
+    "loggers": {
+        "fedora_elections": {
+            "handlers": ["console"],
+            "level": "DEBUG",
+            "propagate": True,
+        },
+        "flask": {
+            "handlers": ["console"],
+            "level": "INFO",
+            "propagate": True,
+        },
+        "flask_oidc": {
+            "handlers": ["console"],
+            "level": "INFO",
+            "propagate": False,
+        },
+        "sqlalchemy": {
+            "handlers": ["console"],
+            "level": "WARN",
+            "propagate": False,
+        },
+        "fedora_messaging": {
+            "handlers": ["console"],
+            "level": "INFO",
+            "propagate": True,
+        },
+        "pika": {
+            "handlers": ["console"],
+            "level": "WARN",
+            "propagate": True,
+        },
+    },
+}

From a1a79fa678202b2db8544e15a391bede5a9f38be Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:18:02 +0000
Subject: [PATCH 5/7] Add a little more logging after sending a message


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/fedora_elections/fedmsgshim.py b/fedora_elections/fedmsgshim.py
index 51bba88..ce08619 100644
--- a/fedora_elections/fedmsgshim.py
+++ b/fedora_elections/fedmsgshim.py
@@ -23,6 +23,7 @@ def publish(topic, msg):  # pragma: no cover
             body=msg
         )
         fedora_messaging.api.publish(message)
+        _log.debug("Sent to fedora_messaging")
     except PublishReturned as e:
         _log.exception(
             'Fedora Messaging broker rejected message %s: %s',

From 442f9b9b7f19d11f515932d36f74fc73eee83706 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:21:32 +0000
Subject: [PATCH 6/7] Move the tests to run on py3 by default


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/runtests.sh b/runtests.sh
index 8ac84b0..9f39110 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
 
 FEDORA_ELECTIONS_CONFIG=`pwd`/tests/config \
-PYTHONPATH=fedora_elections ./nosetests \
+PYTHONPATH=fedora_elections python3 ./nosetests \
 --with-coverage --cover-erase --cover-package=fedora_elections $*

From 34523f2d72a01d8601f76352e8233aeb9a3891a0 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: May 02 2019 14:21:50 +0000
Subject: [PATCH 7/7] Add six to the list of requirements


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/requirements.txt b/requirements.txt
index 78dffb3..af5bd9a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,3 +10,4 @@ SQLAlchemy
 wtforms
 arrow
 blinker # required by Flask for the unit-tests (for signaling)
+six

