From bdc73e771a93ea2d32b5c1f39739af2c849e4b46 Mon Sep 17 00:00:00 2001
From: Henrik Levkowetz <henrik@levkowetz.com>
Date: Tue, 16 Jul 2019 13:20:05 +0000
Subject: [PATCH] Python2/3 compatibility: replaced six.ensure_text() with
 either six.text_type or django's force_text(), depending on the case, and
 fixed a variable scope issue.  - Legacy-Id: 16461

---
 changelog.py                          |  4 ++--
 ietf/api/serializer.py                |  2 +-
 ietf/community/views.py               |  2 +-
 ietf/doc/feeds.py                     |  2 +-
 ietf/doc/fields.py                    |  2 +-
 ietf/doc/mails.py                     | 12 +++++-----
 ietf/doc/models.py                    |  6 ++---
 ietf/doc/templatetags/ietf_filters.py |  5 ++--
 ietf/doc/tests_review.py              |  6 +++--
 ietf/doc/utils_charter.py             |  5 ++--
 ietf/doc/utils_search.py              |  2 +-
 ietf/doc/views_charter.py             |  4 ++--
 ietf/doc/views_doc.py                 |  2 +-
 ietf/doc/views_status_change.py       |  4 ++--
 ietf/group/tests_info.py              |  2 +-
 ietf/group/tests_review.py            |  2 +-
 ietf/group/views.py                   |  2 +-
 ietf/idindex/index.py                 |  2 +-
 ietf/idindex/tests.py                 |  2 +-
 ietf/iesg/views.py                    |  4 ++--
 ietf/ipr/feeds.py                     |  5 ++--
 ietf/ipr/fields.py                    |  2 +-
 ietf/ipr/views.py                     |  4 ++--
 ietf/liaisons/fields.py               |  2 +-
 ietf/liaisons/forms.py                |  2 +-
 ietf/meeting/tests_views.py           | 20 ++++++++--------
 ietf/nomcom/forms.py                  |  4 ++--
 ietf/nomcom/tests.py                  | 10 ++++----
 ietf/nomcom/utils.py                  |  6 ++---
 ietf/person/factories.py              |  4 ++--
 ietf/person/fields.py                 |  2 +-
 ietf/person/models.py                 |  2 +-
 ietf/person/tests.py                  |  2 +-
 ietf/review/utils.py                  |  2 +-
 ietf/secr/sreq/tests.py               |  4 ++--
 ietf/submit/tests.py                  | 34 +++++++++++++--------------
 ietf/sync/rfceditor.py                |  2 +-
 ietf/utils/admin.py                   |  6 +++--
 ietf/utils/mail.py                    |  4 ++--
 ietf/utils/pipe.py                    |  2 +-
 ietf/utils/tests.py                   | 21 ++++++++++-------
 requirements.txt                      |  2 +-
 42 files changed, 111 insertions(+), 103 deletions(-)

diff --git a/changelog.py b/changelog.py
index c7eb53a8e..bf27661de 100644
--- a/changelog.py
+++ b/changelog.py
@@ -43,8 +43,8 @@ class ChangeLogEntry:
     title = ""
 
 def parse(logfile):
-    ver_line = "^(\w+) \((\S+)\) (\S+;)? (?:urgency=(\S+))?$"
-    sig_line = "^ -- ([^<]+) <([^>]+)>  (.*?) *$"
+    ver_line = r"^(\w+) \((\S+)\) (\S+;)? (?:urgency=(\S+))?$"
+    sig_line = r"^ -- ([^<]+) <([^>]+)>  (.*?) *$"
     inf_line = r"^  \*\*(.*)\*\* *"
 
     entries = []
diff --git a/ietf/api/serializer.py b/ietf/api/serializer.py
index 0dfdb6aed..98e276efe 100644
--- a/ietf/api/serializer.py
+++ b/ietf/api/serializer.py
@@ -154,7 +154,7 @@ class AdminJsonSerializer(Serializer):
                             if hasattr(field_value, "_meta"):
                                 self._current[name] = self.expand_related(field_value, name)
                             else:
-                                self._current[name] = six.ensure_text(field_value)
+                                self._current[name] = six.text_type(field_value)
             except ObjectDoesNotExist:
                 pass
             except AttributeError:
diff --git a/ietf/community/views.py b/ietf/community/views.py
index 375287e29..427e72943 100644
--- a/ietf/community/views.py
+++ b/ietf/community/views.py
@@ -202,7 +202,7 @@ def export_to_csv(request, username=None, acronym=None, group_type=None):
         row.append(e.time.strftime("%Y-%m-%d") if e else "")
         row.append(strip_tags(doc.friendly_state()))
         row.append(doc.group.acronym if doc.group else "")
-        row.append(six.ensure_text(doc.ad) if doc.ad else "")
+        row.append(six.text_type(doc.ad) if doc.ad else "")
         e = doc.latest_event()
         row.append(e.time.strftime("%Y-%m-%d") if e else "")
         writer.writerow([v.encode("utf-8") for v in row])
diff --git a/ietf/doc/feeds.py b/ietf/doc/feeds.py
index 24a79568c..3fb50898d 100644
--- a/ietf/doc/feeds.py
+++ b/ietf/doc/feeds.py
@@ -49,7 +49,7 @@ class DocumentChangesFeed(Feed):
         return item.time
 
     def item_author_name(self, item):
-        return six.ensure_text(item.by)
+        return six.text_type(item.by)
 
     def item_link(self, item):
         return urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=item.doc.canonical_name())) + "#history-%s" % item.pk
diff --git a/ietf/doc/fields.py b/ietf/doc/fields.py
index e8f76b222..9c358949f 100644
--- a/ietf/doc/fields.py
+++ b/ietf/doc/fields.py
@@ -83,7 +83,7 @@ class SearchableDocumentsField(forms.CharField):
             "model_name": self.model.__name__.lower()
         })
 
-        return ",".join(six.ensure_text(o.pk) for o in value)
+        return ",".join(six.text_type(o.pk) for o in value)
 
     def clean(self, value):
         value = super(SearchableDocumentsField, self).clean(value)
diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py
index 9d9526751..7ff511903 100644
--- a/ietf/doc/mails.py
+++ b/ietf/doc/mails.py
@@ -13,7 +13,7 @@ from django.template.loader import render_to_string
 from django.utils.html import strip_tags
 from django.conf import settings
 from django.urls import reverse as urlreverse
-from django.utils.encoding import force_str
+from django.utils.encoding import force_str, force_text
 
 import debug                            # pyflakes:ignore
 
@@ -128,7 +128,7 @@ def generate_ballot_writeup(request, doc):
     e.doc = doc
     e.rev = doc.rev
     e.desc = "Ballot writeup was generated"
-    e.text = six.ensure_text(render_to_string("doc/mail/ballot_writeup.txt", {'iana': iana}))
+    e.text = force_text(render_to_string("doc/mail/ballot_writeup.txt", {'iana': iana}))
 
     # caller is responsible for saving, if necessary
     return e
@@ -140,7 +140,7 @@ def generate_ballot_rfceditornote(request, doc):
     e.doc = doc
     e.rev = doc.rev
     e.desc = "RFC Editor Note for ballot was generated"
-    e.text = six.ensure_text(render_to_string("doc/mail/ballot_rfceditornote.txt"))
+    e.text = force_text(render_to_string("doc/mail/ballot_rfceditornote.txt"))
     e.save()
     
     return e
@@ -185,7 +185,7 @@ def generate_last_call_announcement(request, doc):
     e.doc = doc
     e.rev = doc.rev
     e.desc = "Last call announcement was generated"
-    e.text = six.ensure_text(mail)
+    e.text = force_text(mail)
 
     # caller is responsible for saving, if necessary
     return e
@@ -205,7 +205,7 @@ def generate_approval_mail(request, doc):
     e.doc = doc
     e.rev = doc.rev
     e.desc = "Ballot approval text was generated"
-    e.text = six.ensure_text(mail)
+    e.text = force_text(mail)
 
     # caller is responsible for saving, if necessary
     return e
@@ -288,7 +288,7 @@ def generate_publication_request(request, doc):
         approving_body = "IRSG"
         consensus_body = doc.group.acronym.upper()
     else:
-        approving_body = six.ensure_text(doc.stream)
+        approving_body = six.text_type(doc.stream)
         consensus_body = approving_body
 
     e = doc.latest_event(WriteupDocEvent, type="changed_rfc_editor_note_text")
diff --git a/ietf/doc/models.py b/ietf/doc/models.py
index 65c3e4730..eaa5d9c91 100644
--- a/ietf/doc/models.py
+++ b/ietf/doc/models.py
@@ -17,7 +17,7 @@ from django.core.validators import URLValidator, RegexValidator
 from django.urls import reverse as urlreverse
 from django.contrib.contenttypes.models import ContentType
 from django.conf import settings
-from django.utils.encoding import python_2_unicode_compatible
+from django.utils.encoding import python_2_unicode_compatible, force_text
 from django.utils.html import mark_safe
 
 import debug                            # pyflakes:ignore
@@ -880,7 +880,7 @@ class DocHistory(DocumentInfo):
     name = models.CharField(max_length=255)
 
     def __str__(self):
-        return six.ensure_text(self.doc.name)
+        return force_text(self.doc.name)
 
     def canonical_name(self):
         if hasattr(self, '_canonical_name'):
@@ -930,7 +930,7 @@ class DocAlias(models.Model):
         return self.docs.first()
 
     def __str__(self):
-        return u"%s-->%s" % (self.name, ','.join([six.ensure_text(d.name) for d in self.docs.all() if isinstance(d, Document) ]))
+        return u"%s-->%s" % (self.name, ','.join([force_text(d.name) for d in self.docs.all() if isinstance(d, Document) ]))
     document_link = admin_link("document")
     class Meta:
         verbose_name = "document alias"
diff --git a/ietf/doc/templatetags/ietf_filters.py b/ietf/doc/templatetags/ietf_filters.py
index a8662bbc4..53428c359 100644
--- a/ietf/doc/templatetags/ietf_filters.py
+++ b/ietf/doc/templatetags/ietf_filters.py
@@ -17,6 +17,7 @@ from django.utils.html import escape
 from django.template.defaultfilters import truncatewords_html, linebreaksbr, stringfilter, striptags
 from django.utils.safestring import mark_safe, SafeData
 from django.utils.html import strip_tags
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -198,7 +199,7 @@ def rfcnospace(string):
 @register.filter
 def prettystdname(string):
     from ietf.doc.utils import prettify_std_name
-    return prettify_std_name(six.ensure_text(string or ""))
+    return prettify_std_name(force_text(string or ""))
 
 @register.filter(name='rfcurl')
 def rfclink(string):
@@ -341,7 +342,7 @@ def expires_soon(x,request):
 
 @register.filter(name='startswith')
 def startswith(x, y):
-    return six.ensure_text(x).startswith(y)
+    return six.text_type(x).startswith(y)
 
 @register.filter
 def has_role(user, role_names):
diff --git a/ietf/doc/tests_review.py b/ietf/doc/tests_review.py
index 1137cf141..48c1e61b5 100644
--- a/ietf/doc/tests_review.py
+++ b/ietf/doc/tests_review.py
@@ -101,10 +101,12 @@ class ReviewTests(TestCase):
 
         self.assertEqual(len(outbox),2)
         self.assertTrue('reviewteam Early' in outbox[0]['Subject'])
-#        debug.show("outbox[0]['To']")
+        if not 'reviewsecretary@' in outbox[0]['To']:
+            print(outbox[0].as_string())
         self.assertTrue('reviewsecretary@' in outbox[0]['To'])
         self.assertTrue('reviewteam3 Early' in outbox[1]['Subject'])
-#        debug.show("outbox[1]['To']")
+        if not 'reviewsecretary3@' in outbox[1]['To']:
+            print(outbox[1].as_string())
         self.assertTrue('reviewsecretary3@' in outbox[1]['To'])
 
         # set the reviewteamsetting for the secretary email alias, then do the post again
diff --git a/ietf/doc/utils_charter.py b/ietf/doc/utils_charter.py
index 3dae431a6..7b44ad3ff 100644
--- a/ietf/doc/utils_charter.py
+++ b/ietf/doc/utils_charter.py
@@ -9,12 +9,11 @@ import io
 import os
 import re
 import shutil
-import six
 
 from django.conf import settings
 from django.urls import reverse as urlreverse
 from django.template.loader import render_to_string
-from django.utils.encoding import smart_text
+from django.utils.encoding import smart_text, force_text
 
 import debug                            # pyflakes:ignore
 
@@ -152,7 +151,7 @@ def generate_ballot_writeup(request, doc):
     e.doc = doc
     e.rev = doc.rev,
     e.desc = "Ballot writeup was generated"
-    e.text = six.ensure_text(render_to_string("doc/charter/ballot_writeup.txt"))
+    e.text = force_text(render_to_string("doc/charter/ballot_writeup.txt"))
 
     # caller is responsible for saving, if necessary
     return e
diff --git a/ietf/doc/utils_search.py b/ietf/doc/utils_search.py
index 8756832d7..14227f4a8 100644
--- a/ietf/doc/utils_search.py
+++ b/ietf/doc/utils_search.py
@@ -106,7 +106,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
         d.expirable = expirable_draft(d)
 
         if d.get_state_slug() != "rfc":
-            d.milestones = [ m for (t, s, d, m) in sorted(((m.time, m.state.slug, m.desc, m) for m in d.groupmilestone_set.all() if m.state_id == "active")) ]
+            d.milestones = [ m for (t, s, v, m) in sorted(((m.time, m.state.slug, m.desc, m) for m in d.groupmilestone_set.all() if m.state_id == "active")) ]
             d.reviewed_by_teams = sorted(set(r.team.acronym for r in d.reviewrequest_set.filter(state__in=["assigned","accepted","part-completed","completed"]).distinct().select_related('team')))
 
         e = d.latest_event_cache.get('started_iesg_process', None)
diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py
index 2438f4241..bf827aaf7 100644
--- a/ietf/doc/views_charter.py
+++ b/ietf/doc/views_charter.py
@@ -8,7 +8,6 @@ import datetime
 import io
 import json
 import os
-import six
 import textwrap
 
 from django.http import HttpResponseRedirect, HttpResponseNotFound, HttpResponseForbidden, Http404
@@ -19,6 +18,7 @@ from django.utils.safestring import mark_safe
 from django.conf import settings
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -816,7 +816,7 @@ def charter_with_milestones_txt(request, name, rev):
 
     try:
         with io.open(os.path.join(settings.CHARTER_PATH, filename), 'r') as f:
-            charter_text = six.ensure_text(f.read(), errors='ignore')
+            charter_text = force_text(f.read(), errors='ignore')
     except IOError:
         charter_text = "Error reading charter text %s" % filename
 
diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py
index cbdcfefe7..d10323ce5 100644
--- a/ietf/doc/views_doc.py
+++ b/ietf/doc/views_doc.py
@@ -1274,7 +1274,7 @@ def add_sessionpresentation(request,name):
     if doc.group:
         sessions = sorted(sessions,key=lambda x:0 if x.group==doc.group else 1)
 
-    session_choices = [(s.pk, six.ensure_text(s)) for s in sessions]
+    session_choices = [(s.pk, six.text_type(s)) for s in sessions]
 
     if request.method == 'POST':
         version_form = VersionForm(request.POST,choices=version_choices)
diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py
index 14113f5d5..b52e7d0cf 100644
--- a/ietf/doc/views_status_change.py
+++ b/ietf/doc/views_status_change.py
@@ -8,7 +8,6 @@ import datetime
 import io
 import os
 import re
-import six
 
 from django import forms
 from django.shortcuts import render, get_object_or_404, redirect
@@ -16,6 +15,7 @@ from django.http import Http404, HttpResponseRedirect
 from django.urls import reverse
 from django.template.loader import render_to_string
 from django.conf import settings
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -641,7 +641,7 @@ def generate_last_call_text(request, doc):
     e.doc = doc
     e.rev = doc.rev
     e.desc = 'Last call announcement was generated'
-    e.text = six.ensure_text(new_text)
+    e.text = force_text(new_text)
     e.save()
 
     return e 
diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py
index 11c227579..1829399b2 100644
--- a/ietf/group/tests_info.py
+++ b/ietf/group/tests_info.py
@@ -1268,7 +1268,7 @@ class StatusUpdateTests(TestCase):
             response = self.client.get(url)
             self.assertEqual(response.status_code,200)
             q=PyQuery(response.content)
-            self.assertTrue(bleach.linkify(escape(event.desc)) in six.ensure_text(q('pre')))
+            self.assertTrue(bleach.linkify(escape(event.desc)) in six.text_type(q('pre')))
             self.assertFalse(q('a#edit_button'))
             self.client.login(username=chair.person.user.username,password='%s+password'%chair.person.user.username)
             response = self.client.get(url)
diff --git a/ietf/group/tests_review.py b/ietf/group/tests_review.py
index 4d5f99c2a..66ee9a13e 100644
--- a/ietf/group/tests_review.py
+++ b/ietf/group/tests_review.py
@@ -264,7 +264,7 @@ class ReviewTests(TestCase):
         q = PyQuery(r.content)
         generated_text = q("[name=body]").text()
         self.assertTrue(review_req1.doc.name in generated_text)
-        self.assertTrue(six.ensure_text(Person.objects.get(user__username="marschairman")) in generated_text)
+        self.assertTrue(six.text_type(Person.objects.get(user__username="marschairman")) in generated_text)
 
         empty_outbox()
         r = self.client.post(url, {
diff --git a/ietf/group/views.py b/ietf/group/views.py
index ab15db3df..7844c74d2 100644
--- a/ietf/group/views.py
+++ b/ietf/group/views.py
@@ -1448,7 +1448,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status=
         saving = form_action.startswith("save")
 
         # check for conflicts
-        review_requests_dict = { six.ensure_text(r.pk): r for r in review_requests }
+        review_requests_dict = { six.text_type(r.pk): r for r in review_requests }
         posted_reqs = set(request.POST.getlist("reviewrequest", []))
         current_reqs = set(review_requests_dict.keys())
 
diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py
index b79308952..03d5f2b2d 100644
--- a/ietf/idindex/index.py
+++ b/ietf/idindex/index.py
@@ -195,7 +195,7 @@ def all_id2_txt():
                 area = d.group.parent.acronym
         fields.append(area)
         # 9 responsible AD name
-        fields.append(six.ensure_text(d.ad) if d.ad else "")
+        fields.append(six.text_type(d.ad) if d.ad else "")
         # 10
         fields.append(d.intended_std_level.name if d.intended_std_level else "")
         # 11
diff --git a/ietf/idindex/tests.py b/ietf/idindex/tests.py
index c073fbe0b..503a84a93 100644
--- a/ietf/idindex/tests.py
+++ b/ietf/idindex/tests.py
@@ -102,7 +102,7 @@ class IndexTests(TestCase):
         self.assertEqual(t[6], draft.latest_event(type="new_revision").time.strftime("%Y-%m-%d"))
         self.assertEqual(t[7], draft.group.acronym)
         self.assertEqual(t[8], draft.group.parent.acronym)
-        self.assertEqual(t[9], six.ensure_text(draft.ad))
+        self.assertEqual(t[9], six.text_type(draft.ad))
         self.assertEqual(t[10], draft.intended_std_level.name)
         self.assertEqual(t[11], "")
         self.assertEqual(t[12], ".pdf,.txt")
diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py
index 35b9d0b96..41c25ca6d 100644
--- a/ietf/iesg/views.py
+++ b/ietf/iesg/views.py
@@ -316,9 +316,9 @@ def agenda_documents_txt(request):
         row = (
             d.computed_telechat_date.isoformat(),
             d.name,
-            six.ensure_text(d.intended_std_level),
+            six.text_type(d.intended_std_level),
             "1" if d.stream_id in ("ise", "irtf") else "0",
-            six.ensure_text(d.area_acronym()).lower(),
+            six.text_type(d.area_acronym()).lower(),
             d.ad.plain_name() if d.ad else "None Assigned",
             d.rev,
             )
diff --git a/ietf/ipr/feeds.py b/ietf/ipr/feeds.py
index 7482abf5e..7b8f1938f 100644
--- a/ietf/ipr/feeds.py
+++ b/ietf/ipr/feeds.py
@@ -4,12 +4,11 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
-import six
-
 from django.contrib.syndication.views import Feed
 from django.utils.feedgenerator import Atom1Feed
 from django.urls import reverse_lazy
 from django.utils.safestring import mark_safe
+from django.utils.encoding import force_text
 
 from ietf.ipr.models import IprDisclosureBase
 
@@ -28,7 +27,7 @@ class LatestIprDisclosuresFeed(Feed):
         return mark_safe(item.title)
 
     def item_description(self, item):
-        return six.ensure_text(item.title)
+        return force_text(item.title)
         
     def item_pubdate(self, item):
         return item.time
diff --git a/ietf/ipr/fields.py b/ietf/ipr/fields.py
index d2a24268c..a6529c270 100644
--- a/ietf/ipr/fields.py
+++ b/ietf/ipr/fields.py
@@ -68,7 +68,7 @@ class SearchableIprDisclosuresField(forms.CharField):
         # patterns may not have been fully constructed there yet
         self.widget.attrs["data-ajax-url"] = urlreverse('ietf.ipr.views.ajax_search')
 
-        return ",".join(six.ensure_text(e.pk) for e in value)
+        return ",".join(six.text_type(e.pk) for e in value)
 
     def clean(self, value):
         value = super(SearchableIprDisclosuresField, self).clean(value)
diff --git a/ietf/ipr/views.py b/ietf/ipr/views.py
index 607b609ad..81df9ab95 100644
--- a/ietf/ipr/views.py
+++ b/ietf/ipr/views.py
@@ -456,7 +456,7 @@ def by_draft_txt(request):
 
     lines = [ "# Machine-readable list of IPR disclosures by draft name" ]
     for name, iprs in docipr.items():
-        lines.append(name + "\t" + "\t".join(six.ensure_text(ipr_id) for ipr_id in sorted(iprs)))
+        lines.append(name + "\t" + "\t".join(six.text_type(ipr_id) for ipr_id in sorted(iprs)))
 
     return HttpResponse("\n".join(lines), content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET)
 
@@ -478,7 +478,7 @@ def by_draft_recursive_txt(request):
 
     lines = [ "# Machine-readable list of IPR disclosures by draft name" ]
     for name, iprs in docipr.items():
-        lines.append(name + "\t" + "\t".join(six.ensure_text(ipr_id) for ipr_id in sorted(iprs)))
+        lines.append(name + "\t" + "\t".join(six.text_type(ipr_id) for ipr_id in sorted(iprs)))
 
     return HttpResponse("\n".join(lines), content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET)
 
diff --git a/ietf/liaisons/fields.py b/ietf/liaisons/fields.py
index b70572ff8..6f21b7c74 100644
--- a/ietf/liaisons/fields.py
+++ b/ietf/liaisons/fields.py
@@ -65,7 +65,7 @@ class SearchableLiaisonStatementsField(forms.CharField):
         # patterns may not have been fully constructed there yet
         self.widget.attrs["data-ajax-url"] = urlreverse("ietf.liaisons.views.ajax_select2_search_liaison_statements")
 
-        return ",".join(six.ensure_text(o.pk) for o in value)
+        return ",".join(six.text_type(o.pk) for o in value)
 
     def clean(self, value):
         value = super(SearchableLiaisonStatementsField, self).clean(value)
diff --git a/ietf/liaisons/forms.py b/ietf/liaisons/forms.py
index eeb128a0c..d9bb4da6d 100644
--- a/ietf/liaisons/forms.py
+++ b/ietf/liaisons/forms.py
@@ -452,7 +452,7 @@ class IncomingLiaisonForm(LiaisonModelForm):
             self.fields['from_contact'].initial = self.person.role_set.filter(group=queryset[0]).first().email.address
             self.fields['from_contact'].widget.attrs['readonly'] = True
         self.fields['from_groups'].queryset = queryset
-        self.fields['from_groups'].widget.submitter = six.ensure_text(self.person)
+        self.fields['from_groups'].widget.submitter = six.text_type(self.person)
 
         # if there's only one possibility make it the default
         if len(queryset) == 1:
diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py
index a9a296923..89d033fb1 100644
--- a/ietf/meeting/tests_views.py
+++ b/ietf/meeting/tests_views.py
@@ -1727,7 +1727,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Upload', six.ensure_text(q("title")))
+        self.assertIn('Upload', six.text_type(q("title")))
         self.assertFalse(session.sessionpresentation_set.exists())
         test_file = StringIO('%PDF-1.4\n%âãÏÓ\nthis is some text for a test')
         test_file.name = "not_really.pdf"
@@ -1738,7 +1738,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Revise', six.ensure_text(q("title")))
+        self.assertIn('Revise', six.text_type(q("title")))
         test_file = StringIO('%PDF-1.4\n%âãÏÓ\nthis is some different text for a test')
         test_file.name = "also_not_really.pdf"
         r = self.client.post(url,dict(file=test_file))
@@ -1762,7 +1762,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Upload', six.ensure_text(q("title")))
+        self.assertIn('Upload', six.text_type(q("title")))
         self.assertFalse(session.sessionpresentation_set.exists())
         test_file = StringIO('%PDF-1.4\n%âãÏÓ\nthis is some text for a test')
         test_file.name = "not_really.pdf"
@@ -1780,7 +1780,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Upload', six.ensure_text(q("title")))
+        self.assertIn('Upload', six.text_type(q("title")))
         
 
     def test_upload_minutes_agenda(self):
@@ -1795,7 +1795,7 @@ class MaterialsTests(TestCase):
             r = self.client.get(url)
             self.assertEqual(r.status_code, 200)
             q = PyQuery(r.content)
-            self.assertIn('Upload', six.ensure_text(q("Title")))
+            self.assertIn('Upload', six.text_type(q("Title")))
             self.assertFalse(session.sessionpresentation_set.exists())
             self.assertFalse(q('form input[type="checkbox"]'))
     
@@ -1849,7 +1849,7 @@ class MaterialsTests(TestCase):
             r = self.client.get(url)
             self.assertEqual(r.status_code, 200)
             q = PyQuery(r.content)
-            self.assertIn('Revise', six.ensure_text(q("Title")))
+            self.assertIn('Revise', six.text_type(q("Title")))
             test_file = BytesIO(b'this is some different text for a test')
             test_file.name = "also_not_really.txt"
             r = self.client.post(url,dict(file=test_file,apply_to_all=True))
@@ -1883,7 +1883,7 @@ class MaterialsTests(TestCase):
             r = self.client.get(url)
             self.assertEqual(r.status_code, 200)
             q = PyQuery(r.content)
-            self.assertIn('Upload', six.ensure_text(q("Title")))
+            self.assertIn('Upload', six.text_type(q("Title")))
             self.assertFalse(session.sessionpresentation_set.exists())
             self.assertFalse(q('form input[type="checkbox"]'))
 
@@ -1904,7 +1904,7 @@ class MaterialsTests(TestCase):
             r = self.client.get(url)
             self.assertEqual(r.status_code, 200)
             q = PyQuery(r.content)
-            self.assertIn('Upload', six.ensure_text(q("title")))
+            self.assertIn('Upload', six.text_type(q("title")))
             self.assertFalse(session.sessionpresentation_set.filter(document__type_id=doctype))
             test_file = BytesIO(b'this is some text for a test')
             test_file.name = "not_really.txt"
@@ -1927,7 +1927,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Upload', six.ensure_text(q("title")))
+        self.assertIn('Upload', six.text_type(q("title")))
         self.assertFalse(session1.sessionpresentation_set.filter(document__type_id='slides'))
         test_file = BytesIO(b'this is not really a slide')
         test_file.name = 'not_really.txt'
@@ -1955,7 +1955,7 @@ class MaterialsTests(TestCase):
         r = self.client.get(url)
         self.assertTrue(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertIn('Revise', six.ensure_text(q("title")))
+        self.assertIn('Revise', six.text_type(q("title")))
         test_file = BytesIO(b'new content for the second slide deck')
         test_file.name = 'doesnotmatter.txt'
         r = self.client.post(url,dict(file=test_file,title='rename the presentation',apply_to_all=False))
diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py
index 2f801a842..401bc6532 100644
--- a/ietf/nomcom/forms.py
+++ b/ietf/nomcom/forms.py
@@ -40,12 +40,12 @@ class PositionNomineeField(forms.ChoiceField):
         results = []
         for position in positions:
             accepted_nominees = [np.nominee for np in NomineePosition.objects.filter(position=position,state='accepted').exclude(nominee__duplicated__isnull=False)]
-            nominees = [('%s_%s' % (position.id, i.id), six.ensure_text(i)) for i in accepted_nominees]
+            nominees = [('%s_%s' % (position.id, i.id), six.text_type(i)) for i in accepted_nominees]
             if nominees:
                 results.append((position.name+" (Accepted)", nominees))
         for position in positions:
             other_nominees = [np.nominee for np in NomineePosition.objects.filter(position=position).exclude(state='accepted').exclude(nominee__duplicated__isnull=False)]
-            nominees = [('%s_%s' % (position.id, i.id), six.ensure_text(i)) for i in other_nominees]
+            nominees = [('%s_%s' % (position.id, i.id), six.text_type(i)) for i in other_nominees]
             if nominees:
                 results.append((position.name+" (Declined or Pending)", nominees))
         kwargs['choices'] = results
diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py
index 49ada547b..7b13ee897 100644
--- a/ietf/nomcom/tests.py
+++ b/ietf/nomcom/tests.py
@@ -7,7 +7,6 @@ from __future__ import absolute_import, print_function, unicode_literals
 import datetime
 import io
 import random
-import six
 import shutil
 
 from pyquery import PyQuery
@@ -16,9 +15,10 @@ from six.moves.urllib.parse import urlparse
 from django.db import IntegrityError
 from django.db.models import Max
 from django.conf import settings
-from django.urls import reverse
 from django.core.files import File
 from django.contrib.auth.models import User
+from django.urls import reverse
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -526,7 +526,7 @@ class NomcomViewsTest(TestCase):
         self.assertEqual('Nomination receipt', outbox[-1]['Subject'])
         self.assertEqual(self.email_from, outbox[-1]['From'])
         self.assertIn('plain', outbox[-1]['To'])
-        self.assertIn('Comments with accents äöå', six.ensure_text(outbox[-1].get_payload(decode=True),"utf-8","replace"))
+        self.assertIn('Comments with accents äöå', force_text(outbox[-1].get_payload(decode=True),"utf-8","replace"))
 
         # Nominate the same person for the same position again without asking for confirmation 
 
@@ -567,7 +567,7 @@ class NomcomViewsTest(TestCase):
         self.assertEqual('Nomination receipt', outbox[-1]['Subject'])
         self.assertEqual(self.email_from, outbox[-1]['From'])
         self.assertIn('plain', outbox[-1]['To'])
-        self.assertIn('Comments with accents äöå', six.ensure_text(outbox[-1].get_payload(decode=True),"utf-8","replace"))
+        self.assertIn('Comments with accents äöå', force_text(outbox[-1].get_payload(decode=True),"utf-8","replace"))
 
         # Nominate the same person for the same position again without asking for confirmation 
 
@@ -812,7 +812,7 @@ class NomcomViewsTest(TestCase):
         self.assertNotIn('$', email_body)
         self.assertEqual(self.email_from, outbox[-2]['From'])
         self.assertIn('plain', outbox[2]['To'])
-        self.assertIn('Comments with accents äöå', six.ensure_text(outbox[2].get_payload(decode=True),"utf-8","replace"))
+        self.assertIn('Comments with accents äöå', force_text(outbox[2].get_payload(decode=True),"utf-8","replace"))
 
         empty_outbox()
         self.feedback_view(public=True)
diff --git a/ietf/nomcom/utils.py b/ietf/nomcom/utils.py
index 1d76fa11d..5f8da9b06 100644
--- a/ietf/nomcom/utils.py
+++ b/ietf/nomcom/utils.py
@@ -22,7 +22,7 @@ from django.core.exceptions import ObjectDoesNotExist
 from django.urls import reverse
 from django.template.loader import render_to_string
 from django.shortcuts import get_object_or_404
-from django.utils.encoding import force_str
+from django.utils.encoding import force_str, force_text
 
 from ietf.dbtemplate.models import DBTemplate
 from ietf.person.models import Email, Person
@@ -433,7 +433,7 @@ def get_body(message):
         body = []
         for part in text_parts:
             charset = get_charset(part, get_charset(message))
-            body.append(six.ensure_text(part.get_payload(decode=True),
+            body.append(force_text(part.get_payload(decode=True),
                                 charset,
                                 "replace"))
 
@@ -441,7 +441,7 @@ def get_body(message):
 
     else:  # if it is not multipart, the payload will be a string
            # representing the message body
-        body = six.ensure_text(message.get_payload(decode=True),
+        body = force_text(message.get_payload(decode=True),
                        get_charset(message),
                        "replace")
         return body.strip()
diff --git a/ietf/person/factories.py b/ietf/person/factories.py
index 0dca61037..e076b4ef7 100644
--- a/ietf/person/factories.py
+++ b/ietf/person/factories.py
@@ -10,13 +10,13 @@ import faker.config
 import os
 import random
 import shutil
-import six
 
 from unidecode import unidecode
 
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.utils.text import slugify
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -58,7 +58,7 @@ class PersonFactory(factory.DjangoModelFactory):
 
     user = factory.SubFactory(UserFactory)
     name = factory.LazyAttribute(lambda p: normalize_name('%s %s'%(p.user.first_name, p.user.last_name)))
-    ascii = factory.LazyAttribute(lambda p: six.ensure_text(unidecode_name(p.name)))
+    ascii = factory.LazyAttribute(lambda p: force_text(unidecode_name(p.name)))
 
     class Params:
         with_bio = factory.Trait(biography = "\n\n".join(fake.paragraphs()))
diff --git a/ietf/person/fields.py b/ietf/person/fields.py
index f2ab5d756..1f1e79948 100644
--- a/ietf/person/fields.py
+++ b/ietf/person/fields.py
@@ -168,7 +168,7 @@ class PersonEmailChoiceField(forms.ModelChoiceField):
 
     def label_from_instance(self, email):
         if self.label_with == "person":
-            return six.ensure_text(email.person)
+            return six.text_type(email.person)
         elif self.label_with == "email":
             return email.address
         else:
diff --git a/ietf/person/models.py b/ietf/person/models.py
index 5025a900b..6e40686f8 100644
--- a/ietf/person/models.py
+++ b/ietf/person/models.py
@@ -86,7 +86,7 @@ class Person(models.Model):
         if not hasattr(self, '_cached_plain_ascii'):
             if self.ascii:
                 if isinstance(self.ascii, six.binary_type):
-                    uname = six.ensure_text(self.ascii)
+                    uname = six.text_type(self.ascii)
                     ascii = unidecode_name(uname)
                 else:
                     ascii = unidecode_name(self.ascii)
diff --git a/ietf/person/tests.py b/ietf/person/tests.py
index d4a2d9f67..410f89cbd 100644
--- a/ietf/person/tests.py
+++ b/ietf/person/tests.py
@@ -93,7 +93,7 @@ class PersonTests(TestCase):
         empty_outbox()
         p = PersonFactory(name="Föö Bär")
         PersonFactory(name=p.name)
-        self.assertTrue("possible duplicate" in six.ensure_text(outbox[0]["Subject"]).lower())
+        self.assertTrue("possible duplicate" in six.text_type(outbox[0]["Subject"]).lower())
 
     def test_merge(self):
         url = urlreverse("ietf.person.views.merge")
diff --git a/ietf/review/utils.py b/ietf/review/utils.py
index 236f85519..cfff82e8c 100644
--- a/ietf/review/utils.py
+++ b/ietf/review/utils.py
@@ -964,7 +964,7 @@ def make_assignment_choices(email_queryset, review_req):
         if stats:
             explanations.append(", ".join(stats))
 
-        label = six.ensure_text(e.person)
+        label = six.text_type(e.person)
         if explanations:
             label = "{}: {}".format(label, "; ".join(explanations))
 
diff --git a/ietf/secr/sreq/tests.py b/ietf/secr/sreq/tests.py
index 2725feae5..e95f592ae 100644
--- a/ietf/secr/sreq/tests.py
+++ b/ietf/secr/sreq/tests.py
@@ -184,14 +184,14 @@ class SubmitRequestCase(TestCase):
         r = self.client.post(url,post_data)
         self.assertEqual(r.status_code, 200)
         q = PyQuery(r.content)
-        self.assertTrue('Confirm' in six.ensure_text(q("title")))
+        self.assertTrue('Confirm' in six.text_type(q("title")))
         # confirm
         post_data['submit'] = 'Submit'
         r = self.client.post(confirm_url,post_data)
         self.assertRedirects(r, reverse('ietf.secr.sreq.views.main'))
         self.assertEqual(len(outbox),len_before+1)
         notification = outbox[-1]
-        notification_payload = six.ensure_text(notification.get_payload(decode=True),"utf-8","replace")
+        notification_payload = six.text_type(notification.get_payload(decode=True),"utf-8","replace")
         session = Session.objects.get(meeting=meeting,group=group)
         self.assertEqual(session.resources.count(),1)
         self.assertEqual(session.people_constraints.count(),1)
diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py
index 4463cb367..d87d73885 100644
--- a/ietf/submit/tests.py
+++ b/ietf/submit/tests.py
@@ -19,7 +19,7 @@ from pyquery import PyQuery
 
 from django.conf import settings
 from django.urls import reverse as urlreverse
-from django.utils.encoding import force_str
+from django.utils.encoding import force_str, force_text
 
 import debug                            # pyflakes:ignore
 
@@ -38,7 +38,7 @@ from ietf.person.models import Person
 from ietf.person.factories import UserFactory, PersonFactory
 from ietf.submit.models import Submission, Preapproval
 from ietf.submit.mail import add_submission_email, process_response_email
-from ietf.utils.mail import outbox, empty_outbox
+from ietf.utils.mail import outbox, empty_outbox, get_payload
 from ietf.utils.models import VersionInfo
 from ietf.utils.test_utils import login_testing_unauthorized, TestCase
 from ietf.utils.draft import Draft
@@ -296,16 +296,16 @@ class SubmitTests(TestCase):
         self.assertTrue(draft.relations_that_doc("possibly-replaces").first().target, sug_replaced_alias)
         self.assertEqual(len(outbox), mailbox_before + 5)
         self.assertIn(("I-D Action: %s" % name), outbox[-4]["Subject"])
-        self.assertIn(author.ascii, six.ensure_text(outbox[-4]))
+        self.assertIn(author.ascii, get_payload(outbox[-4]))
         self.assertIn(("I-D Action: %s" % name), outbox[-3]["Subject"])
-        self.assertIn(author.ascii, six.ensure_text(outbox[-3]))
+        self.assertIn(author.ascii, get_payload(outbox[-3]))
         self.assertIn("New Version Notification",outbox[-2]["Subject"])
-        self.assertIn(name, six.ensure_text(outbox[-2]))
-        self.assertIn("mars", six.ensure_text(outbox[-2]))
+        self.assertIn(name, get_payload(outbox[-2]))
+        self.assertIn("mars", get_payload(outbox[-2]))
         # Check "Review of suggested possible replacements for..." mail
         self.assertIn("review", outbox[-1]["Subject"].lower())
-        self.assertIn(name, six.ensure_text(outbox[-1]))
-        self.assertIn(sug_replaced_alias.name, six.ensure_text(outbox[-1]))
+        self.assertIn(name, get_payload(outbox[-1]))
+        self.assertIn(sug_replaced_alias.name, get_payload(outbox[-1]))
         self.assertIn("ames-chairs@", outbox[-1]["To"].lower())
         self.assertIn("mars-chairs@", outbox[-1]["To"].lower())
 
@@ -413,7 +413,7 @@ class SubmitTests(TestCase):
         self.assertTrue("unknown-email-" not in confirm_email["To"])
         if change_authors:
             # Since authors changed, ensure chairs are copied (and that the message says why)
-            self.assertTrue("chairs have been copied" in six.ensure_text(confirm_email))
+            self.assertTrue("chairs have been copied" in six.text_type(confirm_email))
             if group_type in ['wg','rg','ag']:
                 self.assertTrue("mars-chairs@" in confirm_email["To"].lower())
             elif group_type == 'area':
@@ -423,7 +423,7 @@ class SubmitTests(TestCase):
             if stream_type=='ise':
                self.assertTrue("rfc-ise@" in confirm_email["To"].lower())
         else:
-            self.assertNotIn("chairs have been copied", six.ensure_text(confirm_email))
+            self.assertNotIn("chairs have been copied", six.text_type(confirm_email))
             self.assertNotIn("mars-chairs@", confirm_email["To"].lower())
 
         confirmation_url = self.extract_confirmation_url(confirm_email)
@@ -492,17 +492,17 @@ class SubmitTests(TestCase):
         self.assertEqual(len(outbox), mailbox_before + 3)
         self.assertTrue(("I-D Action: %s" % name) in outbox[-3]["Subject"])
         self.assertTrue(("I-D Action: %s" % name) in draft.message_set.order_by("-time")[0].subject)
-        self.assertTrue(author.ascii in six.ensure_text(outbox[-3]))
+        self.assertTrue(author.ascii in get_payload(outbox[-3]))
         self.assertTrue("i-d-announce@" in outbox[-3]['To'])
         self.assertTrue("New Version Notification" in outbox[-2]["Subject"])
-        self.assertTrue(name in six.ensure_text(outbox[-2]))
+        self.assertTrue(name in get_payload(outbox[-2]))
         interesting_address = {'ietf':'mars', 'irtf':'irtf-chair', 'iab':'iab-chair', 'ise':'rfc-ise'}[draft.stream_id]
-        self.assertTrue(interesting_address in six.ensure_text(outbox[-2]))
+        self.assertTrue(interesting_address in force_text(outbox[-2].as_string()))
         if draft.stream_id == 'ietf':
-            self.assertTrue(draft.ad.role_email("ad").address in six.ensure_text(outbox[-2]))
-            self.assertTrue(ballot_position.ad.role_email("ad").address in six.ensure_text(outbox[-2]))
+            self.assertTrue(draft.ad.role_email("ad").address in force_text(outbox[-2].as_string()))
+            self.assertTrue(ballot_position.ad.role_email("ad").address in force_text(outbox[-2].as_string()))
         self.assertTrue("New Version Notification" in outbox[-1]["Subject"])
-        self.assertTrue(name in six.ensure_text(outbox[-1]))
+        self.assertTrue(name in get_payload(outbox[-1]))
         r = self.client.get(urlreverse('ietf.doc.views_search.recent_drafts'))
         self.assertEqual(r.status_code, 200)
         self.assertContains(r, draft.name)
@@ -562,7 +562,7 @@ class SubmitTests(TestCase):
         # both submitter and author get email
         self.assertTrue(author.email().address.lower() in confirm_email["To"])
         self.assertTrue("submitter@example.com" in confirm_email["To"])
-        self.assertFalse("chairs have been copied" in six.ensure_text(confirm_email))
+        self.assertFalse("chairs have been copied" in six.text_type(confirm_email))
 
         confirmation_url = self.extract_confirmation_url(outbox[-1])
 
diff --git a/ietf/sync/rfceditor.py b/ietf/sync/rfceditor.py
index 6caf9ec87..609360215 100644
--- a/ietf/sync/rfceditor.py
+++ b/ietf/sync/rfceditor.py
@@ -552,6 +552,6 @@ def post_approved_draft(url, name):
         # catch everything so we don't leak exceptions, convert them
         # into string instead
         log("Exception on RFC-Editor notification for draft '%s': '%s'" % (name, e))
-        error = six.ensure_text(e)
+        error = six.text_type(e)
 
     return text, error
diff --git a/ietf/utils/admin.py b/ietf/utils/admin.py
index e01f1388c..ec141b78c 100644
--- a/ietf/utils/admin.py
+++ b/ietf/utils/admin.py
@@ -7,6 +7,8 @@ from __future__ import absolute_import, print_function, unicode_literals
 import six
 
 from django.contrib import admin
+from django.utils.encoding import force_text
+
 from ietf.utils.models import VersionInfo
 
 def name(obj):
@@ -16,10 +18,10 @@ def name(obj):
         if callable(obj.name):
             name = obj.name()
         else:
-            name = six.ensure_text(obj.name)
+            name = force_text(obj.name)
         if name:
             return name
-    return six.ensure_text(obj)
+    return six.text_type(obj)
     
 def admin_link(field, label=None, ordering="", display=name, suffix=""):
     if not label:
diff --git a/ietf/utils/mail.py b/ietf/utils/mail.py
index 4e3961bd5..91070b496 100644
--- a/ietf/utils/mail.py
+++ b/ietf/utils/mail.py
@@ -174,7 +174,7 @@ def mail_context(request):
         return RequestContext(request)
     else:
         return Context()
-  
+
 def send_mail(request, to, frm, subject, template, context, *args, **kwargs):
     '''
     Send an email to the destination [list], with the given return
@@ -321,7 +321,7 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F
     """Send MIME message with content already filled in."""
     
     condition_message(to, frm, subject, msg, cc, extra)
-
+    
     # start debug server with python -m smtpd -n -c DebuggingServer localhost:2025
     # then put USING_DEBUG_EMAIL_SERVER=True and EMAIL_HOST='localhost'
     # and EMAIL_PORT=2025 in settings_local.py
diff --git a/ietf/utils/pipe.py b/ietf/utils/pipe.py
index 62a67e671..e61fce373 100644
--- a/ietf/utils/pipe.py
+++ b/ietf/utils/pipe.py
@@ -26,7 +26,7 @@ def pipe(cmd, str=None):
         if str:
             out += str
         code = pipe.poll()
-        if code > -1:
+        if code != None:
             err = pipe.stderr.read()
             break
         if len(out) >= MAX:
diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py
index a54758148..8c778cb2b 100644
--- a/ietf/utils/tests.py
+++ b/ietf/utils/tests.py
@@ -29,6 +29,7 @@ from django.template.defaulttags import URLNode
 from django.template.loader import get_template
 from django.templatetags.static import StaticNode
 from django.urls import reverse as urlreverse
+from django.utils.encoding import force_text
 
 import debug                            # pyflakes:ignore
 
@@ -160,12 +161,12 @@ def get_callbacks(urllist):
             callbacks.update(get_callbacks(entry.url_patterns))
         else:
             if hasattr(entry, '_callback_str'):
-                callbacks.add(six.ensure_text(entry._callback_str))
+                callbacks.add(force_text(entry._callback_str))
             if (hasattr(entry, 'callback') and entry.callback
                 and type(entry.callback) in [types.FunctionType, types.MethodType ]):
                 callbacks.add("%s.%s" % (entry.callback.__module__, entry.callback.__name__))
             if hasattr(entry, 'name') and entry.name:
-                callbacks.add(six.ensure_text(entry.name))
+                callbacks.add(force_text(entry.name))
             # There are some entries we don't handle here, mostly clases
             # (such as Feed subclasses)
 
@@ -278,7 +279,7 @@ class TemplateChecksTestCase(TestCase):
         r = self.client.get(url)        
         self.assertTemplateUsed(r, '500.html')
 
-@skipIf(six.PY3, "Trac not available for Python3 as of 14 Jul 2019")
+@skipIf(True, "Trac not available for Python3 as of 14 Jul 2019")
 @skipIf(skip_wiki_glue_testing, skip_message)
 class TestWikiGlueManagementCommand(TestCase):
 
@@ -301,14 +302,18 @@ class TestWikiGlueManagementCommand(TestCase):
         set_coverage_checking(True)
 
     def test_wiki_create_output(self):
-        for type in ['wg','rg','ag','area']:
-            GroupFactory(type_id=type)
+        for group_type in ['wg','rg','ag','area']:
+            GroupFactory(type_id=group_type)
         groups = Group.objects.filter(
                         type__slug__in=['wg','rg','ag','area'],
                         state__slug='active'
                     ).order_by('acronym')
         out = six.StringIO()
         err = six.StringIO()
+        debug.type('self.wiki_dir_pattern')
+        debug.show('self.wiki_dir_pattern')
+        debug.type('self.svn_dir_pattern')
+        debug.show('self.svn_dir_pattern')
         call_command('create_group_wikis', stdout=out, stderr=err, verbosity=2,
             wiki_dir_pattern=self.wiki_dir_pattern,
             svn_dir_pattern=self.svn_dir_pattern,
@@ -419,13 +424,13 @@ class DraftTests(TestCase):
         self.assertEqual(self.draft.get_status(),'Informational')
     
     def test_get_authors(self):
-        self.assertTrue(all(['@' in author for author in self.draft.get_authors()]))
+        self.assertTrue(all([u'@' in author for author in self.draft.get_authors()]))
 
     def test_get_authors_with_firm(self):
-        self.assertTrue(all(['@' in author for author in self.draft.get_authors_with_firm()]))
+        self.assertTrue(all([u'@' in author for author in self.draft.get_authors_with_firm()]))
         
     def test_old_get_refs(self):
-        self.assertEqual(self.draft.old_get_refs()[1][0],'rfc2119')
+        self.assertEqual(self.draft.old_get_refs()[1][0],u'rfc2119')
 
     def test_get_meta(self):
         tempdir = mkdtemp()
diff --git a/requirements.txt b/requirements.txt
index bca7b425d..cedd99532 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -57,7 +57,7 @@ six>=1.9.0
 sqlparse>=0.2.2
 tblib>=1.3.0
 tqdm>=3.7.0
-#Trac>=1.2.3
+Trac>=1.2.3
 Unidecode>=0.4.18
 #wsgiref>=0.1.2
 xml2rfc>=2.9.3,!=2.6.0