You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2020/01/21 16:03:26 UTC

[allura] 04/12: [#7878] misc unicode fixes

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

brondsem pushed a commit to branch db/7878
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 41ec930cfd7cde10cc223b6197f286e62c67a6bc
Author: Dave Brondsema <db...@slashdotmedia.com>
AuthorDate: Thu Jan 16 21:27:12 2020 +0000

    [#7878] misc unicode fixes
---
 Allura/allura/lib/AsciiDammit.py                   | 258 ++++++++++-----------
 Allura/allura/lib/helpers.py                       |   4 +-
 Allura/allura/lib/macro.py                         |   4 +-
 Allura/allura/tests/model/test_filesystem.py       |   2 +-
 Allura/allura/tests/test_app.py                    |  10 +-
 Allura/allura/tests/test_helpers.py                |   8 +-
 Allura/allura/tests/test_mail_util.py              |   2 +-
 Allura/allura/tests/test_tasks.py                  |   2 +-
 Allura/allura/tests/unit/test_repo.py              |  27 ++-
 AlluraTest/alluratest/test_syntax.py               |   4 +-
 ForgeGit/forgegit/model/git_repo.py                |   8 +-
 ForgeGit/forgegit/tests/model/test_repository.py   |   4 +-
 ForgeSVN/forgesvn/model/svn.py                     |   2 +-
 .../forgetracker/tests/functional/test_root.py     |   3 +-
 ForgeWiki/forgewiki/tests/functional/test_rest.py  |   4 +-
 15 files changed, 174 insertions(+), 168 deletions(-)

diff --git a/Allura/allura/lib/AsciiDammit.py b/Allura/allura/lib/AsciiDammit.py
index 95d27dd..ea27a9f 100644
--- a/Allura/allura/lib/AsciiDammit.py
+++ b/Allura/allura/lib/AsciiDammit.py
@@ -26,134 +26,134 @@ __license__ = "Public domain"
 import re
 import types
 
-CHARS = {'\x80': ('EUR', 'euro'),
-         '\x81': ' ',
-         '\x82': (',', 'sbquo'),
-         '\x83': ('f', 'fnof'),
-         '\x84': (',,', 'bdquo'),
-         '\x85': ('...', 'hellip'),
-         '\x86': ('+', 'dagger'),
-         '\x87': ('++', 'Dagger'),
-         '\x88': ('^', 'caret'),
-         '\x89': '%',
-         '\x8A': ('S', 'Scaron'),
-         '\x8B': ('<', 'lt;'),
-         '\x8C': ('OE', 'OElig'),
-         '\x8D': '?',
-         '\x8E': 'Z',
-         '\x8F': '?',
-         '\x90': '?',
-         '\x91': ("'", 'lsquo'),
-         '\x92': ("'", 'rsquo'),
-         '\x93': ('"', 'ldquo'),
-         '\x94': ('"', 'rdquo'),
-         '\x95': ('*', 'bull'),
-         '\x96': ('-', 'ndash'),
-         '\x97': ('--', 'mdash'),
-         '\x98': ('~', 'tilde'),
-         '\x99': ('(TM)', 'trade'),
-         '\x9a': ('s', 'scaron'),
-         '\x9b': ('>', 'gt'),
-         '\x9c': ('oe', 'oelig'),
-         '\x9d': '?',
-         '\x9e': 'z',
-         '\x9f': ('Y', 'Yuml'),
-         '\xa0': (' ', 'nbsp'),
-         '\xa1': ('!', 'iexcl'),
-         '\xa2': ('c', 'cent'),
-         '\xa3': ('GBP', 'pound'),
-         '\xa4': ('$', 'curren'),  # This approximation is especially lame.
-         '\xa5': ('YEN', 'yen'),
-         '\xa6': ('|', 'brvbar'),
-         '\xa7': ('S', 'sect'),
-         '\xa8': ('..', 'uml'),
-         '\xa9': ('', 'copy'),
-         '\xaa': ('(th)', 'ordf'),
-         '\xab': ('<<', 'laquo'),
-         '\xac': ('!', 'not'),
-         '\xad': (' ', 'shy'),
-         '\xae': ('(R)', 'reg'),
-         '\xaf': ('-', 'macr'),
-         '\xb0': ('o', 'deg'),
-         '\xb1': ('+-', 'plusmm'),
-         '\xb2': ('2', 'sup2'),
-         '\xb3': ('3', 'sup3'),
-         '\xb4': ("'", 'acute'),
-         '\xb5': ('u', 'micro'),
-         '\xb6': ('P', 'para'),
-         '\xb7': ('*', 'middot'),
-         '\xb8': (',', 'cedil'),
-         '\xb9': ('1', 'sup1'),
-         '\xba': ('(th)', 'ordm'),
-         '\xbb': ('>>', 'raquo'),
-         '\xbc': ('1/4', 'frac14'),
-         '\xbd': ('1/2', 'frac12'),
-         '\xbe': ('3/4', 'frac34'),
-         '\xbf': ('?', 'iquest'),
-         '\xc0': ('A', "Agrave"),
-         '\xc1': ('A', "Aacute"),
-         '\xc2': ('A', "Acirc"),
-         '\xc3': ('A', "Atilde"),
-         '\xc4': ('A', "Auml"),
-         '\xc5': ('A', "Aring"),
-         '\xc6': ('AE', "Aelig"),
-         '\xc7': ('C', "Ccedil"),
-         '\xc8': ('E', "Egrave"),
-         '\xc9': ('E', "Eacute"),
-         '\xca': ('E', "Ecirc"),
-         '\xcb': ('E', "Euml"),
-         '\xcc': ('I', "Igrave"),
-         '\xcd': ('I', "Iacute"),
-         '\xce': ('I', "Icirc"),
-         '\xcf': ('I', "Iuml"),
-         '\xd0': ('D', "Eth"),
-         '\xd1': ('N', "Ntilde"),
-         '\xd2': ('O', "Ograve"),
-         '\xd3': ('O', "Oacute"),
-         '\xd4': ('O', "Ocirc"),
-         '\xd5': ('O', "Otilde"),
-         '\xd6': ('O', "Ouml"),
-         '\xd7': ('*', "times"),
-         '\xd8': ('O', "Oslash"),
-         '\xd9': ('U', "Ugrave"),
-         '\xda': ('U', "Uacute"),
-         '\xdb': ('U', "Ucirc"),
-         '\xdc': ('U', "Uuml"),
-         '\xdd': ('Y', "Yacute"),
-         '\xde': ('b', "Thorn"),
-         '\xdf': ('B', "szlig"),
-         '\xe0': ('a', "agrave"),
-         '\xe1': ('a', "aacute"),
-         '\xe2': ('a', "acirc"),
-         '\xe3': ('a', "atilde"),
-         '\xe4': ('a', "auml"),
-         '\xe5': ('a', "aring"),
-         '\xe6': ('ae', "aelig"),
-         '\xe7': ('c', "ccedil"),
-         '\xe8': ('e', "egrave"),
-         '\xe9': ('e', "eacute"),
-         '\xea': ('e', "ecirc"),
-         '\xeb': ('e', "euml"),
-         '\xec': ('i', "igrave"),
-         '\xed': ('i', "iacute"),
-         '\xee': ('i', "icirc"),
-         '\xef': ('i', "iuml"),
-         '\xf0': ('o', "eth"),
-         '\xf1': ('n', "ntilde"),
-         '\xf2': ('o', "ograve"),
-         '\xf3': ('o', "oacute"),
-         '\xf4': ('o', "ocirc"),
-         '\xf5': ('o', "otilde"),
-         '\xf6': ('o', "ouml"),
-         '\xf7': ('/', "divide"),
-         '\xf8': ('o', "oslash"),
-         '\xf9': ('u', "ugrave"),
-         '\xfa': ('u', "uacute"),
-         '\xfb': ('u', "ucirc"),
-         '\xfc': ('u', "uuml"),
-         '\xfd': ('y', "yacute"),
-         '\xfe': ('b', "thorn"),
-         '\xff': ('y', "yuml"),
+CHARS = {b'\x80': ('EUR', 'euro'),
+         b'\x81': ' ',
+         b'\x82': (',', 'sbquo'),
+         b'\x83': ('f', 'fnof'),
+         b'\x84': (',,', 'bdquo'),
+         b'\x85': ('...', 'hellip'),
+         b'\x86': ('+', 'dagger'),
+         b'\x87': ('++', 'Dagger'),
+         b'\x88': ('^', 'caret'),
+         b'\x89': '%',
+         b'\x8A': ('S', 'Scaron'),
+         b'\x8B': ('<', 'lt;'),
+         b'\x8C': ('OE', 'OElig'),
+         b'\x8D': '?',
+         b'\x8E': 'Z',
+         b'\x8F': '?',
+         b'\x90': '?',
+         b'\x91': ("'", 'lsquo'),
+         b'\x92': ("'", 'rsquo'),
+         b'\x93': ('"', 'ldquo'),
+         b'\x94': ('"', 'rdquo'),
+         b'\x95': ('*', 'bull'),
+         b'\x96': ('-', 'ndash'),
+         b'\x97': ('--', 'mdash'),
+         b'\x98': ('~', 'tilde'),
+         b'\x99': ('(TM)', 'trade'),
+         b'\x9a': ('s', 'scaron'),
+         b'\x9b': ('>', 'gt'),
+         b'\x9c': ('oe', 'oelig'),
+         b'\x9d': '?',
+         b'\x9e': 'z',
+         b'\x9f': ('Y', 'Yuml'),
+         b'\xa0': (' ', 'nbsp'),
+         b'\xa1': ('!', 'iexcl'),
+         b'\xa2': ('c', 'cent'),
+         b'\xa3': ('GBP', 'pound'),
+         b'\xa4': ('$', 'curren'),  # This approximation is especially lame.
+         b'\xa5': ('YEN', 'yen'),
+         b'\xa6': ('|', 'brvbar'),
+         b'\xa7': ('S', 'sect'),
+         b'\xa8': ('..', 'uml'),
+         b'\xa9': ('', 'copy'),
+         b'\xaa': ('(th)', 'ordf'),
+         b'\xab': ('<<', 'laquo'),
+         b'\xac': ('!', 'not'),
+         b'\xad': (' ', 'shy'),
+         b'\xae': ('(R)', 'reg'),
+         b'\xaf': ('-', 'macr'),
+         b'\xb0': ('o', 'deg'),
+         b'\xb1': ('+-', 'plusmm'),
+         b'\xb2': ('2', 'sup2'),
+         b'\xb3': ('3', 'sup3'),
+         b'\xb4': ("'", 'acute'),
+         b'\xb5': ('u', 'micro'),
+         b'\xb6': ('P', 'para'),
+         b'\xb7': ('*', 'middot'),
+         b'\xb8': (',', 'cedil'),
+         b'\xb9': ('1', 'sup1'),
+         b'\xba': ('(th)', 'ordm'),
+         b'\xbb': ('>>', 'raquo'),
+         b'\xbc': ('1/4', 'frac14'),
+         b'\xbd': ('1/2', 'frac12'),
+         b'\xbe': ('3/4', 'frac34'),
+         b'\xbf': ('?', 'iquest'),
+         b'\xc0': ('A', "Agrave"),
+         b'\xc1': ('A', "Aacute"),
+         b'\xc2': ('A', "Acirc"),
+         b'\xc3': ('A', "Atilde"),
+         b'\xc4': ('A', "Auml"),
+         b'\xc5': ('A', "Aring"),
+         b'\xc6': ('AE', "Aelig"),
+         b'\xc7': ('C', "Ccedil"),
+         b'\xc8': ('E', "Egrave"),
+         b'\xc9': ('E', "Eacute"),
+         b'\xca': ('E', "Ecirc"),
+         b'\xcb': ('E', "Euml"),
+         b'\xcc': ('I', "Igrave"),
+         b'\xcd': ('I', "Iacute"),
+         b'\xce': ('I', "Icirc"),
+         b'\xcf': ('I', "Iuml"),
+         b'\xd0': ('D', "Eth"),
+         b'\xd1': ('N', "Ntilde"),
+         b'\xd2': ('O', "Ograve"),
+         b'\xd3': ('O', "Oacute"),
+         b'\xd4': ('O', "Ocirc"),
+         b'\xd5': ('O', "Otilde"),
+         b'\xd6': ('O', "Ouml"),
+         b'\xd7': ('*', "times"),
+         b'\xd8': ('O', "Oslash"),
+         b'\xd9': ('U', "Ugrave"),
+         b'\xda': ('U', "Uacute"),
+         b'\xdb': ('U', "Ucirc"),
+         b'\xdc': ('U', "Uuml"),
+         b'\xdd': ('Y', "Yacute"),
+         b'\xde': ('b', "Thorn"),
+         b'\xdf': ('B', "szlig"),
+         b'\xe0': ('a', "agrave"),
+         b'\xe1': ('a', "aacute"),
+         b'\xe2': ('a', "acirc"),
+         b'\xe3': ('a', "atilde"),
+         b'\xe4': ('a', "auml"),
+         b'\xe5': ('a', "aring"),
+         b'\xe6': ('ae', "aelig"),
+         b'\xe7': ('c', "ccedil"),
+         b'\xe8': ('e', "egrave"),
+         b'\xe9': ('e', "eacute"),
+         b'\xea': ('e', "ecirc"),
+         b'\xeb': ('e', "euml"),
+         b'\xec': ('i', "igrave"),
+         b'\xed': ('i', "iacute"),
+         b'\xee': ('i', "icirc"),
+         b'\xef': ('i', "iuml"),
+         b'\xf0': ('o', "eth"),
+         b'\xf1': ('n', "ntilde"),
+         b'\xf2': ('o', "ograve"),
+         b'\xf3': ('o', "oacute"),
+         b'\xf4': ('o', "ocirc"),
+         b'\xf5': ('o', "otilde"),
+         b'\xf6': ('o', "ouml"),
+         b'\xf7': ('/', "divide"),
+         b'\xf8': ('o', "oslash"),
+         b'\xf9': ('u', "ugrave"),
+         b'\xfa': ('u', "uacute"),
+         b'\xfb': ('u', "ucirc"),
+         b'\xfc': ('u', "uuml"),
+         b'\xfd': ('y', "yacute"),
+         b'\xfe': ('b', "thorn"),
+         b'\xff': ('y', "yuml"),
          }
 
 
@@ -213,7 +213,7 @@ def demoronise(t):
 
 if __name__ == '__main__':
 
-    french = '\x93Sacr\xe9 bleu!\x93'
+    french = b'\x93Sacr\xe9 bleu!\x93'
     print "First we mangle some French."
     print asciiDammit(french)
     print htmlDammit(french)
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index c204aaf..c39ee78 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -724,7 +724,7 @@ def render_any_markup(name, txt, code_mode=False, linenumbers_style=TABLE):
     renders any other markup format using the pypeline
     Returns jinja-safe text
     """
-    if txt == '':
+    if not txt:
         txt = '<p><em>Empty File</em></p>'
     else:
         fmt = g.pypeline_markup.can_render(name)
@@ -970,7 +970,7 @@ class exceptionless(object):
                         'Error calling %s(args=%s, kwargs=%s): %s',
                         fname, args, kwargs, str(e))
                 return self.error_result
-        inner.__name__ = fname
+        inner.__name__ = str(fname)
         return inner
 
 
diff --git a/Allura/allura/lib/macro.py b/Allura/allura/lib/macro.py
index 4a2ec43..911be84 100644
--- a/Allura/allura/lib/macro.py
+++ b/Allura/allura/lib/macro.py
@@ -453,8 +453,8 @@ def members(limit=20):
 def embed(url=None):
     consumer = oembed.OEmbedConsumer()
     endpoint = oembed.OEmbedEndpoint('http://www.youtube.com/oembed',
-                                     ['http://*.youtube.com/*', 'https://*.youtube.com/*',
-                                      'http://*.youtube-nocookie.com/*', 'https://*.youtube-nocookie.com/*',
+                                     [str('http://*.youtube.com/*'), str('https://*.youtube.com/*'),
+                                      str('http://*.youtube-nocookie.com/*'), str('https://*.youtube-nocookie.com/*'),
                                       ])
     consumer.addEndpoint(endpoint)
 
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index 665ec22..f8f1e7c 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -116,7 +116,7 @@ class TestFile(TestCase):
         assert self.db.fs.chunks.count() == 1
         self._assert_content(f, 'test1')
         with f.wfile() as fp:
-            fp.write('test2')
+            fp.write(b'test2')
         self.session.flush()
         assert self.db.fs.count() == 1
         assert self.db.fs.files.count() == 2
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index 25e39c2..8ea1b68 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -139,17 +139,17 @@ def test_handle_artifact_unicode(qg):
 
     a = app.Application(c.project, c.app.config)
 
-    msg = dict(payload='foo ƒ†©¥˙¨ˆ', message_id=1, headers={})
+    msg = dict(payload='foo ƒ†©¥˙¨ˆ'.encode('utf-8'), message_id=1, headers={})
     a.handle_artifact_message(ticket, msg)
-    assert_equal(post.attach.call_args[0][1].getvalue(), 'foo ƒ†©¥˙¨ˆ')
+    assert_equal(post.attach.call_args[0][1].getvalue(), 'foo ƒ†©¥˙¨ˆ'.encode('utf-8'))
 
-    msg = dict(payload='foo', message_id=1, headers={})
+    msg = dict(payload='foo'.encode('utf-8'), message_id=1, headers={})
     a.handle_artifact_message(ticket, msg)
     assert_equal(post.attach.call_args[0][1].getvalue(), 'foo')
 
-    msg = dict(payload="\x94my quote\x94", message_id=1, headers={})
+    msg = dict(payload="\x94my quote\x94".encode('utf-8'), message_id=1, headers={})
     a.handle_artifact_message(ticket, msg)
-    assert_equal(post.attach.call_args[0][1].getvalue(), '\x94my quote\x94')
+    assert_equal(post.attach.call_args[0][1].getvalue(), '\x94my quote\x94'.encode('utf-8'))
 
     # assert against prod example
     msg_raw = """Message-Id: <15...@webmail.messagingengine.com>
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 73f8fe4..873e82f 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -89,16 +89,18 @@ def test_escape_json():
 
 def test_really_unicode():
     here_dir = path.dirname(__file__)
-    s = h.really_unicode('\xef\xbb\xbf<?xml version="1.0" encoding="utf-8" ?>')
-    assert s.startswith('\ufeff')
+    s = h.really_unicode(b'\xef\xbb\xbf<?xml version="1.0" encoding="utf-8" ?>')
+    assert s.startswith('\ufeff'), repr(s)
     s = h.really_unicode(
         open(path.join(here_dir, 'data/unicode_test.txt')).read())
     assert isinstance(s, six.text_type)
     # try non-ascii string in legacy 8bit encoding
     h.really_unicode('\u0410\u0401'.encode('cp1251'))
     # ensure invalid encodings are handled gracefully
-    s = h._attempt_encodings('foo', ['LKDJFLDK'])
+    s = h._attempt_encodings(b'foo', ['LKDJFLDK'])
     assert isinstance(s, six.text_type)
+    # unicode stays the same
+    assert_equals(h.really_unicode('¬∂•°‹'), '¬∂•°‹')
 
 
 def test_find_project():
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index eba9b8b..bdae63f 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -216,7 +216,7 @@ class TestHeader(object):
 
     @raises(TypeError)
     def test_bytestring(self):
-        our_header = Header('[asdf2:wiki] Discussion for Home page')
+        our_header = Header(b'[asdf2:wiki] Discussion for Home page')
         assert_equal(str(our_header), '[asdf2:wiki] Discussion for Home page')
 
     def test_ascii(self):
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index e9c966b..74c9372 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -591,7 +591,7 @@ def raise_exc():
     errs = []
     for x in range(10):
         try:
-            assert False, 'assert %d' % x
+            assert False, str('assert %d' % x)
         except:
             errs.append(sys.exc_info())
     raise CompoundError(*errs)
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index 1e20c59..83827e5 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -18,6 +18,8 @@
 from __future__ import unicode_literals
 import datetime
 import unittest
+
+import six
 from mock import patch, Mock, MagicMock, call
 from nose.tools import assert_equal
 from datadiff import tools as dd
@@ -109,18 +111,18 @@ class TestBlob(unittest.TestCase):
 
     def test_has_html_view_text_mime(self):
         blob = M.repository.Blob(MagicMock(), 'INSTALL', 'blob1')
-        blob.content_type = 'text/plain'
+        blob.content_type = b'text/plain'
         assert_equal(blob.has_html_view, True)
 
     def test_has_html_view_text_ext(self):
         blob = M.repository.Blob(MagicMock(), 'INSTALL.txt', 'blob1')
-        blob.content_type = 'foo/bar'
+        blob.content_type = b'foo/bar'
         assert_equal(blob.has_html_view, True)
 
     def test_has_html_view_text_contents(self):
         blob = M.repository.Blob(MagicMock(), 'INSTALL', 'blob1')
-        blob.content_type = 'foo/bar'
-        blob.text = 'hello world, this is text here'
+        blob.content_type = b'foo/bar'
+        blob.text = b'hello world, this is text here'
         assert_equal(blob.has_html_view, True)
 
     def test_has_html_view_bin_ext(self):
@@ -129,14 +131,14 @@ class TestBlob(unittest.TestCase):
 
     def test_has_html_view_bin_content(self):
         blob = M.repository.Blob(MagicMock(), 'myfile', 'blob1')
-        blob.content_type = 'whatever'
-        blob.text = '\0\0\0\0'
+        blob.content_type = b'whatever'
+        blob.text = b'\0\0\0\0'
         assert_equal(blob.has_html_view, False)
 
     def test_has_html_view__local_setting_override_bin(self):
         blob = M.repository.Blob(MagicMock(), 'myfile.dat', 'blob1')
-        blob.content_type = 'whatever'
-        blob.text = '\0\0\0\0'
+        blob.content_type = b'whatever'
+        blob.text = b'\0\0\0\0'
         blob.repo._additional_viewable_extensions = ['.dat']
         assert_equal(blob.has_html_view, True)
 
@@ -276,10 +278,11 @@ class TestZipDir(unittest.TestCase):
         with self.assertRaises(Exception) as cm:
             zipdir(src, zipfile)
         emsg = str(cm.exception)
-        self.assertTrue(
-            "Command: "
-            "['/bin/zip', '-y', '-q', '-r', '/fake/zip/file.tmp', 'repo'] "
-            "returned non-zero exit code 1" in emsg)
+        self.assertIn(
+            "Command: " +
+            ("['/bin/zip', '-y', '-q', '-r', '/fake/zip/file.tmp', 'repo'] " if six.PY3 else
+             "[u'/bin/zip', u'-y', u'-q', u'-r', u'/fake/zip/file.tmp', u'repo'] ") +
+            "returned non-zero exit code 1", emsg)
         self.assertTrue("STDOUT: 1" in emsg)
         self.assertTrue("STDERR: 2" in emsg)
 
diff --git a/AlluraTest/alluratest/test_syntax.py b/AlluraTest/alluratest/test_syntax.py
index 7b06d62..a6f5fff 100644
--- a/AlluraTest/alluratest/test_syntax.py
+++ b/AlluraTest/alluratest/test_syntax.py
@@ -114,11 +114,11 @@ def create_many_lint_methods():
             continue
 
         lint_test_method = lambda self, these_files=files: run_linter(these_files)
-        lint_test_method.__name__ = 'test_pylint_{}'.format(i)
+        lint_test_method.__name__ = str('test_pylint_{}'.format(i))
         setattr(TestLinters, 'test_pylint_{}'.format(i), lint_test_method)
 
         pyflake_test_method = lambda self, these_files=files: run_pyflakes(these_files)
-        pyflake_test_method.__name__ = 'test_pyflakes_{}'.format(i)
+        pyflake_test_method.__name__ = str('test_pyflakes_{}'.format(i))
         setattr(TestLinters, 'test_pyflakes_{}'.format(i), pyflake_test_method)
 
 
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 67e0081..26f8bae 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -490,7 +490,7 @@ class GitImplementation(M.RepositoryImplementation):
     def _object(self, oid):
         evens = oid[::2]
         odds = oid[1::2]
-        binsha = ''
+        binsha = b''
         for e, o in zip(evens, odds):
             binsha += chr(int(e + o, 16))
         return git.Object.new_from_sha(self._git, binsha)
@@ -772,17 +772,17 @@ class _OpenedGitBlob(object):
         '''
         Yields one line at a time, reading from the stream
         '''
-        buffer = ''
+        buffer = b''
         while True:
             # Replenish buffer until we have a line break
-            while '\n' not in buffer:
+            while b'\n' not in buffer:
                 chars = self._stream.read(self.CHUNK_SIZE)
                 if not chars:
                     break
                 buffer += chars
             if not buffer:
                 break
-            eol = buffer.find('\n')
+            eol = buffer.find(b'\n')
             if eol == -1:
                 # end without \n
                 yield buffer
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 5799c72..fed9243 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -455,9 +455,9 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
                 pass
         multipart_msg = sendmail.call_args_list[0][0][6]
         text_msg = sendmail.call_args_list[1][0][6]
-        text_body = text_msg.get_payload(decode=True)
+        text_body = text_msg.get_payload(decode=True).decode('utf-8')
         html_body = email.iterators.typed_subpart_iterator(multipart_msg, 'text', 'html').next()\
-            .get_payload(decode=True)
+            .get_payload(decode=True).decode('utf-8')
 
         # no extra HTML in commit messages
         assert_in('''-----
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index b9f1ecc..b8c835c 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -703,7 +703,7 @@ class SVNImplementation(M.RepositoryImplementation):
         try:
             # need to set system locale to handle all symbols in filename
             import locale
-            locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
+            locale.setlocale(locale.LC_ALL, str('en_US.UTF-8'))
             self._svn.export(path,
                              tmpdest,
                              revision=pysvn.Revision(
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 8a62959..ede3637 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -53,6 +53,7 @@ from forgetracker import model as tm
 from allura.lib.security import has_access, Credentials
 from allura.lib import helpers as h
 from allura.lib.search import SearchError
+from allura.lib.utils import urlencode
 from allura.tests import decorators as td
 from allura.tasks import mail_tasks
 from ming.orm.ormsession import ThreadLocalORMSession
@@ -1380,7 +1381,7 @@ class TestFunctionalController(TrackerTestController):
 
     def test_search_with_strange_chars(self):
         r = self.app.get('/p/test/bugs/search/?' +
-                         urllib.urlencode({'q': 'tést'}))
+                         urlencode({'q': 'tést'}))
         assert 'Search bugs: tést' in r
 
     def test_saved_search_with_strange_chars(self):
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 9e804a7..7d2e795 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -116,8 +116,8 @@ class TestWikiApi(TestRestApiBase):
         assert_equal(r.json['text'], 'foo <img src=x onerror=alert(1)> bar')
 
     def test_json_encoding_directly(self):
-        # used in @expose('json')
-        assert_equal(tg.jsonify.encode('<'), '"\\u003C"')
+        # used in @expose('json'), monkey-patched in our patches.py
+        assert_equal(tg.jsonify.encode('<'), '"\u003C"')
         # make sure these are unchanged
         assert_equal(json.dumps('<'), '"<"')