File sqlalchemy2.patch of Package python-pecan

From 3c4e8488b6bf0db895ca3edbe51016e5026b92a7 Mon Sep 17 00:00:00 2001
From: Ryan Petrello <ryan@ryanpetrello.com>
Date: Fri, 17 Mar 2023 09:47:07 -0400
Subject: [PATCH] remove six as a requirement, and add support for SQLAlchemy
 2.0

---
 pecan/commands/base.py                       |   4 +-
 pecan/commands/shell.py                      |   2 +-
 pecan/compat/__init__.py                     |  21 +-
 pecan/configuration.py                       |  26 +-
 pecan/core.py                                |  29 +-
 pecan/decorators.py                          |   6 +-
 pecan/hooks.py                               |   4 +-
 pecan/jsonify.py                             |  29 +-
 pecan/middleware/debug.py                    |   9 +-
 pecan/middleware/errordocument.py            |   9 +-
 pecan/middleware/static.py                   |   8 +-
 pecan/rest.py                                |   8 +-
 pecan/routing.py                             |   5 +-
 pecan/scaffolds/__init__.py                  |  15 +-
 pecan/secure.py                              |  20 +-
 pecan/tests/middleware/test_errordocument.py |  19 +-
 pecan/tests/middleware/test_recursive.py     |   7 +-
 pecan/tests/scaffold_builder.py              |   4 +-
 pecan/tests/test_base.py                     | 377 +++++++++----------
 pecan/tests/test_conf.py                     |   6 +-
 pecan/tests/test_generic.py                  |  12 +-
 pecan/tests/test_hooks.py                    |  67 ++--
 pecan/tests/test_jsonify.py                  |  19 +-
 pecan/tests/test_no_thread_locals.py         | 250 ++++++------
 pecan/tests/test_rest.py                     | 265 +++++++------
 pecan/tests/test_scaffolds.py                |   3 +-
 pecan/tests/test_secure.py                   |  39 +-
 pecan/tests/test_templating.py               |   4 +-
 pecan/util.py                                |   8 +-
 requirements.txt                             |   1 -
 setup.py                                     |   2 +-
 34 files changed, 616 insertions(+), 689 deletions(-)


diff --git a/pecan/commands/base.py b/pecan/commands/base.py
index 441d577..b1a25e8 100644
--- a/pecan/commands/base.py
+++ b/pecan/commands/base.py
@@ -4,8 +4,6 @@
 import sys
 from warnings import warn
 
-import six
-
 log = logging.getLogger(__name__)
 
 
@@ -81,7 +79,7 @@ def parse_sub_commands(self):
             )
             for arg in getattr(cmd, 'arguments', tuple()):
                 arg = arg.copy()
-                if isinstance(arg.get('name'), six.string_types):
+                if isinstance(arg.get('name'), str):
                     sub.add_argument(arg.pop('name'), **arg)
                 elif isinstance(arg.get('name'), list):
                     sub.add_argument(*arg.pop('name'), **arg)
diff --git a/pecan/commands/shell.py b/pecan/commands/shell.py
index 00a0521..d09fb6f 100644
--- a/pecan/commands/shell.py
+++ b/pecan/commands/shell.py
@@ -141,7 +141,7 @@ def run(self, args):
         banner += '  %-10s - This project\'s WSGI App instance\n' % 'wsgiapp'
         banner += '  %-10s - The current configuration\n' % 'conf'
         if TestApp:
-            banner += '  %-10s - webtest.TestApp wrapped around wsgiapp\n' % 'app'
+            banner += '  %-10s - webtest.TestApp wrapped around wsgiapp\n' % 'app'  # noqa
         if model:
             model_name = getattr(
                 model,
diff --git a/pecan/compat/__init__.py b/pecan/compat/__init__.py
index 650929b..995abc5 100644
--- a/pecan/compat/__init__.py
+++ b/pecan/compat/__init__.py
@@ -1,23 +1,14 @@
 import inspect
 
-import six
-
-if six.PY3:
-    import urllib.parse as urlparse
-    from urllib.parse import quote, unquote_plus
-    from urllib.request import urlopen, URLError
-    from html import escape
-    izip = zip
-else:
-    import urlparse  # noqa
-    from urllib import quote, unquote_plus  # noqa
-    from urllib2 import urlopen, URLError  # noqa
-    from cgi import escape  # noqa
-    from itertools import izip
+import urllib.parse as urlparse  # noqa
+from urllib.parse import quote, unquote_plus  # noqa
+from urllib.request import urlopen, URLError  # noqa
+from html import escape  # noqa
+izip = zip
 
 
 def is_bound_method(ob):
-    return inspect.ismethod(ob) and six.get_method_self(ob) is not None
+    return inspect.ismethod(ob) and ob.__self__ is not None
 
 
 def getargspec(func):
diff --git a/pecan/configuration.py b/pecan/configuration.py
index 0221a68..50531ff 100644
--- a/pecan/configuration.py
+++ b/pecan/configuration.py
@@ -2,13 +2,7 @@
 import inspect
 import os
 import sys
-
-import six
-
-if six.PY3:
-    from importlib.machinery import SourceFileLoader
-else:
-    import imp
+from importlib.machinery import SourceFileLoader
 
 
 IDENTIFIER = re.compile(r'[a-z_](\w)*$', re.IGNORECASE)
@@ -63,7 +57,7 @@ def update(self, conf_dict):
         '''
 
         if isinstance(conf_dict, dict):
-            iterator = six.iteritems(conf_dict)
+            iterator = iter(conf_dict.items())
         else:
             iterator = iter(conf_dict)
 
@@ -134,14 +128,14 @@ def __setitem__(self, key, value):
                 self.__values__[key] = ConfigDict(value)
             else:
                 self.__values__[key] = Config(value, filename=self.__file__)
-        elif isinstance(value, six.string_types) and '%(confdir)s' in value:
+        elif isinstance(value, str) and '%(confdir)s' in value:
             confdir = os.path.dirname(self.__file__) or os.getcwd()
             self.__values__[key] = value.replace('%(confdir)s', confdir)
         else:
             self.__values__[key] = value
 
     def __iter__(self):
-        return six.iteritems(self.__values__)
+        return iter(self.__values__.items())
 
     def __dir__(self):
         """
@@ -174,13 +168,7 @@ def conf_from_file(filepath):
     # This provides more verbose import-related error reporting than exec()
     absname, _ = os.path.splitext(abspath)
     basepath, module_name = absname.rsplit(os.sep, 1)
-    if six.PY3:
-        SourceFileLoader(module_name, abspath).load_module(module_name)
-    else:
-        imp.load_module(
-            module_name,
-            *imp.find_module(module_name, [basepath])
-        )
+    SourceFileLoader(module_name, abspath).load_module(module_name)
 
     # If we were able to import as a module, actually exec the compiled code
     exec(compiled, globals(), conf_dict)
@@ -215,7 +203,7 @@ def conf_from_dict(conf_dict):
     '''
     conf = Config(filename=conf_dict.get('__file__', ''))
 
-    for k, v in six.iteritems(conf_dict):
+    for k, v in iter(conf_dict.items()):
         if k.startswith('__'):
             continue
         elif inspect.ismodule(v):
@@ -248,7 +236,7 @@ def set_config(config, overwrite=False):
     if overwrite is True:
         _runtime_conf.empty()
 
-    if isinstance(config, six.string_types):
+    if isinstance(config, str):
         config = conf_from_file(config)
         _runtime_conf.update(config)
         if config.__file__:
diff --git a/pecan/core.py b/pecan/core.py
index bcf9cd4..819e50c 100644
--- a/pecan/core.py
+++ b/pecan/core.py
@@ -7,13 +7,11 @@
 import sys
 import types
 
-import six
-
 from webob import (Request as WebObRequest, Response as WebObResponse, exc,
                    acceptparse)
 from webob.multidict import NestedMultiDict
 
-from .compat import urlparse, izip
+from .compat import urlparse, izip, is_bound_method as ismethod
 from .jsonify import encode as dumps
 from .secure import handle_security
 from .templating import RendererFactory
@@ -21,10 +19,6 @@
 from .util import _cfg, getargspec
 from .middleware.recursive import ForwardRequestException
 
-if six.PY3:
-    from .compat import is_bound_method as ismethod
-else:
-    from inspect import ismethod
 
 # make sure that json is defined in mimetypes
 add_type('application/json', '.json', True)
@@ -130,12 +124,7 @@ def abort(status_code, detail='', headers=None, comment=None, **kw):
             comment=comment,
             **kw
         )
-
-        if six.PY3:
-            raise webob_exception.with_traceback(traceback)
-        else:
-            # Using exec to avoid python 3 parsers from crashing
-            exec('raise webob_exception, None, traceback')
+        raise webob_exception.with_traceback(traceback)
     finally:
         # Per the suggestion of the Python docs, delete the traceback object
         del traceback
@@ -236,7 +225,7 @@ def __init__(self, root, default_renderer='mako',
                  force_canonical=True, guess_content_type_from_ext=True,
                  context_local_factory=None, request_cls=Request,
                  response_cls=Response, **kw):
-        if isinstance(root, six.string_types):
+        if isinstance(root, str):
             root = self.__translate_root__(root)
 
         self.root = root
@@ -246,7 +235,7 @@ def __init__(self, root, default_renderer='mako',
         self.default_renderer = default_renderer
 
         # pre-sort these so we don't have to do it per-request
-        if six.callable(hooks):
+        if callable(hooks):
             hooks = hooks()
 
         self.hooks = list(sorted(
@@ -275,7 +264,7 @@ def __translate_root__(self, item):
             module = __import__(name, fromlist=fromlist)
             kallable = getattr(module, parts[-1])
             msg = "%s does not represent a callable class or function."
-            if not six.callable(kallable):
+            if not callable(kallable):
                 raise TypeError(msg % item)
             return kallable()
 
@@ -397,7 +386,7 @@ def get_args(self, state, all_params, remainder, argspec, im_self):
 
         # handle wildcard GET/POST params
         if argspec[2]:
-            for name, value in six.iteritems(all_params):
+            for name, value in iter(all_params.items()):
                 if name not in argspec[0]:
                     kwargs[name] = value
 
@@ -466,7 +455,7 @@ def find_controller(self, state):
         # handle generic controllers
         im_self = None
         if cfg.get('generic'):
-            im_self = six.get_method_self(controller)
+            im_self = controller.__self__
             handlers = cfg['generic_handlers']
             controller = handlers.get(req.method, handlers['DEFAULT'])
             handle_security(controller, im_self)
@@ -622,7 +611,7 @@ def invoke_controller(self, controller, args, kwargs, state):
             testing_variables['controller_output'] = result
 
         # set the body content
-        if result and isinstance(result, six.text_type):
+        if result and isinstance(result, str):
             resp.text = result
         elif result:
             resp.body = result
@@ -707,7 +696,7 @@ def __call__(self, environ, start_response):
                         'title': e.title,
                         'description': e.detail
                     })
-                    if isinstance(json_body, six.text_type):
+                    if isinstance(json_body, str):
                         e.text = json_body
                     else:
                         e.body = json_body
diff --git a/pecan/decorators.py b/pecan/decorators.py
index e9636b1..4f6daf5 100644
--- a/pecan/decorators.py
+++ b/pecan/decorators.py
@@ -1,6 +1,4 @@
-from inspect import getmembers, isclass, ismethod, isfunction
-
-import six
+from inspect import getmembers, isclass, isfunction
 
 from .util import _cfg, getargspec
 
@@ -109,7 +107,7 @@ def deco(f):
         if isclass(f):
             for meth in [
                 m[1] for m in getmembers(f)
-                if (isfunction if six.PY3 else ismethod)(m[1])
+                if isfunction(m[1])
             ]:
                 if getattr(meth, 'exposed', False):
                     _cfg(meth)['transactional'] = True
diff --git a/pecan/hooks.py b/pecan/hooks.py
index 9938c15..ae75e1b 100644
--- a/pecan/hooks.py
+++ b/pecan/hooks.py
@@ -1,8 +1,8 @@
+import builtins
 import types
 import sys
 from inspect import getmembers
 
-import six
 from webob.exc import HTTPFound
 
 from .util import iscontroller, _cfg
@@ -15,7 +15,7 @@
 
 def walk_controller(root_class, controller, hooks, seen=None):
     seen = seen or set()
-    if type(controller) not in vars(six.moves.builtins).values():
+    if type(controller) not in vars(builtins).values():
         # Avoid recursion loops
         try:
             if controller in seen:
diff --git a/pecan/jsonify.py b/pecan/jsonify.py
index c5cbc15..5f8bd48 100644
--- a/pecan/jsonify.py
+++ b/pecan/jsonify.py
@@ -12,26 +12,26 @@
     from webob.multidict import MultiDict
     webob_dicts = (MultiDict,)
 
-import six
 try:
     from functools import singledispatch
 except ImportError:  # pragma: no cover
     from singledispatch import singledispatch
 
 try:
-    from sqlalchemy.engine.result import ResultProxy, RowProxy
-except ImportError:  # pragma no cover
+    import sqlalchemy  # noqa
     try:
-        from sqlalchemy.engine.base import ResultProxy, RowProxy
-    except ImportError:  # pragma no cover
-        # dummy classes since we don't have SQLAlchemy installed
-
-        class ResultProxy(object):  # noqa
-            pass
-
-        class RowProxy(object):  # noqa
-            pass
+        # SQLAlchemy 2.0 support
+        from sqlalchemy.engine import CursorResult as ResultProxy
+        from sqlalchemy.engine import Row as RowProxy
+    except ImportError:
+        from sqlalchemy.engine.result import ResultProxy, RowProxy
+except ImportError:
+    # dummy classes since we don't have SQLAlchemy installed
+    class ResultProxy(object):  # noqa
+        pass
 
+    class RowProxy(object):  # noqa
+        pass
 
 try:
     from sqlalchemy.engine.cursor import LegacyCursorResult, LegacyRow
@@ -93,7 +93,7 @@ def default(self, obj):
             returns webob_dicts.mixed() dictionary, which is guaranteed
             to be JSON-friendly.
         '''
-        if hasattr(obj, '__json__') and six.callable(obj.__json__):
+        if hasattr(obj, '__json__') and callable(obj.__json__):
             return obj.__json__()
         elif isinstance(obj, (date, datetime)):
             return str(obj)
@@ -119,6 +119,9 @@ def default(self, obj):
         elif isinstance(obj, LegacyRow):
             return dict(obj._mapping)
         elif isinstance(obj, RowProxy):
+            if obj.__class__.__name__ == 'Row':
+                # SQLAlchemy 2.0 support
+                obj = obj._mapping
             return dict(obj)
         elif isinstance(obj, webob_dicts):
             return obj.mixed()
diff --git a/pecan/middleware/debug.py b/pecan/middleware/debug.py
index 2c3d4b0..b6ce553 100644
--- a/pecan/middleware/debug.py
+++ b/pecan/middleware/debug.py
@@ -1,4 +1,4 @@
-__CONFIG_HELP__ = '''
+__CONFIG_HELP__ = b'''
 <div class="traceback">
   <b>To disable this interface, set </b>
   <a target="window"
@@ -10,18 +10,17 @@
 
 try:
     import re
-    from six import b
     from backlash.debug import DebuggedApplication
 
     class DebugMiddleware(DebuggedApplication):
 
-        body_re = re.compile(b('(<body[^>]*>)'), re.I)
+        body_re = re.compile(b'(<body[^>]*>)', re.I)
 
         def debug_application(self, environ, start_response):
             for part in super(DebugMiddleware, self).debug_application(
                 environ, start_response
             ):
-                yield self.body_re.sub(b('\g<1>%s' % __CONFIG_HELP__), part)
+                yield self.body_re.sub(b'<1>%s' % __CONFIG_HELP__, part)
 
 
 except ImportError:
@@ -30,7 +29,7 @@ def debug_application(self, environ, start_response):
     from pprint import pformat
 
     from mako.template import Template
-    from six.moves import cStringIO as StringIO
+    from io import StringIO
     from webob import Response
     from webob.exc import HTTPException
 
diff --git a/pecan/middleware/errordocument.py b/pecan/middleware/errordocument.py
index 12a3c9e..5f4201b 100644
--- a/pecan/middleware/errordocument.py
+++ b/pecan/middleware/errordocument.py
@@ -1,6 +1,5 @@
 import sys
 
-from six import b as b_
 from .recursive import ForwardRequestException, RecursionLoop
 
 
@@ -32,9 +31,11 @@ def keep_status_start_response(status, headers, exc_info=None):
                 [('Content-type', 'text/plain')],
                 sys.exc_info()
             )
-            return [b_(
-                'Error: %s.  (Error page could not be fetched)' % self.status
-            )]
+            return [
+                b'Error: %s.  (Error page could not be fetched)' % (
+                    self.status.encode('utf-8')
+                )
+            ]
 
 
 class ErrorDocumentMiddleware(object):
diff --git a/pecan/middleware/static.py b/pecan/middleware/static.py
index ab6dd4e..da70178 100644
--- a/pecan/middleware/static.py
+++ b/pecan/middleware/static.py
@@ -10,8 +10,6 @@
 from datetime import datetime
 from time import gmtime
 
-import six
-
 
 class FileWrapper(object):
     """This class can be used to convert a :class:`file`-like object into
@@ -37,17 +35,13 @@ def close(self):
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         data = self.file.read(self.buffer_size)
         if data:
             return data
         raise StopIteration()
 
 
-if six.PY3:
-    FileWrapper.__next__ = FileWrapper.next
-
-
 def wrap_file(environ, file, buffer_size=8192):
     """Wraps a file.  This uses the WSGI server's file wrapper if available
     or otherwise the generic :class:`FileWrapper`.
diff --git a/pecan/rest.py b/pecan/rest.py
index e231c71..3483df4 100644
--- a/pecan/rest.py
+++ b/pecan/rest.py
@@ -2,7 +2,6 @@
 import warnings
 
 from webob import exc
-import six
 
 from .core import abort
 from .decorators import expose
@@ -49,8 +48,7 @@ def __new__(cls, *args, **kwargs):
         # object.__new__ will error if called with extra arguments, and either
         # __new__ is overridden or __init__ is not overridden;
         # https://hg.python.org/cpython/file/78d36d54391c/Objects/typeobject.c#l3034
-        # In PY3, this is actually a TypeError (in PY2, it just raises
-        # a DeprecationWarning)
+        # In PY3, this is a TypeError
         new = super(RestController, cls).__new__
         if new is object.__new__:
             return new(cls)
@@ -182,7 +180,7 @@ def _handle_lookup(self, args, request=None):
             self._raise_method_deprecation_warning(self.handle_lookup)
 
         # filter empty strings from the arg list
-        args = list(six.moves.filter(bool, args))
+        args = list(filter(bool, args))
 
         # check for lookup controllers
         lookup = getattr(self, '_lookup', None)
@@ -276,7 +274,7 @@ def _handle_get(self, method, remainder, request=None):
 
         # route to a get_all or get if no additional parts are available
         if not remainder or remainder == ['']:
-            remainder = list(six.moves.filter(bool, remainder))
+            remainder = list(filter(bool, remainder))
             controller = self._find_controller('get_all', 'get')
             if controller:
                 self._handle_bad_rest_arguments(controller, remainder, request)
diff --git a/pecan/routing.py b/pecan/routing.py
index 9b2f57b..95c5160 100644
--- a/pecan/routing.py
+++ b/pecan/routing.py
@@ -4,7 +4,6 @@
 from inspect import getmembers, ismethod
 
 from webob import exc
-import six
 
 from .secure import handle_security, cross_boundary
 from .util import iscontroller, getargspec, _cfg
@@ -42,7 +41,7 @@ class Controller(object):
     """
 
     def _validate_route(route):
-        if not isinstance(route, six.string_types):
+        if not isinstance(route, str):
             raise TypeError('%s must be a string' % route)
 
         if route in ('.', '..') or not re.match(
@@ -280,7 +279,7 @@ def _detect_custom_path_segments(obj):
         for key, val in getmembers(obj):
             if iscontroller(val) and isinstance(
                 getattr(val, 'custom_route', None),
-                six.string_types
+                str,
             ):
                 route = val.custom_route
 
diff --git a/pecan/scaffolds/__init__.py b/pecan/scaffolds/__init__.py
index 2dbe46f..405ca5e 100644
--- a/pecan/scaffolds/__init__.py
+++ b/pecan/scaffolds/__init__.py
@@ -4,8 +4,6 @@
 import pkg_resources
 from string import Template
 
-import six
-
 DEFAULT_SCAFFOLD = 'base'
 _bad_chars_re = re.compile('[^a-zA-Z0-9_]')
 
@@ -125,18 +123,13 @@ def render_template(content, variables):
     fsenc = sys.getfilesystemencoding()
 
     def to_native(s, encoding='latin-1', errors='strict'):
-        if six.PY3:
-            if isinstance(s, six.text_type):
-                return s
-            return str(s, encoding, errors)
-        else:
-            if isinstance(s, six.text_type):
-                return s.encode(encoding, errors)
-            return str(s)
+        if isinstance(s, str):
+            return s
+        return str(s, encoding, errors)
 
     output = Template(
         to_native(content, fsenc)
     ).substitute(variables)
-    if isinstance(output, six.text_type):
+    if isinstance(output, str):
         output = output.encode(fsenc, 'strict')
     return output
diff --git a/pecan/secure.py b/pecan/secure.py
index 7b04368..db5a746 100644
--- a/pecan/secure.py
+++ b/pecan/secure.py
@@ -2,18 +2,12 @@
 from inspect import getmembers, isfunction
 from webob import exc
 
-import six
-
+from .compat import is_bound_method as ismethod
 from .decorators import expose
 from .util import _cfg, iscontroller
 
 __all__ = ['unlocked', 'secure', 'SecureController']
 
-if six.PY3:
-    from .compat import is_bound_method as ismethod
-else:
-    from inspect import ismethod
-
 
 class _SecureState(object):
     def __init__(self, desc, boolean_value):
@@ -66,7 +60,7 @@ def __init__(self, obj, check_permissions):
         self._parent = None
 
     def _check_permissions(self):
-        if isinstance(self.check_permissions, six.string_types):
+        if isinstance(self.check_permissions, str):
             return getattr(self.parent, self.check_permissions)()
         else:
             return self.check_permissions()
@@ -76,7 +70,7 @@ def __get_parent(self):
 
     def __set_parent(self, parent):
         if ismethod(parent):
-            self._parent = six.get_method_self(parent)
+            self._parent = parent.__self__
         else:
             self._parent = parent
     parent = property(__get_parent, __set_parent)
@@ -92,7 +86,7 @@ def _allowed_check_permissions_types(x):
     return (
         ismethod(x) or
         isfunction(x) or
-        isinstance(x, six.string_types)
+        isinstance(x, str)
     )
 
 
@@ -145,7 +139,7 @@ def __init__(cls, name, bases, dict_):
         )
 
         for name, value in getmembers(cls)[:]:
-            if (isfunction if six.PY3 else ismethod)(value):
+            if isfunction(value):
                 if iscontroller(value) and value._pecan.get(
                     'secured'
                 ) is None:
@@ -207,9 +201,9 @@ def handle_security(controller, im_self=None):
     if controller._pecan.get('secured', False):
         check_permissions = controller._pecan['check_permissions']
 
-        if isinstance(check_permissions, six.string_types):
+        if isinstance(check_permissions, str):
             check_permissions = getattr(
-                im_self or six.get_method_self(controller),
+                im_self or controller.__self__,
                 check_permissions
             )
 
diff --git a/pecan/tests/middleware/test_errordocument.py b/pecan/tests/middleware/test_errordocument.py
index 29f46e5..93bbfe6 100644
--- a/pecan/tests/middleware/test_errordocument.py
+++ b/pecan/tests/middleware/test_errordocument.py
@@ -1,7 +1,6 @@
 import json
 
 from webtest import TestApp
-from six import b as b_
 
 import pecan
 from pecan.middleware.errordocument import ErrorDocumentMiddleware
@@ -11,13 +10,13 @@
 
 def four_oh_four_app(environ, start_response):
     if environ['PATH_INFO'].startswith('/error'):
-        code = environ['PATH_INFO'].split('/')[2]
+        code = environ['PATH_INFO'].split('/')[2].encode('utf-8')
         start_response("200 OK", [('Content-type', 'text/plain')])
 
-        body = "Error: %s" % code
+        body = b"Error: %s" % code
         if environ['QUERY_STRING']:
-            body += "\nQS: %s" % environ['QUERY_STRING']
-        return [b_(body)]
+            body += b"\nQS: %s" % environ['QUERY_STRING'].encode('utf-8')
+        return [body]
     start_response("404 Not Found", [('Content-type', 'text/plain')])
     return []
 
@@ -33,12 +32,12 @@ def setUp(self):
     def test_hit_error_page(self):
         r = self.app.get('/error/404')
         assert r.status_int == 200
-        assert r.body == b_('Error: 404')
+        assert r.body == b'Error: 404'
 
     def test_middleware_routes_to_404_message(self):
         r = self.app.get('/', expect_errors=True)
         assert r.status_int == 404
-        assert r.body == b_('Error: 404')
+        assert r.body == b'Error: 404'
 
     def test_error_endpoint_with_query_string(self):
         app = TestApp(RecursiveMiddleware(ErrorDocumentMiddleware(
@@ -46,7 +45,7 @@ def test_error_endpoint_with_query_string(self):
         )))
         r = app.get('/', expect_errors=True)
         assert r.status_int == 404
-        assert r.body == b_('Error: 404\nQS: foo=bar')
+        assert r.body == b'Error: 404\nQS: foo=bar'
 
     def test_error_with_recursion_loop(self):
         app = TestApp(RecursiveMiddleware(ErrorDocumentMiddleware(
@@ -54,8 +53,8 @@ def test_error_with_recursion_loop(self):
         )))
         r = app.get('/', expect_errors=True)
         assert r.status_int == 404
-        assert r.body == b_(
-            'Error: 404 Not Found.  (Error page could not be fetched)'
+        assert r.body == (
+            b'Error: 404 Not Found.  (Error page could not be fetched)'
         )
 
     def test_original_exception(self):
diff --git a/pecan/tests/middleware/test_recursive.py b/pecan/tests/middleware/test_recursive.py
index ed95d50..2d1481c 100644
--- a/pecan/tests/middleware/test_recursive.py
+++ b/pecan/tests/middleware/test_recursive.py
@@ -1,5 +1,4 @@
 from webtest import TestApp
-from six import b as b_
 
 from pecan.middleware.recursive import (RecursiveMiddleware,
                                         ForwardRequestException)
@@ -8,16 +7,16 @@
 
 def simple_app(environ, start_response):
     start_response("200 OK", [('Content-type', 'text/plain')])
-    return [b_('requested page returned')]
+    return [b'requested page returned']
 
 
 def error_docs_app(environ, start_response):
     if environ['PATH_INFO'] == '/not_found':
         start_response("404 Not found", [('Content-type', 'text/plain')])
-        return [b_('Not found')]
+        return [b'Not found']
     elif environ['PATH_INFO'] == '/error':
         start_response("200 OK", [('Content-type', 'text/plain')])
-        return [b_('Page not found')]
+        return [b'Page not found']
     elif environ['PATH_INFO'] == '/recurse':
         raise ForwardRequestException('/recurse')
     else:
diff --git a/pecan/tests/scaffold_builder.py b/pecan/tests/scaffold_builder.py
index 9ee7879..c608c18 100644
--- a/pecan/tests/scaffold_builder.py
+++ b/pecan/tests/scaffold_builder.py
@@ -3,8 +3,6 @@
 import subprocess
 import time
 
-from six import b as b_
-
 from pecan.compat import urlopen, URLError
 from pecan.tests import PecanTestCase
 
@@ -79,7 +77,7 @@ def test_project_pecan_shell_command(self):
             self.poll(proc)
 
             out, _ = proc.communicate(
-                b_('{"model" : model, "conf" : conf, "app" : app}')
+                b'{"model" : model, "conf" : conf, "app" : app}'
             )
             assert 'testing123.model' in out.decode(), out
             assert 'Config(' in out.decode(), out
diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py
index 62d691e..57c8173 100644
--- a/pecan/tests/test_base.py
+++ b/pecan/tests/test_base.py
@@ -5,15 +5,11 @@
 import json
 import traceback
 import warnings
-from unittest import mock
+from io import StringIO, BytesIO
 
 import webob
 from webob.exc import HTTPNotFound
 from webtest import TestApp
-import six
-from six import b as b_
-from six import u as u_
-from six.moves import cStringIO as StringIO
 
 from pecan import (
     Pecan, Request, Response, expose, request, response, redirect,
@@ -49,19 +45,19 @@ def index(self):
 
             @expose()
             def explicit_body(self):
-                response.body = b_('Hello, World!')
+                response.body = b'Hello, World!'
 
             @expose()
             def empty_body(self):
-                response.body = b_('')
+                response.body = b''
 
             @expose()
             def explicit_text(self):
-                response.text = six.text_type('Hello, World!')
+                response.text = 'Hello, World!'
 
             @expose()
             def empty_text(self):
-                response.text = six.text_type('')
+                response.text = ''
 
             @expose()
             def explicit_json(self):
@@ -91,22 +87,22 @@ def test_index_with_non_unicode(self):
     def test_explicit_body(self):
         r = self.app_.get('/explicit_body/')
         self.assertEqual(r.status_int, 200)
-        self.assertEqual(r.body, b_('Hello, World!'))
+        self.assertEqual(r.body, b'Hello, World!')
 
     def test_empty_body(self):
         r = self.app_.get('/empty_body/')
         self.assertEqual(r.status_int, 204)
-        self.assertEqual(r.body, b_(''))
+        self.assertEqual(r.body, b'')
 
     def test_explicit_text(self):
         r = self.app_.get('/explicit_text/')
         self.assertEqual(r.status_int, 200)
-        self.assertEqual(r.body, b_('Hello, World!'))
+        self.assertEqual(r.body, b'Hello, World!')
 
     def test_empty_text(self):
         r = self.app_.get('/empty_text/')
         self.assertEqual(r.status_int, 204)
-        self.assertEqual(r.body, b_(''))
+        self.assertEqual(r.body, b'')
 
     def test_explicit_json(self):
         r = self.app_.get('/explicit_json/')
@@ -127,12 +123,12 @@ def app_(self):
         class RootController(object):
             @expose()
             def index(self):
-                body = six.BytesIO(b_('Hello, World!'))
+                body = BytesIO(b'Hello, World!')
                 response.body_file = body
 
             @expose()
             def empty(self):
-                body = six.BytesIO(b_(''))
+                body = BytesIO(b'')
                 response.body_file = body
 
         return TestApp(Pecan(RootController()))
@@ -140,7 +136,7 @@ def empty(self):
     def test_body_generator(self):
         r = self.app_.get('/')
         self.assertEqual(r.status_int, 200)
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
     def test_empty_body_generator(self):
         r = self.app_.get('/empty')
@@ -179,17 +175,17 @@ def index(self):
     def test_empty_root(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
     def test_index(self):
         r = self.app_.get('/index')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
     def test_index_html(self):
         r = self.app_.get('/index.html')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
 
 class TestObjectDispatch(PecanTestCase):
@@ -232,22 +228,22 @@ def deeper(self):
     def test_index(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
     def test_one_level(self):
         r = self.app_.get('/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/deeper')
+        assert r.body == b'/deeper'
 
     def test_one_level_with_trailing(self):
         r = self.app_.get('/sub/')
         assert r.status_int == 200
-        assert r.body == b_('/sub/')
+        assert r.body == b'/sub/'
 
     def test_two_levels(self):
         r = self.app_.get('/sub/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/sub/deeper')
+        assert r.body == b'/sub/deeper'
 
     def test_two_levels_with_trailing(self):
         r = self.app_.get('/sub/sub/')
@@ -256,10 +252,9 @@ def test_two_levels_with_trailing(self):
     def test_three_levels(self):
         r = self.app_.get('/sub/sub/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/sub/sub/deeper')
+        assert r.body == b'/sub/sub/deeper'
 
 
-@unittest.skipIf(not six.PY3, "tests are Python3 specific")
 class TestUnicodePathSegments(PecanTestCase):
 
     def test_unicode_methods(self):
@@ -270,7 +265,7 @@ class RootController(object):
 
         resp = app.get('/%F0%9F%8C%B0/')
         assert resp.status_int == 200
-        assert resp.body == b_('Hello, World!')
+        assert resp.body == b'Hello, World!'
 
     def test_unicode_child(self):
         class ChildController(object):
@@ -285,7 +280,7 @@ class RootController(object):
 
         resp = app.get('/%F0%9F%8C%B0/')
         assert resp.status_int == 200
-        assert resp.body == b_('Hello, World!')
+        assert resp.body == b'Hello, World!'
 
 
 class TestLookups(PecanTestCase):
@@ -318,17 +313,17 @@ def _lookup(self, someID, *remainder):
     def test_index(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
     def test_lookup(self):
         r = self.app_.get('/100/')
         assert r.status_int == 200
-        assert r.body == b_('/100')
+        assert r.body == b'/100'
 
     def test_lookup_with_method(self):
         r = self.app_.get('/100/name')
         assert r.status_int == 200
-        assert r.body == b_('/100/name')
+        assert r.body == b'/100/name'
 
     def test_lookup_with_wrong_argspec(self):
         class RootController(object):
@@ -378,7 +373,7 @@ def test_canonical_lookup(self):
         assert self.app_.get('/users', expect_errors=404).status_int == 404
         assert self.app_.get('/users/', expect_errors=404).status_int == 404
         assert self.app_.get('/users/100').status_int == 302
-        assert self.app_.get('/users/100/').body == b_('100')
+        assert self.app_.get('/users/100/').body == b'100'
 
 
 class TestControllerArguments(PecanTestCase):
@@ -466,22 +461,22 @@ def test_required_argument(self):
     def test_single_argument(self):
         r = self.app_.get('/1')
         assert r.status_int == 200
-        assert r.body == b_('index: 1')
+        assert r.body == b'index: 1'
 
     def test_single_argument_with_encoded_url(self):
         r = self.app_.get('/This%20is%20a%20test%21')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_single_argument_with_plus(self):
         r = self.app_.get('/foo+bar')
         assert r.status_int == 200
-        assert r.body == b_('index: foo+bar')
+        assert r.body == b'index: foo+bar'
 
     def test_single_argument_with_encoded_plus(self):
         r = self.app_.get('/foo%2Bbar')
         assert r.status_int == 200
-        assert r.body == b_('index: foo+bar')
+        assert r.body == b'index: foo+bar'
 
     def test_two_arguments(self):
         r = self.app_.get('/1/dummy', status=404)
@@ -490,120 +485,120 @@ def test_two_arguments(self):
     def test_keyword_argument(self):
         r = self.app_.get('/?id=2')
         assert r.status_int == 200
-        assert r.body == b_('index: 2')
+        assert r.body == b'index: 2'
 
     def test_keyword_argument_with_encoded_url(self):
         r = self.app_.get('/?id=This%20is%20a%20test%21')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_keyword_argument_with_plus(self):
         r = self.app_.get('/?id=foo+bar')
         assert r.status_int == 200
-        assert r.body == b_('index: foo bar')
+        assert r.body == b'index: foo bar'
 
     def test_keyword_argument_with_encoded_plus(self):
         r = self.app_.get('/?id=foo%2Bbar')
         assert r.status_int == 200
-        assert r.body == b_('index: foo+bar')
+        assert r.body == b'index: foo+bar'
 
     def test_argument_and_keyword_argument(self):
         r = self.app_.get('/3?id=three')
         assert r.status_int == 200
-        assert r.body == b_('index: 3')
+        assert r.body == b'index: 3'
 
     def test_encoded_argument_and_keyword_argument(self):
         r = self.app_.get('/This%20is%20a%20test%21?id=three')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_explicit_kwargs(self):
         r = self.app_.post('/', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_path_with_explicit_kwargs(self):
         r = self.app_.post('/4', {'id': 'four'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_explicit_json_kwargs(self):
         r = self.app_.post_json('/', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_path_with_explicit_json_kwargs(self):
         r = self.app_.post_json('/4', {'id': 'four'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_multiple_kwargs(self):
         r = self.app_.get('/?id=5&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('index: 5')
+        assert r.body == b'index: 5'
 
     def test_kwargs_from_root(self):
         r = self.app_.post('/', {'id': '6', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('index: 6')
+        assert r.body == b'index: 6'
 
     def test_json_kwargs_from_root(self):
         r = self.app_.post_json('/', {'id': '6', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('index: 6')
+        assert r.body == b'index: 6'
 
         # multiple args
 
     def test_multiple_positional_arguments(self):
         r = self.app_.get('/multiple/one/two')
         assert r.status_int == 200
-        assert r.body == b_('multiple: one, two')
+        assert r.body == b'multiple: one, two'
 
     def test_multiple_positional_arguments_with_url_encode(self):
         r = self.app_.get('/multiple/One%20/Two%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple: One , Two!')
+        assert r.body == b'multiple: One , Two!'
 
     def test_multiple_positional_arguments_with_kwargs(self):
         r = self.app_.get('/multiple?one=three&two=four')
         assert r.status_int == 200
-        assert r.body == b_('multiple: three, four')
+        assert r.body == b'multiple: three, four'
 
     def test_multiple_positional_arguments_with_url_encoded_kwargs(self):
         r = self.app_.get('/multiple?one=Three%20&two=Four%20%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple: Three , Four !')
+        assert r.body == b'multiple: Three , Four !'
 
     def test_positional_args_with_dictionary_kwargs(self):
         r = self.app_.post('/multiple', {'one': 'five', 'two': 'six'})
         assert r.status_int == 200
-        assert r.body == b_('multiple: five, six')
+        assert r.body == b'multiple: five, six'
 
     def test_positional_args_with_json_kwargs(self):
         r = self.app_.post_json('/multiple', {'one': 'five', 'two': 'six'})
         assert r.status_int == 200
-        assert r.body == b_('multiple: five, six')
+        assert r.body == b'multiple: five, six'
 
     def test_positional_args_with_url_encoded_dictionary_kwargs(self):
         r = self.app_.post('/multiple', {'one': 'Five%20', 'two': 'Six%20%21'})
         assert r.status_int == 200
-        assert r.body == b_('multiple: Five%20, Six%20%21')
+        assert r.body == b'multiple: Five%20, Six%20%21'
 
         # optional arg
     def test_optional_arg(self):
         r = self.app_.get('/optional')
         assert r.status_int == 200
-        assert r.body == b_('optional: None')
+        assert r.body == b'optional: None'
 
     def test_multiple_optional(self):
         r = self.app_.get('/optional/1')
         assert r.status_int == 200
-        assert r.body == b_('optional: 1')
+        assert r.body == b'optional: 1'
 
     def test_multiple_optional_url_encoded(self):
         r = self.app_.get('/optional/Some%20Number')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_multiple_optional_missing(self):
         r = self.app_.get('/optional/2/dummy', status=404)
@@ -612,72 +607,72 @@ def test_multiple_optional_missing(self):
     def test_multiple_with_kwargs(self):
         r = self.app_.get('/optional?id=2')
         assert r.status_int == 200
-        assert r.body == b_('optional: 2')
+        assert r.body == b'optional: 2'
 
     def test_multiple_with_url_encoded_kwargs(self):
         r = self.app_.get('/optional?id=Some%20Number')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_multiple_args_with_url_encoded_kwargs(self):
         r = self.app_.get('/optional/3?id=three')
         assert r.status_int == 200
-        assert r.body == b_('optional: 3')
+        assert r.body == b'optional: 3'
 
     def test_url_encoded_positional_args(self):
         r = self.app_.get('/optional/Some%20Number?id=three')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_kwargs(self):
         r = self.app_.post('/optional', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 4')
+        assert r.body == b'optional: 4'
 
     def test_optional_arg_with_json_kwargs(self):
         r = self.app_.post_json('/optional', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 4')
+        assert r.body == b'optional: 4'
 
     def test_optional_arg_with_url_encoded_kwargs(self):
         r = self.app_.post('/optional', {'id': 'Some%20Number'})
         assert r.status_int == 200
-        assert r.body == b_('optional: Some%20Number')
+        assert r.body == b'optional: Some%20Number'
 
     def test_multiple_positional_arguments_with_dictionary_kwargs(self):
         r = self.app_.post('/optional/5', {'id': 'five'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 5')
+        assert r.body == b'optional: 5'
 
     def test_multiple_positional_arguments_with_json_kwargs(self):
         r = self.app_.post_json('/optional/5', {'id': 'five'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 5')
+        assert r.body == b'optional: 5'
 
     def test_multiple_positional_url_encoded_arguments_with_kwargs(self):
         r = self.app_.post('/optional/Some%20Number', {'id': 'five'})
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_multiple_kwargs(self):
         r = self.app_.get('/optional?id=6&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('optional: 6')
+        assert r.body == b'optional: 6'
 
     def test_optional_arg_with_multiple_url_encoded_kwargs(self):
         r = self.app_.get('/optional?id=Some%20Number&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_multiple_dictionary_kwargs(self):
         r = self.app_.post('/optional', {'id': '7', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 7')
+        assert r.body == b'optional: 7'
 
     def test_optional_arg_with_multiple_json_kwargs(self):
         r = self.app_.post_json('/optional', {'id': '7', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 7')
+        assert r.body == b'optional: 7'
 
     def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self):
         r = self.app_.post('/optional', {
@@ -685,34 +680,34 @@ def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self):
             'dummy': 'dummy'
         })
         assert r.status_int == 200
-        assert r.body == b_('optional: Some%20Number')
+        assert r.body == b'optional: Some%20Number'
 
         # multiple optional args
 
     def test_multiple_optional_positional_args(self):
         r = self.app_.get('/multiple_optional')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, None')
+        assert r.body == b'multiple_optional: None, None, None'
 
     def test_multiple_optional_positional_args_one_arg(self):
         r = self.app_.get('/multiple_optional/1')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_one_url_encoded_arg(self):
         r = self.app_.get('/multiple_optional/One%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_all_args(self):
         r = self.app_.get('/multiple_optional/1/2/3')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_positional_args_all_url_encoded_args(self):
         r = self.app_.get('/multiple_optional/One%21/Two%21/Three%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, Two!, Three!')
+        assert r.body == b'multiple_optional: One!, Two!, Three!'
 
     def test_multiple_optional_positional_args_too_many_args(self):
         r = self.app_.get('/multiple_optional/1/2/3/dummy', status=404)
@@ -721,64 +716,64 @@ def test_multiple_optional_positional_args_too_many_args(self):
     def test_multiple_optional_positional_args_with_kwargs(self):
         r = self.app_.get('/multiple_optional?one=1')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_url_encoded_kwargs(self):
         r = self.app_.get('/multiple_optional?one=One%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_with_string_kwargs(self):
         r = self.app_.get('/multiple_optional/1?one=one')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_encoded_str_kwargs(self):
         r = self.app_.get('/multiple_optional/One%21?one=one')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_with_dict_kwargs(self):
         r = self.app_.post('/multiple_optional', {'one': '1'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_json_kwargs(self):
         r = self.app_.post_json('/multiple_optional', {'one': '1'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_encoded_dict_kwargs(self):
         r = self.app_.post('/multiple_optional', {'one': 'One%21'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One%21, None, None')
+        assert r.body == b'multiple_optional: One%21, None, None'
 
     def test_multiple_optional_positional_args_and_dict_kwargs(self):
         r = self.app_.post('/multiple_optional/1', {'one': 'one'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_and_json_kwargs(self):
         r = self.app_.post_json('/multiple_optional/1', {'one': 'one'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_encoded_positional_args_and_dict_kwargs(self):
         r = self.app_.post('/multiple_optional/One%21', {'one': 'one'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_args_with_multiple_kwargs(self):
         r = self.app_.get('/multiple_optional?one=1&two=2&three=3&four=4')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_args_with_multiple_encoded_kwargs(self):
         r = self.app_.get(
             '/multiple_optional?one=One%21&two=Two%21&three=Three%21&four=4'
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, Two!, Three!')
+        assert r.body == b'multiple_optional: One!, Two!, Three!'
 
     def test_multiple_optional_args_with_multiple_dict_kwargs(self):
         r = self.app_.post(
@@ -786,7 +781,7 @@ def test_multiple_optional_args_with_multiple_dict_kwargs(self):
             {'one': '1', 'two': '2', 'three': '3', 'four': '4'}
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_args_with_multiple_json_kwargs(self):
         r = self.app_.post_json(
@@ -794,7 +789,7 @@ def test_multiple_optional_args_with_multiple_json_kwargs(self):
             {'one': '1', 'two': '2', 'three': '3', 'four': '4'}
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self):
         r = self.app_.post(
@@ -807,47 +802,47 @@ def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self):
             }
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One%21, Two%21, Three%21')
+        assert r.body == b'multiple_optional: One%21, Two%21, Three%21'
 
     def test_multiple_optional_args_with_last_kwarg(self):
         r = self.app_.get('/multiple_optional?three=3')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, 3')
+        assert r.body == b'multiple_optional: None, None, 3'
 
     def test_multiple_optional_args_with_last_encoded_kwarg(self):
         r = self.app_.get('/multiple_optional?three=Three%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, Three!')
+        assert r.body == b'multiple_optional: None, None, Three!'
 
     def test_multiple_optional_args_with_middle_arg(self):
         r = self.app_.get('/multiple_optional', {'two': '2'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, 2, None')
+        assert r.body == b'multiple_optional: None, 2, None'
 
     def test_variable_args(self):
         r = self.app_.get('/variable_args')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_multiple_variable_args(self):
         r = self.app_.get('/variable_args/1/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: 1, dummy')
+        assert r.body == b'variable_args: 1, dummy'
 
     def test_multiple_encoded_variable_args(self):
         r = self.app_.get('/variable_args/Testing%20One%20Two/Three%21')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: Testing One Two, Three!')
+        assert r.body == b'variable_args: Testing One Two, Three!'
 
     def test_variable_args_with_kwargs(self):
         r = self.app_.get('/variable_args?id=2&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_variable_args_with_dict_kwargs(self):
         r = self.app_.post('/variable_args', {'id': '3', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_variable_args_with_json_kwargs(self):
         r = self.app_.post_json(
@@ -855,12 +850,12 @@ def test_variable_args_with_json_kwargs(self):
             {'id': '3', 'dummy': 'dummy'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_variable_kwargs(self):
         r = self.app_.get('/variable_kwargs')
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: ')
+        assert r.body == b'variable_kwargs: '
 
     def test_multiple_variable_kwargs(self):
         r = self.app_.get('/variable_kwargs/1/dummy', status=404)
@@ -869,19 +864,19 @@ def test_multiple_variable_kwargs(self):
     def test_multiple_variable_kwargs_with_explicit_kwargs(self):
         r = self.app_.get('/variable_kwargs?id=2&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=dummy, id=2')
+        assert r.body == b'variable_kwargs: dummy=dummy, id=2'
 
     def test_multiple_variable_kwargs_with_explicit_encoded_kwargs(self):
         r = self.app_.get(
             '/variable_kwargs?id=Two%21&dummy=This%20is%20a%20test'
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=This is a test, id=Two!')
+        assert r.body == b'variable_kwargs: dummy=This is a test, id=Two!'
 
     def test_multiple_variable_kwargs_with_dict_kwargs(self):
         r = self.app_.post('/variable_kwargs', {'id': '3', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=dummy, id=3')
+        assert r.body == b'variable_kwargs: dummy=dummy, id=3'
 
     def test_multiple_variable_kwargs_with_json_kwargs(self):
         r = self.app_.post_json(
@@ -889,7 +884,7 @@ def test_multiple_variable_kwargs_with_json_kwargs(self):
             {'id': '3', 'dummy': 'dummy'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=dummy, id=3')
+        assert r.body == b'variable_kwargs: dummy=dummy, id=3'
 
     def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self):
         r = self.app_.post(
@@ -897,43 +892,43 @@ def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self):
             {'id': 'Three%21', 'dummy': 'This%20is%20a%20test'}
         )
         assert r.status_int == 200
-        result = 'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21'
-        assert r.body == b_(result)
+        result = b'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21'
+        assert r.body == result
 
     def test_variable_all(self):
         r = self.app_.get('/variable_all')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: ')
+        assert r.body == b'variable_all: '
 
     def test_variable_all_with_one_extra(self):
         r = self.app_.get('/variable_all/1')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 1')
+        assert r.body == b'variable_all: 1'
 
     def test_variable_all_with_two_extras(self):
         r = self.app_.get('/variable_all/2/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 2, dummy')
+        assert r.body == b'variable_all: 2, dummy'
 
     def test_variable_mixed(self):
         r = self.app_.get('/variable_all/3?month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 3, day=12, month=1')
+        assert r.body == b'variable_all: 3, day=12, month=1'
 
     def test_variable_mixed_explicit(self):
         r = self.app_.get('/variable_all/4?id=four&month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 4, day=12, id=four, month=1')
+        assert r.body == b'variable_all: 4, day=12, id=four, month=1'
 
     def test_variable_post(self):
         r = self.app_.post('/variable_all/5/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 5, dummy')
+        assert r.body == b'variable_all: 5, dummy'
 
     def test_variable_post_with_kwargs(self):
         r = self.app_.post('/variable_all/6', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 6, day=12, month=1')
+        assert r.body == b'variable_all: 6, day=12, month=1'
 
     def test_variable_post_with_json_kwargs(self):
         r = self.app_.post_json(
@@ -941,7 +936,7 @@ def test_variable_post_with_json_kwargs(self):
             {'month': '1', 'day': '12'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 6, day=12, month=1')
+        assert r.body == b'variable_all: 6, day=12, month=1'
 
     def test_variable_post_mixed(self):
         r = self.app_.post(
@@ -949,7 +944,7 @@ def test_variable_post_mixed(self):
             {'id': 'seven', 'month': '1', 'day': '12'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 7, day=12, id=seven, month=1')
+        assert r.body == b'variable_all: 7, day=12, id=seven, month=1'
 
     def test_variable_post_mixed_with_json(self):
         r = self.app_.post_json(
@@ -957,39 +952,35 @@ def test_variable_post_mixed_with_json(self):
             {'id': 'seven', 'month': '1', 'day': '12'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 7, day=12, id=seven, month=1')
+        assert r.body == b'variable_all: 7, day=12, id=seven, month=1'
 
     def test_duplicate_query_parameters_GET(self):
         r = self.app_.get('/variable_kwargs?list=1&list=2')
-        l = [u_('1'), u_('2')]
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: list=%s' % l)
+        assert r.body == b"variable_kwargs: list=['1', '2']"
 
     def test_duplicate_query_parameters_POST(self):
         r = self.app_.post('/variable_kwargs',
                            {'list': ['1', '2']})
-        l = [u_('1'), u_('2')]
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: list=%s' % l)
+        assert r.body == b"variable_kwargs: list=['1', '2']"
 
     def test_duplicate_query_parameters_POST_mixed(self):
         r = self.app_.post('/variable_kwargs?list=1&list=2',
                            {'list': ['3', '4']})
-        l = [u_('1'), u_('2'), u_('3'), u_('4')]
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: list=%s' % l)
+        assert r.body == b"variable_kwargs: list=['1', '2', '3', '4']"
 
     def test_duplicate_query_parameters_POST_mixed_json(self):
         r = self.app_.post('/variable_kwargs?list=1&list=2',
                            {'list': 3})
-        l = [u_('1'), u_('2'), u_('3')]
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: list=%s' % l)
+        assert r.body == b"variable_kwargs: list=['1', '2', '3']"
 
     def test_staticmethod(self):
         r = self.app_.get('/static/foobar')
         assert r.status_int == 200
-        assert r.body == b_('id is foobar')
+        assert r.body == b'id is foobar'
 
     def test_no_remainder(self):
         try:
@@ -1009,57 +1000,57 @@ def test_no_remainder(self):
     def test_one_remainder(self):
         r = self.app_.get('/eater/1')
         assert r.status_int == 200
-        assert r.body == b_('eater: 1, None, ')
+        assert r.body == b'eater: 1, None, '
 
     def test_two_remainders(self):
         r = self.app_.get('/eater/2/dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 2, dummy, ')
+        assert r.body == b'eater: 2, dummy, '
 
     def test_many_remainders(self):
         r = self.app_.get('/eater/3/dummy/foo/bar')
         assert r.status_int == 200
-        assert r.body == b_('eater: 3, dummy, foo, bar')
+        assert r.body == b'eater: 3, dummy, foo, bar'
 
     def test_remainder_with_kwargs(self):
         r = self.app_.get('/eater/4?month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('eater: 4, None, day=12, month=1')
+        assert r.body == b'eater: 4, None, day=12, month=1'
 
     def test_remainder_with_many_kwargs(self):
         r = self.app_.get('/eater/5?id=five&month=1&day=12&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 5, dummy, day=12, month=1')
+        assert r.body == b'eater: 5, dummy, day=12, month=1'
 
     def test_post_remainder(self):
         r = self.app_.post('/eater/6')
         assert r.status_int == 200
-        assert r.body == b_('eater: 6, None, ')
+        assert r.body == b'eater: 6, None, '
 
     def test_post_three_remainders(self):
         r = self.app_.post('/eater/7/dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 7, dummy, ')
+        assert r.body == b'eater: 7, dummy, '
 
     def test_post_many_remainders(self):
         r = self.app_.post('/eater/8/dummy/foo/bar')
         assert r.status_int == 200
-        assert r.body == b_('eater: 8, dummy, foo, bar')
+        assert r.body == b'eater: 8, dummy, foo, bar'
 
     def test_post_remainder_with_kwargs(self):
         r = self.app_.post('/eater/9', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('eater: 9, None, day=12, month=1')
+        assert r.body == b'eater: 9, None, day=12, month=1'
 
     def test_post_empty_remainder_with_json_kwargs(self):
         r = self.app_.post_json('/eater/9/', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('eater: 9, None, day=12, month=1')
+        assert r.body == b'eater: 9, None, day=12, month=1'
 
     def test_post_remainder_with_json_kwargs(self):
         r = self.app_.post_json('/eater/9', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('eater: 9, None, day=12, month=1')
+        assert r.body == b'eater: 9, None, day=12, month=1'
 
     def test_post_many_remainders_with_many_kwargs(self):
         r = self.app_.post(
@@ -1067,7 +1058,7 @@ def test_post_many_remainders_with_many_kwargs(self):
             {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'}
         )
         assert r.status_int == 200
-        assert r.body == b_('eater: 10, dummy, day=12, month=1')
+        assert r.body == b'eater: 10, dummy, day=12, month=1'
 
     def test_post_many_remainders_with_many_json_kwargs(self):
         r = self.app_.post_json(
@@ -1075,7 +1066,7 @@ def test_post_many_remainders_with_many_json_kwargs(self):
             {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'}
         )
         assert r.status_int == 200
-        assert r.body == b_('eater: 10, dummy, day=12, month=1')
+        assert r.body == b'eater: 10, dummy, day=12, month=1'
 
 
 class TestDefaultErrorRendering(PecanTestCase):
@@ -1088,7 +1079,7 @@ class RootController(object):
         r = app.get('/', status=404)
         assert r.status_int == 404
         assert r.content_type == 'text/plain'
-        assert r.body == b_(HTTPNotFound().plain_body({}))
+        assert r.body == HTTPNotFound().plain_body({}).encode('utf-8')
 
     def test_html_error(self):
         class RootController(object):
@@ -1098,7 +1089,7 @@ class RootController(object):
         r = app.get('/', headers={'Accept': 'text/html'}, status=404)
         assert r.status_int == 404
         assert r.content_type == 'text/html'
-        assert r.body == b_(HTTPNotFound().html_body({}))
+        assert r.body == HTTPNotFound().html_body({}).encode('utf-8')
 
     def test_json_error(self):
         class RootController(object):
@@ -1200,12 +1191,12 @@ def test_index(self):
         assert r.status_int == 302
         r = r.follow()
         assert r.status_int == 200
-        assert r.body == b_('it worked!')
+        assert r.body == b'it worked!'
 
     def test_internal(self):
         r = self.app_.get('/internal')
         assert r.status_int == 200
-        assert r.body == b_('it worked!')
+        assert r.body == b'it worked!'
 
     def test_internal_with_301(self):
         self.assertRaises(ValueError, self.app_.get, '/bad_internal')
@@ -1215,7 +1206,7 @@ def test_permanent_redirect(self):
         assert r.status_int == 301
         r = r.follow()
         assert r.status_int == 200
-        assert r.body == b_('it worked!')
+        assert r.body == b'it worked!'
 
     def test_x_forward_proto(self):
         class ChildController(object):
@@ -1286,7 +1277,7 @@ class RootController(object):
             def test(self, foo):
                 if foo == 'stream':
                     # mimic large file
-                    contents = six.BytesIO(b_('stream'))
+                    contents = BytesIO(b'stream')
                     response.content_type = 'application/octet-stream'
                     contents.seek(0, os.SEEK_END)
                     response.content_length = contents.tell()
@@ -1299,11 +1290,11 @@ def test(self, foo):
         app = TestApp(Pecan(RootController()))
         r = app.get('/test/stream')
         assert r.content_type == 'application/octet-stream'
-        assert r.body == b_('stream')
+        assert r.body == b'stream'
 
         r = app.get('/test/plain')
         assert r.content_type == 'text/plain'
-        assert r.body == b_('plain text')
+        assert r.body == b'plain text'
 
 
 class TestManualResponse(PecanTestCase):
@@ -1314,12 +1305,12 @@ class RootController(object):
             @expose()
             def index(self):
                 resp = webob.Response(response.environ)
-                resp.body = b_('Hello, World!')
+                resp.body = b'Hello, World!'
                 return resp
 
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
 
 class TestCustomResponseandRequest(PecanTestCase):
@@ -1353,7 +1344,7 @@ def index(self):
             response_cls=CustomResponse
         ))
         r = app.get('/')
-        assert r.body == b_('ABC')
+        assert r.body == b'ABC'
         assert r.headers.get('X-Custom-Response') == 'XYZ'
 
 
@@ -1374,7 +1365,7 @@ def index(self):
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
     def test_request_state_cleanup(self):
         """
@@ -1391,7 +1382,7 @@ def index(self):
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
         assert state.__dict__ == {}
 
@@ -1418,25 +1409,25 @@ def test_html_extension(self):
         for path in ('/index.html', '/index.html/'):
             r = self.app_.get(path)
             assert r.status_int == 200
-            assert r.body == b_('.html')
+            assert r.body == b'.html'
 
     def test_image_extension(self):
         for path in ('/index.png', '/index.png/'):
             r = self.app_.get(path)
             assert r.status_int == 200
-            assert r.body == b_('.png')
+            assert r.body == b'.png'
 
     def test_hidden_file(self):
         for path in ('/.vimrc', '/.vimrc/'):
             r = self.app_.get(path)
             assert r.status_int == 204
-            assert r.body == b_('')
+            assert r.body == b''
 
     def test_multi_dot_extension(self):
         for path in ('/gradient.min.js', '/gradient.min.js/'):
             r = self.app_.get(path)
             assert r.status_int == 200
-            assert r.body == b_('.js')
+            assert r.body == b'.js'
 
     def test_bad_content_type(self):
         class RootController(object):
@@ -1447,11 +1438,11 @@ def index(self):
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
         r = app.get('/index.html', expect_errors=True)
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
         with warnings.catch_warnings():
             warnings.simplefilter("ignore")
@@ -1470,7 +1461,7 @@ def _default(self, *args):
 
         r = app.get('/example:x.tiny')
         assert r.status_int == 200
-        assert r.body == b_('SOME VALUE')
+        assert r.body == b'SOME VALUE'
 
     def test_guessing_disabled(self):
         class RootController(object):
@@ -1485,7 +1476,7 @@ def _default(self, *args):
 
         r = app.get('/index.html')
         assert r.status_int == 200
-        assert r.body == b_('SOME VALUE')
+        assert r.body == b'SOME VALUE'
 
     def test_content_type_guessing_disabled(self):
 
@@ -1617,12 +1608,12 @@ def index(self):
     def test_root(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert b_('index') in r.body
+        assert b'index' in r.body
 
     def test_index(self):
         r = self.app_.get('/index')
         assert r.status_int == 200
-        assert b_('index') in r.body
+        assert b'index' in r.body
 
     def test_broken_clients(self):
         # for broken clients
@@ -1633,7 +1624,7 @@ def test_broken_clients(self):
     def test_sub_controller_with_trailing(self):
         r = self.app_.get('/sub/')
         assert r.status_int == 200
-        assert b_('subindex') in r.body
+        assert b'subindex' in r.body
 
     def test_sub_controller_redirect(self):
         r = self.app_.get('/sub', status=302)
@@ -1656,17 +1647,17 @@ def test_posts_fail(self):
     def test_with_args(self):
         r = self.app_.get('/arg/index/foo')
         assert r.status_int == 200
-        assert r.body == b_('foo')
+        assert r.body == b'foo'
 
     def test_accept_noncanonical(self):
         r = self.app_.get('/accept/')
         assert r.status_int == 200
-        assert r.body == b_('accept')
+        assert r.body == b'accept'
 
     def test_accept_noncanonical_no_trailing_slash(self):
         r = self.app_.get('/accept')
         assert r.status_int == 200
-        assert r.body == b_('accept')
+        assert r.body == b'accept'
 
 
 class TestNonCanonical(PecanTestCase):
@@ -1703,22 +1694,22 @@ def index(self):
     def test_index(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert b_('index') in r.body
+        assert b'index' in r.body
 
     def test_subcontroller(self):
         r = self.app_.get('/sub')
         assert r.status_int == 200
-        assert b_('subindex') in r.body
+        assert b'subindex' in r.body
 
     def test_subcontroller_with_kwargs(self):
         r = self.app_.post('/sub', dict(foo=1))
         assert r.status_int == 200
-        assert b_('subindex') in r.body
+        assert b'subindex' in r.body
 
     def test_sub_controller_with_trailing(self):
         r = self.app_.get('/sub/')
         assert r.status_int == 200
-        assert b_('subindex') in r.body
+        assert b'subindex' in r.body
 
     def test_proxy(self):
         class RootController(object):
@@ -1829,11 +1820,11 @@ def badtemplate(self):
         )
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, Jonathan!</h1>") in r.body
+        assert b"<h1>Hello, Jonathan!</h1>" in r.body
 
         r = app.get('/index.html?name=World')
         assert r.status_int == 200
-        assert b_("<h1>Hello, World!</h1>") in r.body
+        assert b"<h1>Hello, World!</h1>" in r.body
 
         error_msg = None
         try:
@@ -1858,11 +1849,11 @@ def index(self, name='Jonathan'):
         )
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, Jonathan!</h1>") in r.body
+        assert b"<h1>Hello, Jonathan!</h1>" in r.body
 
         r = app.get('/index.html?name=World')
         assert r.status_int == 200
-        assert b_("<h1>Hello, World!</h1>") in r.body
+        assert b"<h1>Hello, World!</h1>" in r.body
 
     @unittest.skipIf('jinja' not in builtin_renderers, 'Jinja not installed')
     def test_jinja(self):
@@ -1881,7 +1872,7 @@ def badtemplate(self):
         )
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, Jonathan!</h1>") in r.body
+        assert b"<h1>Hello, Jonathan!</h1>" in r.body
 
         error_msg = None
         try:
@@ -1910,11 +1901,11 @@ def badtemplate(self):
         )
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, Jonathan!</h1>") in r.body
+        assert b"<h1>Hello, Jonathan!</h1>" in r.body
 
         r = app.get('/index.html?name=World')
         assert r.status_int == 200
-        assert b_("<h1>Hello, World!</h1>") in r.body
+        assert b"<h1>Hello, World!</h1>" in r.body
 
         error_msg = None
         try:
@@ -1984,11 +1975,11 @@ def render(self, template_path, namespace):
         ))
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, eoJ!</h1>") in r.body
+        assert b"<h1>Hello, eoJ!</h1>" in r.body
 
         r = app.get('/index.html?name=Tim')
         assert r.status_int == 200
-        assert b_("<h1>Hello, miT!</h1>") in r.body
+        assert b"<h1>Hello, miT!</h1>" in r.body
 
     def test_override_template(self):
         class RootController(object):
@@ -2000,7 +1991,7 @@ def index(self):
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
         assert r.status_int == 200
-        assert b_('Override') in r.body
+        assert b'Override' in r.body
         assert r.content_type == 'text/plain'
 
     def test_render(self):
@@ -2014,7 +2005,7 @@ def index(self, name='Jonathan'):
         )
         r = app.get('/')
         assert r.status_int == 200
-        assert b_("<h1>Hello, Jonathan!</h1>") in r.body
+        assert b"<h1>Hello, Jonathan!</h1>" in r.body
 
     def test_default_json_renderer(self):
 
@@ -2039,7 +2030,7 @@ def index(self, name='Bill'):
         app = TestApp(Pecan(RootController(), default_renderer='json'))
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_("Bill")
+        assert r.body == b"Bill"
 
 
 class TestDeprecatedRouteMethod(PecanTestCase):
@@ -2063,7 +2054,7 @@ def test_required_argument(self):
             warnings.simplefilter("ignore")
             r = self.app_.get('/foo/bar/')
             assert r.status_int == 200
-            assert b_('foo, bar') in r.body
+            assert b'foo, bar' in r.body
 
 
 class TestExplicitRoute(PecanTestCase):
@@ -2080,7 +2071,7 @@ def some_path(self):
 
         r = app.get('/some-path/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
         r = app.get('/some_path/', expect_errors=True)
         assert r.status_int == 404
@@ -2102,7 +2093,7 @@ class RootController(object):
 
         r = app.get('/some-controller/some-path/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
         r = app.get('/some-controller/some_path/', expect_errors=True)
         assert r.status_int == 404
@@ -2138,11 +2129,11 @@ def index(self):
 
         r = app.get('/some-path/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
         r = app.get('/index/', expect_errors=True)
         assert r.status_int == 404
@@ -2204,10 +2195,10 @@ class RootController(BaseController):
         app = TestApp(Pecan(RootController()))
 
         r = app.get('/testing/')
-        assert r.body == b_('/testing/')
+        assert r.body == b'/testing/'
 
         r = app.get('/child/testing/')
-        assert r.body == b_('/child/testing/')
+        assert r.body == b'/child/testing/'
 
     def test_custom_route_prohibited_on_lookup(self):
         try:
@@ -2267,14 +2258,14 @@ def handle_post(self):
 
         r = app.get('/some-path/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
         r = app.get('/foo/', expect_errors=True)
         assert r.status_int == 404
 
         r = app.post('/some-path/')
         assert r.status_int == 200
-        assert r.body == b_('POST!')
+        assert r.body == b'POST!'
 
         r = app.post('/foo/', expect_errors=True)
         assert r.status_int == 404
diff --git a/pecan/tests/test_conf.py b/pecan/tests/test_conf.py
index 2c67adb..8e04144 100644
--- a/pecan/tests/test_conf.py
+++ b/pecan/tests/test_conf.py
@@ -1,9 +1,7 @@
 import os
-import sys
 import tempfile
 import unittest
 
-from six import b as b_
 from webtest import TestApp
 
 import pecan
@@ -148,7 +146,7 @@ def test_config_missing_file_on_path(self):
     def test_config_with_syntax_error(self):
         from pecan import configuration
         with tempfile.NamedTemporaryFile('wb') as f:
-            f.write(b_('\n'.join(['if false', 'var = 3'])))
+            f.write(b'\n'.join([b'if false', b'var = 3']))
             f.flush()
             configuration.Config({})
 
@@ -161,7 +159,7 @@ def test_config_with_syntax_error(self):
     def test_config_with_non_package_relative_import(self):
         from pecan import configuration
         with tempfile.NamedTemporaryFile('wb', suffix='.py') as f:
-            f.write(b_('\n'.join(['from . import variables'])))
+            f.write(b'\n'.join([b'from . import variables']))
             f.flush()
             configuration.Config({})
 
diff --git a/pecan/tests/test_generic.py b/pecan/tests/test_generic.py
index 93c8709..0d9d26e 100644
--- a/pecan/tests/test_generic.py
+++ b/pecan/tests/test_generic.py
@@ -1,8 +1,6 @@
 from json import dumps
 from webtest import TestApp
 
-from six import b as b_
-
 from pecan import Pecan, expose, abort
 from pecan.tests import PecanTestCase
 
@@ -26,11 +24,11 @@ def do_get(self):
         app = TestApp(Pecan(RootController()))
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('GET')
+        assert r.body == b'GET'
 
         r = app.post('/')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(result='POST')))
+        assert r.body == dumps(dict(result='POST')).encode('utf-8')
 
         r = app.get('/do_get', status=404)
         assert r.status_int == 404
@@ -78,11 +76,13 @@ class RootController(object):
         app = TestApp(Pecan(RootController()))
         r = app.get('/sub/sub/')
         assert r.status_int == 200
-        assert r.body == b_('GET')
+        assert r.body == b'GET'
 
         r = app.delete('/sub/sub/joe/is/cool')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(result='joe', args='is, cool')))
+        assert r.body == dumps(
+            dict(result='joe', args='is, cool')
+        ).encode('utf-8')
 
 
 class TestGenericWithSpecialMethods(PecanTestCase):
diff --git a/pecan/tests/test_hooks.py b/pecan/tests/test_hooks.py
index 902074b..324a3f2 100644
--- a/pecan/tests/test_hooks.py
+++ b/pecan/tests/test_hooks.py
@@ -1,11 +1,8 @@
 import inspect
 import operator
+from io import StringIO
 
 from webtest import TestApp
-from six import PY3
-from six import b as b_
-from six import u as u_
-from six.moves import cStringIO as StringIO
 
 from pecan import make_app, expose, redirect, abort, rest, Request, Response
 from pecan.hooks import (
@@ -16,7 +13,7 @@
 from pecan.tests import PecanTestCase
 
 # The `inspect.Arguments` namedtuple is different between PY2/3
-kwargs = operator.attrgetter('varkw' if PY3 else 'keywords')
+kwargs = operator.attrgetter('varkw')
 
 
 class TestHooks(PecanTestCase):
@@ -46,7 +43,7 @@ def on_error(self, state, e):
         app = TestApp(make_app(RootController(), hooks=[SimpleHook()]))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'on_route'
@@ -84,7 +81,7 @@ def on_error(self, state, e):
         ]))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 10
         assert run_hook[0] == 'on_route1'
@@ -125,7 +122,7 @@ def on_route(self, state):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello World!')
+        assert response.body == b'Hello World!'
 
         assert len(run_hook) == 2
         assert run_hook[0] == 'on_route'
@@ -154,7 +151,7 @@ def on_error(self, state, e):
                 run_hook.append('error')
 
                 r = Response()
-                r.text = u_('on_error')
+                r.text = 'on_error'
 
                 return r
 
@@ -201,7 +198,7 @@ def on_error(self, state, e):
         app = TestApp(papp)
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 10
         assert run_hook[0] == 'on_route3'
@@ -258,7 +255,7 @@ def index(self):
         app = TestApp(make_app(RootController()))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 1
         assert run_hook[0] == 'inside'
@@ -267,7 +264,7 @@ def index(self):
 
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Inside here!')
+        assert response.body == b'Inside here!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'before'
@@ -277,7 +274,7 @@ def index(self):
         run_hook = []
         response = app.get('/sub/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Deep inside here!')
+        assert response.body == b'Deep inside here!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'before'
@@ -322,7 +319,7 @@ def index(self):
         app = TestApp(make_app(RootController(), hooks=[SimpleHook(1)]))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'on_route1'
@@ -334,7 +331,7 @@ def index(self):
 
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Inside here!')
+        assert response.body == b'Inside here!'
 
         assert len(run_hook) == 6
         assert run_hook[0] == 'on_route1'
@@ -395,7 +392,7 @@ def index(self):
         app = TestApp(papp)
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'simple - before hook', run_hook[0]
@@ -406,7 +403,7 @@ def index(self):
         run_hook = []
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('This is sub controller!')
+        assert response.body == b'This is sub controller!'
 
         assert len(run_hook) == 4, run_hook
         assert run_hook[0] == 'simple - before hook', run_hook[0]
@@ -434,7 +431,7 @@ def after(self, state):
 
         app = TestApp(make_app(RootController(), hooks=[SimpleHook()]))
         response = app.get('/internal')
-        assert response.body == b_('it worked!')
+        assert response.body == b'it worked!'
 
         assert len(run_hook) == 1
 
@@ -830,7 +827,7 @@ def gen(event):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'start_ro'
@@ -841,7 +838,7 @@ def gen(event):
 
         response = app.post('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'start'
@@ -936,7 +933,7 @@ def gen(event):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Index Method!')
+        assert response.body == b'Index Method!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'start_ro'
@@ -947,7 +944,7 @@ def gen(event):
 
         response = app.post('/')
         assert response.status_int == 200
-        assert response.body == b_('Index Method!')
+        assert response.body == b'Index Method!'
 
         assert len(run_hook) == 5
         assert run_hook[0] == 'start'
@@ -960,7 +957,7 @@ def gen(event):
 
         response = app.get('/decorated')
         assert response.status_int == 200
-        assert response.body == b_('Decorated Method!')
+        assert response.body == b'Decorated Method!'
 
         assert len(run_hook) == 7
         assert run_hook[0] == 'start_ro'
@@ -1065,7 +1062,7 @@ def gen(event):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'start_ro'
@@ -1078,7 +1075,7 @@ def gen(event):
 
         response = app.post('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'start'
@@ -1308,7 +1305,7 @@ def gen(event):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 6
         assert run_hook[0] == 'start_ro'
@@ -1324,7 +1321,7 @@ def gen(event):
 
         response = app.post('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'start'
@@ -1433,7 +1430,7 @@ def gen(event):
 
         response = app.get('/generic')
         assert response.status_int == 200
-        assert response.body == b_('generic get')
+        assert response.body == b'generic get'
         assert len(run_hook) == 6
         assert run_hook[0] == 'start_ro'
         assert run_hook[1] == 'clear'
@@ -1451,7 +1448,7 @@ def gen(event):
 
         response = app.post('/generic')
         assert response.status_int == 200
-        assert response.body == b_('generic post')
+        assert response.body == b'generic post'
         assert len(run_hook) == 4
         assert run_hook[0] == 'start'
         assert run_hook[1] == 'inside'
@@ -1525,7 +1522,7 @@ def index(self):
         out = _stdout.getvalue()
 
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
         assert 'path' in out
         assert 'method' in out
         assert 'status' in out
@@ -1592,7 +1589,7 @@ def index(self):
         out = _stdout.getvalue()
 
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
         assert '/' in out
         assert 'path' in out
         assert 'method' not in out
@@ -1627,7 +1624,7 @@ def index(self):
         out = _stdout.getvalue()
 
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
         assert out == ''
 
     def test_item_not_in_defaults(self):
@@ -1654,7 +1651,7 @@ def index(self):
         out = _stdout.getvalue()
 
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
         assert 'date' in out
         assert 'method' not in out
         assert 'status' not in out
@@ -1724,10 +1721,10 @@ def testing123(self):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
         assert response.headers['X-Testing'] == 'XYZ'
 
         response = app.delete('/100/')
         assert response.status_int == 200
-        assert response.body == b_('Deleting 100')
+        assert response.body == b'Deleting 100'
         assert response.headers['X-Testing'] == 'XYZ'
diff --git a/pecan/tests/test_jsonify.py b/pecan/tests/test_jsonify.py
index 86a76e2..91ec523 100644
--- a/pecan/tests/test_jsonify.py
+++ b/pecan/tests/test_jsonify.py
@@ -4,6 +4,7 @@
 try:
     from sqlalchemy import orm, schema, types
     from sqlalchemy.engine import create_engine
+    from sqlalchemy.orm import registry
 except ImportError:
     create_engine = None  # noqa
 
@@ -179,6 +180,7 @@ def keys(self):
     def create_sa_proxies(self):
 
         # create the table and mapper
+        mapper_registry = registry()
         metadata = schema.MetaData()
         user_table = schema.Table(
             'user',
@@ -190,25 +192,24 @@ def create_sa_proxies(self):
 
         class User(object):
             pass
-        orm.mapper(User, user_table)
+        mapper_registry.map_imperatively(User, user_table)
 
         # create the session
         engine = create_engine('sqlite:///:memory:')
         metadata.bind = engine
-        metadata.create_all()
+        metadata.create_all(metadata.bind)
         session = orm.sessionmaker(bind=engine)()
 
         # add some dummy data
-        user_table.insert().execute([
-            {'first_name': 'Jonathan', 'last_name': 'LaCour'},
-            {'first_name': 'Yoann', 'last_name': 'Roman'}
-        ])
+        session.add(User(first_name='Jonathan', last_name='LaCour'))
+        session.add(User(first_name='Ryan', last_name='Petrello'))
+        session.commit()
 
         # get the SA objects
         self.sa_object = session.query(User).first()
         select = user_table.select()
-        self.result_proxy = select.execute()
-        self.row_proxy = select.execute().fetchone()
+        self.result_proxy = session.execute(select)
+        self.row_proxy = session.execute(select).fetchone()
 
     def test_sa_object(self):
         result = encode(self.sa_object)
@@ -220,7 +221,7 @@ def test_result_proxy(self):
         result = encode(self.result_proxy)
         assert loads(result) == {'count': 2, 'rows': [
             {'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour'},
-            {'id': 2, 'first_name': 'Yoann', 'last_name': 'Roman'}
+            {'id': 2, 'first_name': 'Ryan', 'last_name': 'Petrello'}
         ]}
 
     def test_row_proxy(self):
diff --git a/pecan/tests/test_no_thread_locals.py b/pecan/tests/test_no_thread_locals.py
index 3fbcd88..98b2f2b 100644
--- a/pecan/tests/test_no_thread_locals.py
+++ b/pecan/tests/test_no_thread_locals.py
@@ -4,8 +4,6 @@
 from unittest import mock
 
 from webtest import TestApp
-from six import b as b_
-from six import u as u_
 import webob
 
 from pecan import Pecan, expose, abort, Request, Response
@@ -48,7 +46,7 @@ def test_locals_are_not_used(self):
             app = TestApp(Pecan(self.root(), use_context_locals=False))
             r = app.get('/')
             assert r.status_int == 200
-            assert r.body == b_('Hello, World!')
+            assert r.body == b'Hello, World!'
 
             self.assertRaises(AssertionError, Pecan, self.root)
 
@@ -99,17 +97,17 @@ def index(self, req, resp):
     def test_empty_root(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
     def test_index(self):
         r = self.app_.get('/index')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
     def test_index_html(self):
         r = self.app_.get('/index.html')
         assert r.status_int == 200
-        assert r.body == b_('Hello, World!')
+        assert r.body == b'Hello, World!'
 
 
 class TestManualResponse(PecanTestCase):
@@ -120,12 +118,12 @@ class RootController(object):
             @expose()
             def index(self, req, resp):
                 resp = webob.Response(resp.environ)
-                resp.body = b_('Hello, World!')
+                resp.body = b'Hello, World!'
                 return resp
 
         app = TestApp(Pecan(RootController(), use_context_locals=False))
         r = app.get('/')
-        assert r.body == b_('Hello, World!'), r.body
+        assert r.body == b'Hello, World!', r.body
 
 
 class TestDispatch(PecanTestCase):
@@ -180,22 +178,22 @@ def deeper(self, req, resp):
     def test_index(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
     def test_one_level(self):
         r = self.app_.get('/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/deeper')
+        assert r.body == b'/deeper'
 
     def test_one_level_with_trailing(self):
         r = self.app_.get('/sub/')
         assert r.status_int == 200
-        assert r.body == b_('/sub/')
+        assert r.body == b'/sub/'
 
     def test_two_levels(self):
         r = self.app_.get('/sub/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/sub/deeper')
+        assert r.body == b'/sub/deeper'
 
     def test_two_levels_with_trailing(self):
         r = self.app_.get('/sub/sub/')
@@ -204,7 +202,7 @@ def test_two_levels_with_trailing(self):
     def test_three_levels(self):
         r = self.app_.get('/sub/sub/deeper')
         assert r.status_int == 200
-        assert r.body == b_('/sub/sub/deeper')
+        assert r.body == b'/sub/sub/deeper'
 
 
 class TestLookups(PecanTestCase):
@@ -237,17 +235,17 @@ def _lookup(self, someID, *remainder):
     def test_index(self):
         r = self.app_.get('/')
         assert r.status_int == 200
-        assert r.body == b_('/')
+        assert r.body == b'/'
 
     def test_lookup(self):
         r = self.app_.get('/100/')
         assert r.status_int == 200
-        assert r.body == b_('/100')
+        assert r.body == b'/100'
 
     def test_lookup_with_method(self):
         r = self.app_.get('/100/name')
         assert r.status_int == 200
-        assert r.body == b_('/100/name')
+        assert r.body == b'/100/name'
 
     def test_lookup_with_wrong_argspec(self):
         class RootController(object):
@@ -288,7 +286,7 @@ def test_canonical_lookup(self):
         assert self.app_.get('/users', expect_errors=404).status_int == 404
         assert self.app_.get('/users/', expect_errors=404).status_int == 404
         assert self.app_.get('/users/100').status_int == 302
-        assert self.app_.get('/users/100/').body == b_('100')
+        assert self.app_.get('/users/100/').body == b'100'
 
 
 class TestControllerArguments(PecanTestCase):
@@ -372,12 +370,12 @@ def test_required_argument(self):
     def test_single_argument(self):
         r = self.app_.get('/1')
         assert r.status_int == 200
-        assert r.body == b_('index: 1')
+        assert r.body == b'index: 1'
 
     def test_single_argument_with_encoded_url(self):
         r = self.app_.get('/This%20is%20a%20test%21')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_two_arguments(self):
         r = self.app_.get('/1/dummy', status=404)
@@ -386,90 +384,90 @@ def test_two_arguments(self):
     def test_keyword_argument(self):
         r = self.app_.get('/?id=2')
         assert r.status_int == 200
-        assert r.body == b_('index: 2')
+        assert r.body == b'index: 2'
 
     def test_keyword_argument_with_encoded_url(self):
         r = self.app_.get('/?id=This%20is%20a%20test%21')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_argument_and_keyword_argument(self):
         r = self.app_.get('/3?id=three')
         assert r.status_int == 200
-        assert r.body == b_('index: 3')
+        assert r.body == b'index: 3'
 
     def test_encoded_argument_and_keyword_argument(self):
         r = self.app_.get('/This%20is%20a%20test%21?id=three')
         assert r.status_int == 200
-        assert r.body == b_('index: This is a test!')
+        assert r.body == b'index: This is a test!'
 
     def test_explicit_kwargs(self):
         r = self.app_.post('/', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_path_with_explicit_kwargs(self):
         r = self.app_.post('/4', {'id': 'four'})
         assert r.status_int == 200
-        assert r.body == b_('index: 4')
+        assert r.body == b'index: 4'
 
     def test_multiple_kwargs(self):
         r = self.app_.get('/?id=5&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('index: 5')
+        assert r.body == b'index: 5'
 
     def test_kwargs_from_root(self):
         r = self.app_.post('/', {'id': '6', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('index: 6')
+        assert r.body == b'index: 6'
 
         # multiple args
 
     def test_multiple_positional_arguments(self):
         r = self.app_.get('/multiple/one/two')
         assert r.status_int == 200
-        assert r.body == b_('multiple: one, two')
+        assert r.body == b'multiple: one, two'
 
     def test_multiple_positional_arguments_with_url_encode(self):
         r = self.app_.get('/multiple/One%20/Two%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple: One , Two!')
+        assert r.body == b'multiple: One , Two!'
 
     def test_multiple_positional_arguments_with_kwargs(self):
         r = self.app_.get('/multiple?one=three&two=four')
         assert r.status_int == 200
-        assert r.body == b_('multiple: three, four')
+        assert r.body == b'multiple: three, four'
 
     def test_multiple_positional_arguments_with_url_encoded_kwargs(self):
         r = self.app_.get('/multiple?one=Three%20&two=Four%20%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple: Three , Four !')
+        assert r.body == b'multiple: Three , Four !'
 
     def test_positional_args_with_dictionary_kwargs(self):
         r = self.app_.post('/multiple', {'one': 'five', 'two': 'six'})
         assert r.status_int == 200
-        assert r.body == b_('multiple: five, six')
+        assert r.body == b'multiple: five, six'
 
     def test_positional_args_with_url_encoded_dictionary_kwargs(self):
         r = self.app_.post('/multiple', {'one': 'Five%20', 'two': 'Six%20%21'})
         assert r.status_int == 200
-        assert r.body == b_('multiple: Five%20, Six%20%21')
+        assert r.body == b'multiple: Five%20, Six%20%21'
 
         # optional arg
     def test_optional_arg(self):
         r = self.app_.get('/optional')
         assert r.status_int == 200
-        assert r.body == b_('optional: None')
+        assert r.body == b'optional: None'
 
     def test_multiple_optional(self):
         r = self.app_.get('/optional/1')
         assert r.status_int == 200
-        assert r.body == b_('optional: 1')
+        assert r.body == b'optional: 1'
 
     def test_multiple_optional_url_encoded(self):
         r = self.app_.get('/optional/Some%20Number')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_multiple_optional_missing(self):
         r = self.app_.get('/optional/2/dummy', status=404)
@@ -478,57 +476,57 @@ def test_multiple_optional_missing(self):
     def test_multiple_with_kwargs(self):
         r = self.app_.get('/optional?id=2')
         assert r.status_int == 200
-        assert r.body == b_('optional: 2')
+        assert r.body == b'optional: 2'
 
     def test_multiple_with_url_encoded_kwargs(self):
         r = self.app_.get('/optional?id=Some%20Number')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_multiple_args_with_url_encoded_kwargs(self):
         r = self.app_.get('/optional/3?id=three')
         assert r.status_int == 200
-        assert r.body == b_('optional: 3')
+        assert r.body == b'optional: 3'
 
     def test_url_encoded_positional_args(self):
         r = self.app_.get('/optional/Some%20Number?id=three')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_kwargs(self):
         r = self.app_.post('/optional', {'id': '4'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 4')
+        assert r.body == b'optional: 4'
 
     def test_optional_arg_with_url_encoded_kwargs(self):
         r = self.app_.post('/optional', {'id': 'Some%20Number'})
         assert r.status_int == 200
-        assert r.body == b_('optional: Some%20Number')
+        assert r.body == b'optional: Some%20Number'
 
     def test_multiple_positional_arguments_with_dictionary_kwargs(self):
         r = self.app_.post('/optional/5', {'id': 'five'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 5')
+        assert r.body == b'optional: 5'
 
     def test_multiple_positional_url_encoded_arguments_with_kwargs(self):
         r = self.app_.post('/optional/Some%20Number', {'id': 'five'})
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_multiple_kwargs(self):
         r = self.app_.get('/optional?id=6&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('optional: 6')
+        assert r.body == b'optional: 6'
 
     def test_optional_arg_with_multiple_url_encoded_kwargs(self):
         r = self.app_.get('/optional?id=Some%20Number&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('optional: Some Number')
+        assert r.body == b'optional: Some Number'
 
     def test_optional_arg_with_multiple_dictionary_kwargs(self):
         r = self.app_.post('/optional', {'id': '7', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('optional: 7')
+        assert r.body == b'optional: 7'
 
     def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self):
         r = self.app_.post('/optional', {
@@ -536,34 +534,34 @@ def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self):
             'dummy': 'dummy'
         })
         assert r.status_int == 200
-        assert r.body == b_('optional: Some%20Number')
+        assert r.body == b'optional: Some%20Number'
 
         # multiple optional args
 
     def test_multiple_optional_positional_args(self):
         r = self.app_.get('/multiple_optional')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, None')
+        assert r.body == b'multiple_optional: None, None, None'
 
     def test_multiple_optional_positional_args_one_arg(self):
         r = self.app_.get('/multiple_optional/1')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_one_url_encoded_arg(self):
         r = self.app_.get('/multiple_optional/One%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_all_args(self):
         r = self.app_.get('/multiple_optional/1/2/3')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_positional_args_all_url_encoded_args(self):
         r = self.app_.get('/multiple_optional/One%21/Two%21/Three%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, Two!, Three!')
+        assert r.body == b'multiple_optional: One!, Two!, Three!'
 
     def test_multiple_optional_positional_args_too_many_args(self):
         r = self.app_.get('/multiple_optional/1/2/3/dummy', status=404)
@@ -572,54 +570,54 @@ def test_multiple_optional_positional_args_too_many_args(self):
     def test_multiple_optional_positional_args_with_kwargs(self):
         r = self.app_.get('/multiple_optional?one=1')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_url_encoded_kwargs(self):
         r = self.app_.get('/multiple_optional?one=One%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_with_string_kwargs(self):
         r = self.app_.get('/multiple_optional/1?one=one')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_encoded_str_kwargs(self):
         r = self.app_.get('/multiple_optional/One%21?one=one')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_positional_args_with_dict_kwargs(self):
         r = self.app_.post('/multiple_optional', {'one': '1'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_positional_args_with_encoded_dict_kwargs(self):
         r = self.app_.post('/multiple_optional', {'one': 'One%21'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One%21, None, None')
+        assert r.body == b'multiple_optional: One%21, None, None'
 
     def test_multiple_optional_positional_args_and_dict_kwargs(self):
         r = self.app_.post('/multiple_optional/1', {'one': 'one'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, None, None')
+        assert r.body == b'multiple_optional: 1, None, None'
 
     def test_multiple_optional_encoded_positional_args_and_dict_kwargs(self):
         r = self.app_.post('/multiple_optional/One%21', {'one': 'one'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, None, None')
+        assert r.body == b'multiple_optional: One!, None, None'
 
     def test_multiple_optional_args_with_multiple_kwargs(self):
         r = self.app_.get('/multiple_optional?one=1&two=2&three=3&four=4')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_args_with_multiple_encoded_kwargs(self):
         r = self.app_.get(
             '/multiple_optional?one=One%21&two=Two%21&three=Three%21&four=4'
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One!, Two!, Three!')
+        assert r.body == b'multiple_optional: One!, Two!, Three!'
 
     def test_multiple_optional_args_with_multiple_dict_kwargs(self):
         r = self.app_.post(
@@ -627,7 +625,7 @@ def test_multiple_optional_args_with_multiple_dict_kwargs(self):
             {'one': '1', 'two': '2', 'three': '3', 'four': '4'}
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: 1, 2, 3')
+        assert r.body == b'multiple_optional: 1, 2, 3'
 
     def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self):
         r = self.app_.post(
@@ -640,52 +638,52 @@ def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self):
             }
         )
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: One%21, Two%21, Three%21')
+        assert r.body == b'multiple_optional: One%21, Two%21, Three%21'
 
     def test_multiple_optional_args_with_last_kwarg(self):
         r = self.app_.get('/multiple_optional?three=3')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, 3')
+        assert r.body == b'multiple_optional: None, None, 3'
 
     def test_multiple_optional_args_with_last_encoded_kwarg(self):
         r = self.app_.get('/multiple_optional?three=Three%21')
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, None, Three!')
+        assert r.body == b'multiple_optional: None, None, Three!'
 
     def test_multiple_optional_args_with_middle_arg(self):
         r = self.app_.get('/multiple_optional', {'two': '2'})
         assert r.status_int == 200
-        assert r.body == b_('multiple_optional: None, 2, None')
+        assert r.body == b'multiple_optional: None, 2, None'
 
     def test_variable_args(self):
         r = self.app_.get('/variable_args')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_multiple_variable_args(self):
         r = self.app_.get('/variable_args/1/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: 1, dummy')
+        assert r.body == b'variable_args: 1, dummy'
 
     def test_multiple_encoded_variable_args(self):
         r = self.app_.get('/variable_args/Testing%20One%20Two/Three%21')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: Testing One Two, Three!')
+        assert r.body == b'variable_args: Testing One Two, Three!'
 
     def test_variable_args_with_kwargs(self):
         r = self.app_.get('/variable_args?id=2&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_variable_args_with_dict_kwargs(self):
         r = self.app_.post('/variable_args', {'id': '3', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('variable_args: ')
+        assert r.body == b'variable_args: '
 
     def test_variable_kwargs(self):
         r = self.app_.get('/variable_kwargs')
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: ')
+        assert r.body == b'variable_kwargs: '
 
     def test_multiple_variable_kwargs(self):
         r = self.app_.get('/variable_kwargs/1/dummy', status=404)
@@ -694,19 +692,19 @@ def test_multiple_variable_kwargs(self):
     def test_multiple_variable_kwargs_with_explicit_kwargs(self):
         r = self.app_.get('/variable_kwargs?id=2&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=dummy, id=2')
+        assert r.body == b'variable_kwargs: dummy=dummy, id=2'
 
     def test_multiple_variable_kwargs_with_explicit_encoded_kwargs(self):
         r = self.app_.get(
             '/variable_kwargs?id=Two%21&dummy=This%20is%20a%20test'
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=This is a test, id=Two!')
+        assert r.body == b'variable_kwargs: dummy=This is a test, id=Two!'
 
     def test_multiple_variable_kwargs_with_dict_kwargs(self):
         r = self.app_.post('/variable_kwargs', {'id': '3', 'dummy': 'dummy'})
         assert r.status_int == 200
-        assert r.body == b_('variable_kwargs: dummy=dummy, id=3')
+        assert r.body == b'variable_kwargs: dummy=dummy, id=3'
 
     def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self):
         r = self.app_.post(
@@ -714,43 +712,43 @@ def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self):
             {'id': 'Three%21', 'dummy': 'This%20is%20a%20test'}
         )
         assert r.status_int == 200
-        result = 'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21'
-        assert r.body == b_(result)
+        result = b'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21'
+        assert r.body == result
 
     def test_variable_all(self):
         r = self.app_.get('/variable_all')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: ')
+        assert r.body == b'variable_all: '
 
     def test_variable_all_with_one_extra(self):
         r = self.app_.get('/variable_all/1')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 1')
+        assert r.body == b'variable_all: 1'
 
     def test_variable_all_with_two_extras(self):
         r = self.app_.get('/variable_all/2/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 2, dummy')
+        assert r.body == b'variable_all: 2, dummy'
 
     def test_variable_mixed(self):
         r = self.app_.get('/variable_all/3?month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 3, day=12, month=1')
+        assert r.body == b'variable_all: 3, day=12, month=1'
 
     def test_variable_mixed_explicit(self):
         r = self.app_.get('/variable_all/4?id=four&month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 4, day=12, id=four, month=1')
+        assert r.body == b'variable_all: 4, day=12, id=four, month=1'
 
     def test_variable_post(self):
         r = self.app_.post('/variable_all/5/dummy')
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 5, dummy')
+        assert r.body == b'variable_all: 5, dummy'
 
     def test_variable_post_with_kwargs(self):
         r = self.app_.post('/variable_all/6', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 6, day=12, month=1')
+        assert r.body == b'variable_all: 6, day=12, month=1'
 
     def test_variable_post_mixed(self):
         r = self.app_.post(
@@ -758,7 +756,7 @@ def test_variable_post_mixed(self):
             {'id': 'seven', 'month': '1', 'day': '12'}
         )
         assert r.status_int == 200
-        assert r.body == b_('variable_all: 7, day=12, id=seven, month=1')
+        assert r.body == b'variable_all: 7, day=12, id=seven, month=1'
 
     def test_no_remainder(self):
         try:
@@ -778,47 +776,47 @@ def test_no_remainder(self):
     def test_one_remainder(self):
         r = self.app_.get('/eater/1')
         assert r.status_int == 200
-        assert r.body == b_('eater: 1, None, ')
+        assert r.body == b'eater: 1, None, '
 
     def test_two_remainders(self):
         r = self.app_.get('/eater/2/dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 2, dummy, ')
+        assert r.body == b'eater: 2, dummy, '
 
     def test_many_remainders(self):
         r = self.app_.get('/eater/3/dummy/foo/bar')
         assert r.status_int == 200
-        assert r.body == b_('eater: 3, dummy, foo, bar')
+        assert r.body == b'eater: 3, dummy, foo, bar'
 
     def test_remainder_with_kwargs(self):
         r = self.app_.get('/eater/4?month=1&day=12')
         assert r.status_int == 200
-        assert r.body == b_('eater: 4, None, day=12, month=1')
+        assert r.body == b'eater: 4, None, day=12, month=1'
 
     def test_remainder_with_many_kwargs(self):
         r = self.app_.get('/eater/5?id=five&month=1&day=12&dummy=dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 5, dummy, day=12, month=1')
+        assert r.body == b'eater: 5, dummy, day=12, month=1'
 
     def test_post_remainder(self):
         r = self.app_.post('/eater/6')
         assert r.status_int == 200
-        assert r.body == b_('eater: 6, None, ')
+        assert r.body == b'eater: 6, None, '
 
     def test_post_three_remainders(self):
         r = self.app_.post('/eater/7/dummy')
         assert r.status_int == 200
-        assert r.body == b_('eater: 7, dummy, ')
+        assert r.body == b'eater: 7, dummy, '
 
     def test_post_many_remainders(self):
         r = self.app_.post('/eater/8/dummy/foo/bar')
         assert r.status_int == 200
-        assert r.body == b_('eater: 8, dummy, foo, bar')
+        assert r.body == b'eater: 8, dummy, foo, bar'
 
     def test_post_remainder_with_kwargs(self):
         r = self.app_.post('/eater/9', {'month': '1', 'day': '12'})
         assert r.status_int == 200
-        assert r.body == b_('eater: 9, None, day=12, month=1')
+        assert r.body == b'eater: 9, None, day=12, month=1'
 
     def test_post_many_remainders_with_many_kwargs(self):
         r = self.app_.post(
@@ -826,7 +824,7 @@ def test_post_many_remainders_with_many_kwargs(self):
             {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'}
         )
         assert r.status_int == 200
-        assert r.body == b_('eater: 10, dummy, day=12, month=1')
+        assert r.body == b'eater: 10, dummy, day=12, month=1'
 
 
 class TestRestController(PecanTestCase):
@@ -915,28 +913,30 @@ class RootController(object):
     def test_get_all(self):
         r = self.app_.get('/things')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(items=['zero', 'one', 'two', 'three'])))
+        assert r.body == dumps(
+            dict(items=['zero', 'one', 'two', 'three'])
+        ).encode('utf-8')
 
     def test_get_one(self):
-        for i, value in enumerate(['zero', 'one', 'two', 'three']):
+        for i, value in enumerate([b'zero', b'one', b'two', b'three']):
             r = self.app_.get('/things/%d' % i)
             assert r.status_int == 200
-            assert r.body == b_(value)
+            assert r.body == value
 
     def test_post(self):
         r = self.app_.post('/things', {'value': 'four'})
         assert r.status_int == 302
-        assert r.body == b_('CREATED')
+        assert r.body == b'CREATED'
 
     def test_custom_action(self):
         r = self.app_.get('/things/3/edit')
         assert r.status_int == 200
-        assert r.body == b_('EDIT three')
+        assert r.body == b'EDIT three'
 
     def test_put(self):
         r = self.app_.put('/things/3', {'value': 'THREE!'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
     def test_put_with_method_parameter_and_get(self):
         r = self.app_.get('/things/3?_method=put', {'value': 'X'}, status=405)
@@ -945,17 +945,17 @@ def test_put_with_method_parameter_and_get(self):
     def test_put_with_method_parameter_and_post(self):
         r = self.app_.post('/things/3?_method=put', {'value': 'THREE!'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
     def test_get_delete(self):
         r = self.app_.get('/things/3/delete')
         assert r.status_int == 200
-        assert r.body == b_('DELETE three')
+        assert r.body == b'DELETE three'
 
     def test_delete_method(self):
         r = self.app_.delete('/things/3')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
     def test_delete_with_method_parameter(self):
         r = self.app_.get('/things/3?_method=DELETE', status=405)
@@ -964,27 +964,27 @@ def test_delete_with_method_parameter(self):
     def test_delete_with_method_parameter_and_post(self):
         r = self.app_.post('/things/3?_method=DELETE')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
     def test_custom_method_type(self):
         r = self.app_.request('/things', method='RESET')
         assert r.status_int == 200
-        assert r.body == b_('RESET')
+        assert r.body == b'RESET'
 
     def test_custom_method_type_with_method_parameter(self):
         r = self.app_.get('/things?_method=RESET')
         assert r.status_int == 200
-        assert r.body == b_('RESET')
+        assert r.body == b'RESET'
 
     def test_options(self):
         r = self.app_.request('/things', method='OPTIONS')
         assert r.status_int == 200
-        assert r.body == b_('OPTIONS')
+        assert r.body == b'OPTIONS'
 
     def test_options_with_method_parameter(self):
         r = self.app_.post('/things', {'_method': 'OPTIONS'})
         assert r.status_int == 200
-        assert r.body == b_('OPTIONS')
+        assert r.body == b'OPTIONS'
 
     def test_other_custom_action(self):
         with warnings.catch_warnings():
@@ -1001,7 +1001,7 @@ def test_nested_controller_with_trailing_slash(self):
             warnings.simplefilter("ignore")
             r = self.app_.request('/things/others/', method='MISC')
             assert r.status_int == 200
-            assert r.body == b_('OTHERS')
+            assert r.body == b'OTHERS'
 
     def test_nested_controller_without_trailing_slash(self):
         with warnings.catch_warnings():
@@ -1017,19 +1017,19 @@ def test_named_action(self):
         # test custom "GET" request "length"
         r = self.app_.get('/things/1/length')
         assert r.status_int == 200
-        assert r.body == b_(str(len('one')))
+        assert r.body == b'3'
 
     def test_named_nested_action(self):
         # test custom "GET" request through subcontroller
         r = self.app_.get('/things/others/echo?value=test')
         assert r.status_int == 200
-        assert r.body == b_('test')
+        assert r.body == b'test'
 
     def test_nested_post(self):
         # test custom "POST" request through subcontroller
         r = self.app_.post('/things/others/echo', {'value': 'test'})
         assert r.status_int == 200
-        assert r.body == b_('test')
+        assert r.body == b'test'
 
 
 class TestHooks(PecanTestCase):
@@ -1063,7 +1063,7 @@ def on_error(self, state, e):
         ))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'on_route'
@@ -1101,7 +1101,7 @@ def on_error(self, state, e):
         ], use_context_locals=False))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 10
         assert run_hook[0] == 'on_route1'
@@ -1142,7 +1142,7 @@ def on_route(self, state):
 
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello World!')
+        assert response.body == b'Hello World!'
 
         assert len(run_hook) == 2
         assert run_hook[0] == 'on_route'
@@ -1171,7 +1171,7 @@ def on_error(self, state, e):
                 run_hook.append('error')
 
                 r = webob.Response()
-                r.text = u_('on_error')
+                r.text = 'on_error'
 
                 return r
 
@@ -1218,7 +1218,7 @@ def on_error(self, state, e):
         app = TestApp(papp)
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 10
         assert run_hook[0] == 'on_route3'
@@ -1275,7 +1275,7 @@ def index(self, req, resp):
         app = TestApp(Pecan(RootController(), use_context_locals=False))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 1
         assert run_hook[0] == 'inside'
@@ -1284,7 +1284,7 @@ def index(self, req, resp):
 
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Inside here!')
+        assert response.body == b'Inside here!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'before'
@@ -1294,7 +1294,7 @@ def index(self, req, resp):
         run_hook = []
         response = app.get('/sub/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Deep inside here!')
+        assert response.body == b'Deep inside here!'
 
         assert len(run_hook) == 3
         assert run_hook[0] == 'before'
@@ -1343,7 +1343,7 @@ def index(self, req, resp):
         ))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         assert len(run_hook) == 4
         assert run_hook[0] == 'on_route1'
@@ -1355,7 +1355,7 @@ def index(self, req, resp):
 
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Inside here!')
+        assert response.body == b'Inside here!'
 
         assert len(run_hook) == 6
         assert run_hook[0] == 'on_route1'
diff --git a/pecan/tests/test_rest.py b/pecan/tests/test_rest.py
index 0151cc0..317283f 100644
--- a/pecan/tests/test_rest.py
+++ b/pecan/tests/test_rest.py
@@ -6,7 +6,6 @@
 import sys
 import warnings
 
-from six import b as b_, PY3
 from webtest import TestApp
 
 from pecan import abort, expose, make_app, response, redirect
@@ -107,38 +106,40 @@ class RootController(object):
         # test get_all
         r = app.get('/things')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(items=ThingsController.data)))
+        assert r.body == dumps(
+            dict(items=ThingsController.data)
+        ).encode('utf-8')
 
         # test get_one
         for i, value in enumerate(ThingsController.data):
             r = app.get('/things/%d' % i)
             assert r.status_int == 200
-            assert r.body == b_(value)
+            assert r.body == value.encode('utf-8')
 
         # test post
         r = app.post('/things', {'value': 'four'})
         assert r.status_int == 302
-        assert r.body == b_('CREATED')
+        assert r.body == b'CREATED'
 
         # make sure it works
         r = app.get('/things/4')
         assert r.status_int == 200
-        assert r.body == b_('four')
+        assert r.body == b'four'
 
         # test edit
         r = app.get('/things/3/edit')
         assert r.status_int == 200
-        assert r.body == b_('EDIT three')
+        assert r.body == b'EDIT three'
 
         # test put
         r = app.put('/things/4', {'value': 'FOUR'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/things/4')
         assert r.status_int == 200
-        assert r.body == b_('FOUR')
+        assert r.body == b'FOUR'
 
         # test put with _method parameter and GET
         r = app.get('/things/4?_method=put', {'value': 'FOUR!'}, status=405)
@@ -147,27 +148,27 @@ class RootController(object):
         # make sure it works
         r = app.get('/things/4')
         assert r.status_int == 200
-        assert r.body == b_('FOUR')
+        assert r.body == b'FOUR'
 
         # test put with _method parameter and POST
         r = app.post('/things/4?_method=put', {'value': 'FOUR!'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/things/4')
         assert r.status_int == 200
-        assert r.body == b_('FOUR!')
+        assert r.body == b'FOUR!'
 
         # test get delete
         r = app.get('/things/4/delete')
         assert r.status_int == 200
-        assert r.body == b_('DELETE FOUR!')
+        assert r.body == b'DELETE FOUR!'
 
         # test delete
         r = app.delete('/things/4')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/things')
@@ -186,7 +187,7 @@ class RootController(object):
         # test delete with _method parameter and POST
         r = app.post('/things/3?_method=DELETE')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/things')
@@ -196,22 +197,22 @@ class RootController(object):
         # test "RESET" custom action
         r = app.request('/things', method='RESET')
         assert r.status_int == 200
-        assert r.body == b_('RESET')
+        assert r.body == b'RESET'
 
         # test "RESET" custom action with _method parameter
         r = app.get('/things?_method=RESET')
         assert r.status_int == 200
-        assert r.body == b_('RESET')
+        assert r.body == b'RESET'
 
         # test the "OPTIONS" custom action
         r = app.request('/things', method='OPTIONS')
         assert r.status_int == 200
-        assert r.body == b_('OPTIONS')
+        assert r.body == b'OPTIONS'
 
         # test the "OPTIONS" custom action with the _method parameter
         r = app.post('/things', {'_method': 'OPTIONS'})
         assert r.status_int == 200
-        assert r.body == b_('OPTIONS')
+        assert r.body == b'OPTIONS'
 
         # test the "other" custom action
         with warnings.catch_warnings():
@@ -228,7 +229,7 @@ class RootController(object):
             warnings.simplefilter("ignore")
             r = app.request('/things/others/', method='MISC')
             assert r.status_int == 200
-            assert r.body == b_('OTHERS')
+            assert r.body == b'OTHERS'
 
         # test the "others" custom action missing trailing slash
         with warnings.catch_warnings():
@@ -239,7 +240,7 @@ class RootController(object):
         # test the "others" custom action with the _method parameter
         r = app.get('/things/others/?_method=MISC')
         assert r.status_int == 200
-        assert r.body == b_('OTHERS')
+        assert r.body == b'OTHERS'
 
         # test an invalid custom action
         r = app.get('/things?_method=BAD', status=405)
@@ -248,27 +249,27 @@ class RootController(object):
         # test custom "GET" request "count"
         r = app.get('/things/count')
         assert r.status_int == 200
-        assert r.body == b_('3')
+        assert r.body == b'3'
 
         # test custom "GET" request "length"
         r = app.get('/things/1/length')
         assert r.status_int == 200
-        assert r.body == b_(str(len('one')))
+        assert r.body == b'3'
 
         # test custom "GET" request through subcontroller
         r = app.get('/things/others/echo?value=test')
         assert r.status_int == 200
-        assert r.body == b_('test')
+        assert r.body == b'test'
 
         # test custom "POST" request "length"
         r = app.post('/things/1/length', {'value': 'test'})
         assert r.status_int == 200
-        assert r.body == b_(str(len('onetest')))
+        assert r.body == b'7'
 
         # test custom "POST" request through subcontroller
         r = app.post('/things/others/echo', {'value': 'test'})
         assert r.status_int == 200
-        assert r.body == b_('test')
+        assert r.body == b'test'
 
     def test_getall_with_trailing_slash(self):
 
@@ -289,7 +290,9 @@ class RootController(object):
         # test get_all
         r = app.get('/things/')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(items=ThingsController.data)))
+        assert r.body == dumps(
+            dict(items=ThingsController.data)
+        ).encode('utf-8')
 
     def test_405_with_lookup(self):
 
@@ -321,7 +324,7 @@ class RootController(object):
 
         r = app.get('/things/foo')
         assert r.status_int == 200
-        assert r.body == b_('ID: foo')
+        assert r.body == b'ID: foo'
 
     def test_getall_with_lookup(self):
 
@@ -356,11 +359,13 @@ class RootController(object):
         for path in ('/things', '/things/'):
             r = app.get(path)
             assert r.status_int == 200
-            assert r.body == b_(dumps(dict(items=ThingsController.data)))
+            assert r.body == dumps(
+                dict(items=ThingsController.data)
+            ).encode('utf-8')
 
         r = app.get('/things/foo')
         assert r.status_int == 200
-        assert r.body == b_('ID: foo')
+        assert r.body == b'ID: foo'
 
     def test_simple_nested_rest(self):
 
@@ -394,19 +399,19 @@ class RootController(object):
 
         r = app.post('/foo')
         assert r.status_int == 200
-        assert r.body == b_("FOO-POST")
+        assert r.body == b"FOO-POST"
 
         r = app.delete('/foo/1')
         assert r.status_int == 200
-        assert r.body == b_("FOO-1")
+        assert r.body == b"FOO-1"
 
         r = app.post('/foo/bar')
         assert r.status_int == 200
-        assert r.body == b_("BAR-POST")
+        assert r.body == b"BAR-POST"
 
         r = app.delete('/foo/bar/2')
         assert r.status_int == 200
-        assert r.body == b_("BAR-2")
+        assert r.body == b"BAR-2"
 
     def test_complicated_nested_rest(self):
 
@@ -504,75 +509,79 @@ class RootController(object):
         # test get_all
         r = app.get('/foos')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(items=FoosController.data)))
+        assert r.body == dumps(
+            dict(items=FoosController.data)
+        ).encode('utf-8')
 
         # test nested get_all
         r = app.get('/foos/1/bars')
         assert r.status_int == 200
-        assert r.body == b_(dumps(dict(items=BarsController.data[1])))
+        assert r.body == dumps(
+            dict(items=BarsController.data[1])
+        ).encode('utf-8')
 
         # test get_one
         for i, value in enumerate(FoosController.data):
             r = app.get('/foos/%d' % i)
             assert r.status_int == 200
-            assert r.body == b_(value)
+            assert r.body == value.encode('utf-8')
 
         # test nested get_one
         for i, value in enumerate(FoosController.data):
             for j, value in enumerate(BarsController.data[i]):
                 r = app.get('/foos/%s/bars/%s' % (i, j))
                 assert r.status_int == 200
-                assert r.body == b_(value)
+                assert r.body == value.encode('utf-8')
 
         # test post
         r = app.post('/foos', {'value': 'two'})
         assert r.status_int == 302
-        assert r.body == b_('CREATED')
+        assert r.body == b'CREATED'
 
         # make sure it works
         r = app.get('/foos/2')
         assert r.status_int == 200
-        assert r.body == b_('two')
+        assert r.body == b'two'
 
         # test nested post
         r = app.post('/foos/2/bars', {'value': 'two-zero'})
         assert r.status_int == 302
-        assert r.body == b_('CREATED FOR 2')
+        assert r.body == b'CREATED FOR 2'
 
         # make sure it works
         r = app.get('/foos/2/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('two-zero')
+        assert r.body == b'two-zero'
 
         # test edit
         r = app.get('/foos/1/edit')
         assert r.status_int == 200
-        assert r.body == b_('EDIT one')
+        assert r.body == b'EDIT one'
 
         # test nested edit
         r = app.get('/foos/1/bars/1/edit')
         assert r.status_int == 200
-        assert r.body == b_('EDIT one-one')
+        assert r.body == b'EDIT one-one'
 
         # test put
         r = app.put('/foos/2', {'value': 'TWO'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/foos/2')
         assert r.status_int == 200
-        assert r.body == b_('TWO')
+        assert r.body == b'TWO'
 
         # test nested put
         r = app.put('/foos/2/bars/0', {'value': 'TWO-ZERO'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/foos/2/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('TWO-ZERO')
+        assert r.body == b'TWO-ZERO'
 
         # test put with _method parameter and GET
         r = app.get('/foos/2?_method=put', {'value': 'TWO!'}, status=405)
@@ -581,7 +590,7 @@ class RootController(object):
         # make sure it works
         r = app.get('/foos/2')
         assert r.status_int == 200
-        assert r.body == b_('TWO')
+        assert r.body == b'TWO'
 
         # test nested put with _method parameter and GET
         r = app.get(
@@ -593,42 +602,42 @@ class RootController(object):
         # make sure it works
         r = app.get('/foos/2/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('TWO-ZERO')
+        assert r.body == b'TWO-ZERO'
 
         # test put with _method parameter and POST
         r = app.post('/foos/2?_method=put', {'value': 'TWO!'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/foos/2')
         assert r.status_int == 200
-        assert r.body == b_('TWO!')
+        assert r.body == b'TWO!'
 
         # test nested put with _method parameter and POST
         r = app.post('/foos/2/bars/0?_method=put', {'value': 'TWO-ZERO!'})
         assert r.status_int == 200
-        assert r.body == b_('UPDATED')
+        assert r.body == b'UPDATED'
 
         # make sure it works
         r = app.get('/foos/2/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('TWO-ZERO!')
+        assert r.body == b'TWO-ZERO!'
 
         # test get delete
         r = app.get('/foos/2/delete')
         assert r.status_int == 200
-        assert r.body == b_('DELETE TWO!')
+        assert r.body == b'DELETE TWO!'
 
         # test nested get delete
         r = app.get('/foos/2/bars/0/delete')
         assert r.status_int == 200
-        assert r.body == b_('DELETE TWO-ZERO!')
+        assert r.body == b'DELETE TWO-ZERO!'
 
         # test nested delete
         r = app.delete('/foos/2/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/foos/2/bars')
@@ -638,7 +647,7 @@ class RootController(object):
         # test delete
         r = app.delete('/foos/2')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/foos')
@@ -666,7 +675,7 @@ class RootController(object):
         # test nested delete with _method parameter and POST
         r = app.post('/foos/1/bars/1?_method=DELETE')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/foos/1/bars')
@@ -676,7 +685,7 @@ class RootController(object):
         # test delete with _method parameter and POST
         r = app.post('/foos/1?_method=DELETE')
         assert r.status_int == 200
-        assert r.body == b_('DELETED')
+        assert r.body == b'DELETED'
 
         # make sure it works
         r = app.get('/foos')
@@ -715,19 +724,19 @@ class RootController(object):
 
         r = app.get('/foos/')
         assert r.status_int == 200
-        assert r.body == b_('1')
+        assert r.body == b'1'
 
         r = app.get('/foos/1/')
         assert r.status_int == 200
-        assert r.body == b_('2')
+        assert r.body == b'2'
 
         r = app.get('/foos/1/bars/')
         assert r.status_int == 200
-        assert r.body == b_('3')
+        assert r.body == b'3'
 
         r = app.get('/foos/1/bars/2/')
         assert r.status_int == 200
-        assert r.body == b_('4')
+        assert r.body == b'4'
 
         r = app.get('/foos/bars/', status=404)
         assert r.status_int == 404
@@ -771,19 +780,19 @@ class RootController(object):
 
         r = app.get('/foos/')
         assert r.status_int == 200
-        assert r.body == b_('1')
+        assert r.body == b'1'
 
         r = app.get('/foos/1/')
         assert r.status_int == 200
-        assert r.body == b_('2')
+        assert r.body == b'2'
 
         r = app.get('/foos/1/bars/')
         assert r.status_int == 200
-        assert r.body == b_('3')
+        assert r.body == b'3'
 
         r = app.get('/foos/1/bars/2/')
         assert r.status_int == 200
-        assert r.body == b_('4')
+        assert r.body == b'4'
 
         r = app.get('/foos/bars/')
         assert r.status_int == 302
@@ -886,12 +895,16 @@ class RootController(object):
         # test get_all
         r = app.get('/foos')
         self.assertEqual(r.status_int, 200)
-        self.assertEqual(r.body, b_(dumps(dict(items=FoosController.data))))
+        self.assertEqual(r.body, dumps(
+            dict(items=FoosController.data)
+        ).encode('utf-8'))
 
         # test nested get_all
         r = app.get('/foos/1/bars')
         self.assertEqual(r.status_int, 200)
-        self.assertEqual(r.body, b_(dumps(dict(items=BarsController.data[1]))))
+        self.assertEqual(r.body, dumps(
+            dict(items=BarsController.data[1])
+        ).encode('utf-8'))
 
         r = app.get('/foos/bars', expect_errors=True)
         self.assertEqual(r.status_int, 404)
@@ -927,35 +940,35 @@ def remove(self, id):
 
         r = app.get('/detail')
         assert r.status_int == 200
-        assert r.body == b_('DETAIL')
+        assert r.body == b'DETAIL'
 
         r = app.get('/detail/')
         assert r.status_int == 200
-        assert r.body == b_('DETAIL')
+        assert r.body == b'DETAIL'
 
         r = app.post('/create')
         assert r.status_int == 200
-        assert r.body == b_('CREATE')
+        assert r.body == b'CREATE'
 
         r = app.post('/create/')
         assert r.status_int == 200
-        assert r.body == b_('CREATE')
+        assert r.body == b'CREATE'
 
         r = app.put('/update/123')
         assert r.status_int == 200
-        assert r.body == b_('123')
+        assert r.body == b'123'
 
         r = app.put('/update/123/')
         assert r.status_int == 200
-        assert r.body == b_('123')
+        assert r.body == b'123'
 
         r = app.delete('/remove/456')
         assert r.status_int == 200
-        assert r.body == b_('456')
+        assert r.body == b'456'
 
         r = app.delete('/remove/456/')
         assert r.status_int == 200
-        assert r.body == b_('456')
+        assert r.body == b'456'
 
     def test_custom_delete(self):
 
@@ -998,7 +1011,7 @@ class RootController(object):
         # test custom delete without ID
         r = app.delete('/things/others/')
         assert r.status_int == 200
-        assert r.body == b_('DELETE')
+        assert r.body == b'DELETE'
 
         # test custom delete without ID with _method parameter and GET
         r = app.get('/things/others/?_method=delete', status=405)
@@ -1007,12 +1020,12 @@ class RootController(object):
         # test custom delete without ID with _method parameter and POST
         r = app.post('/things/others/', {'_method': 'delete'})
         assert r.status_int == 200
-        assert r.body == b_('DELETE')
+        assert r.body == b'DELETE'
 
         # test custom delete with ID
         r = app.delete('/things/others/reset/1')
         assert r.status_int == 200
-        assert r.body == b_('1')
+        assert r.body == b'1'
 
         # test custom delete with ID with _method parameter and GET
         r = app.get('/things/others/reset/1?_method=delete', status=405)
@@ -1021,7 +1034,7 @@ class RootController(object):
         # test custom delete with ID with _method parameter and POST
         r = app.post('/things/others/reset/1', {'_method': 'delete'})
         assert r.status_int == 200
-        assert r.body == b_('1')
+        assert r.body == b'1'
 
     def test_get_with_var_args(self):
 
@@ -1048,12 +1061,12 @@ class RootController(object):
         # test get request
         r = app.get('/things/one/two/three')
         assert r.status_int == 200
-        assert r.body == b_('one, two, three')
+        assert r.body == b'one, two, three'
 
         # test nested get request
         r = app.get('/things/one/two/three/others/')
         assert r.status_int == 200
-        assert r.body == b_('NESTED: one, two, three')
+        assert r.body == b'NESTED: one, two, three'
 
     def test_sub_nested_rest(self):
 
@@ -1094,7 +1107,7 @@ class RootController(object):
         # test sub-nested get_one
         r = app.get('/foos/0/bars/0/bazs/0')
         assert r.status_int == 200
-        assert r.body == b_('zero-zero-zero')
+        assert r.body == b'zero-zero-zero'
 
     def test_sub_nested_rest_with_overwrites(self):
 
@@ -1170,35 +1183,35 @@ class RootController(object):
 
         r = app.post('/foos')
         assert r.status_int == 200
-        assert r.body == b_('POST')
+        assert r.body == b'POST'
 
         r = app.put('/foos/0')
         assert r.status_int == 200
-        assert r.body == b_('PUT')
+        assert r.body == b'PUT'
 
         r = app.post('/foos/bars')
         assert r.status_int == 200
-        assert r.body == b_('POST-CHILD')
+        assert r.body == b'POST-CHILD'
 
         r = app.put('/foos/bars/0')
         assert r.status_int == 200
-        assert r.body == b_('PUT-CHILD')
+        assert r.body == b'PUT-CHILD'
 
         r = app.post('/foos/bars/bazs')
         assert r.status_int == 200
-        assert r.body == b_('POST-GRAND-CHILD')
+        assert r.body == b'POST-GRAND-CHILD'
 
         r = app.put('/foos/bars/bazs/0')
         assert r.status_int == 200
-        assert r.body == b_('PUT-GRAND-CHILD')
+        assert r.body == b'PUT-GRAND-CHILD'
 
         r = app.get('/foos/bars/bazs/final/')
         assert r.status_int == 200
-        assert r.body == b_('FINAL')
+        assert r.body == b'FINAL'
 
         r = app.get('/foos/bars/bazs/final/named')
         assert r.status_int == 200
-        assert r.body == b_('NAMED')
+        assert r.body == b'NAMED'
 
     def test_post_with_kwargs_only(self):
 
@@ -1217,7 +1230,7 @@ def post(self, **kw):
 
         r = app.get('/')
         assert r.status_int == 200
-        assert r.body == b_('INDEX')
+        assert r.body == b'INDEX'
 
         kwargs = {'foo': 'bar', 'spam': 'eggs'}
         r = app.post('/', kwargs)
@@ -1306,43 +1319,43 @@ class RootController(RestController):
 
         r = app.get('/foo')
         assert r.status_int == 200
-        assert r.body == b_('INDEX')
+        assert r.body == b'INDEX'
 
         r = app.post('/foo')
         assert r.status_int == 200
-        assert r.body == b_('POST')
+        assert r.body == b'POST'
 
         r = app.get('/foo/1')
         assert r.status_int == 200
-        assert r.body == b_('GET ONE')
+        assert r.body == b'GET ONE'
 
         r = app.post('/foo/1')
         assert r.status_int == 200
-        assert r.body == b_('POST-LOOKUP-1')
+        assert r.body == b'POST-LOOKUP-1'
 
         r = app.put('/foo/1')
         assert r.status_int == 200
-        assert r.body == b_('PUT-1')
+        assert r.body == b'PUT-1'
 
         r = app.delete('/foo/1')
         assert r.status_int == 200
-        assert r.body == b_('DELETE-1')
+        assert r.body == b'DELETE-1'
 
         r = app.put('/foo/1/2')
         assert r.status_int == 200
-        assert r.body == b_('PUT-LOOKUP-1-2')
+        assert r.body == b'PUT-LOOKUP-1-2'
 
         r = app.delete('/foo/1/2')
         assert r.status_int == 200
-        assert r.body == b_('DELETE-LOOKUP-1-2')
+        assert r.body == b'DELETE-LOOKUP-1-2'
 
         r = app.get('/foo/1/2')
         assert r.status_int == 200
-        assert r.body == b_('FINAL-2')
+        assert r.body == b'FINAL-2'
 
         r = app.post('/foo/1/2')
         assert r.status_int == 200
-        assert r.body == b_('POST-2')
+        assert r.body == b'POST-2'
 
     def test_nested_rest_with_default(self):
 
@@ -1359,28 +1372,7 @@ class RootController(RestController):
 
         r = app.get('/foo/missing')
         assert r.status_int == 200
-        assert r.body == b_("DEFAULT missing")
-
-    def test_rest_with_non_utf_8_body(self):
-        if PY3:
-            # webob+PY3 doesn't suffer from this bug; the POST parsing in PY3
-            # seems to more gracefully detect the bytestring
-            return
-
-        class FooController(RestController):
-
-            @expose()
-            def post(self):
-                return "POST"
-
-        class RootController(RestController):
-            foo = FooController()
-
-        app = TestApp(make_app(RootController()))
-
-        data = struct.pack('255h', *range(0, 255))
-        r = app.post('/foo/', data, expect_errors=True)
-        assert r.status_int == 400
+        assert r.body == b"DEFAULT missing"
 
     def test_dynamic_rest_lookup(self):
         class BarController(RestController):
@@ -1444,43 +1436,43 @@ class RootController(RestController):
 
         r = app.get('/foos')
         assert r.status_int == 200
-        assert r.body == b_('FOOS')
+        assert r.body == b'FOOS'
 
         r = app.post('/foos')
         assert r.status_int == 200
-        assert r.body == b_('POST_FOOS')
+        assert r.body == b'POST_FOOS'
 
         r = app.get('/foos/foo')
         assert r.status_int == 200
-        assert r.body == b_('FOO')
+        assert r.body == b'FOO'
 
         r = app.put('/foos/foo')
         assert r.status_int == 200
-        assert r.body == b_('PUT_FOO')
+        assert r.body == b'PUT_FOO'
 
         r = app.delete('/foos/foo')
         assert r.status_int == 200
-        assert r.body == b_('DELETE_FOO')
+        assert r.body == b'DELETE_FOO'
 
         r = app.get('/foos/foo/bars')
         assert r.status_int == 200
-        assert r.body == b_('BARS')
+        assert r.body == b'BARS'
 
         r = app.post('/foos/foo/bars')
         assert r.status_int == 200
-        assert r.body == b_('POST_BARS')
+        assert r.body == b'POST_BARS'
 
         r = app.get('/foos/foo/bars/bar')
         assert r.status_int == 200
-        assert r.body == b_('BAR')
+        assert r.body == b'BAR'
 
         r = app.put('/foos/foo/bars/bar')
         assert r.status_int == 200
-        assert r.body == b_('PUT_BAR')
+        assert r.body == b'PUT_BAR'
 
         r = app.delete('/foos/foo/bars/bar')
         assert r.status_int == 200
-        assert r.body == b_('DELETE_BAR')
+        assert r.body == b'DELETE_BAR'
 
     def test_method_not_allowed_get(self):
         class ThingsController(RestController):
@@ -1554,7 +1546,7 @@ def get(self):
     def test_rest_with_utf8_uri(self):
 
         class FooController(RestController):
-            key = chr(0x1F330) if PY3 else unichr(0x1F330)
+            key = chr(0x1F330)
             data = {key: 'Success!'}
 
             @expose()
@@ -1594,7 +1586,6 @@ class RootController(RestController):
         assert r.status_int == 200
         assert r.body == b'Hello, World!'
 
-    @unittest.skipIf(not PY3, "test is Python3 specific")
     def test_rest_with_utf8_endpoint(self):
         class ChildController(object):
             @expose()
diff --git a/pecan/tests/test_scaffolds.py b/pecan/tests/test_scaffolds.py
index ef8f1f1..f24d435 100644
--- a/pecan/tests/test_scaffolds.py
+++ b/pecan/tests/test_scaffolds.py
@@ -3,8 +3,7 @@
 import sys
 import tempfile
 import unittest
-
-from six.moves import cStringIO as StringIO
+from io import StringIO
 
 from pecan.tests import PecanTestCase
 
diff --git a/pecan/tests/test_secure.py b/pecan/tests/test_secure.py
index 5286985..3257142 100644
--- a/pecan/tests/test_secure.py
+++ b/pecan/tests/test_secure.py
@@ -1,7 +1,6 @@
 import sys
 import unittest
 
-from six import b as b_
 from webtest import TestApp
 
 from pecan import expose, make_app
@@ -56,11 +55,11 @@ def unlocked(self):
         ))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         response = app.get('/unlocked')
         assert response.status_int == 200
-        assert response.body == b_('Sure thing')
+        assert response.body == b'Sure thing'
 
         response = app.get('/locked', expect_errors=True)
         assert response.status_int == 401
@@ -70,7 +69,7 @@ def unlocked(self):
 
         response = app.get('/secret/allowed')
         assert response.status_int == 200
-        assert response.body == b_('Allowed!')
+        assert response.body == b'Allowed!'
 
     def test_unlocked_attribute(self):
         class AuthorizedSubController(object):
@@ -118,11 +117,11 @@ def unlocked(self):
         ))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello, World!')
+        assert response.body == b'Hello, World!'
 
         response = app.get('/unlocked')
         assert response.status_int == 200
-        assert response.body == b_('Sure thing')
+        assert response.body == b'Sure thing'
 
         response = app.get('/locked', expect_errors=True)
         assert response.status_int == 401
@@ -132,15 +131,15 @@ def unlocked(self):
 
         response = app.get('/secret/allowed')
         assert response.status_int == 200
-        assert response.body == b_('Allowed!')
+        assert response.body == b'Allowed!'
 
         response = app.get('/secret/authorized/')
         assert response.status_int == 200
-        assert response.body == b_('Index')
+        assert response.body == b'Index'
 
         response = app.get('/secret/authorized/allowed')
         assert response.status_int == 200
-        assert response.body == b_('Allowed!')
+        assert response.body == b'Allowed!'
 
     def test_secure_attribute(self):
         authorized = False
@@ -160,7 +159,7 @@ def index(self):
         app = TestApp(make_app(RootController()))
         response = app.get('/')
         assert response.status_int == 200
-        assert response.body == b_('Hello from root!')
+        assert response.body == b'Hello from root!'
 
         response = app.get('/sub/', expect_errors=True)
         assert response.status_int == 401
@@ -168,7 +167,7 @@ def index(self):
         authorized = True
         response = app.get('/sub/')
         assert response.status_int == 200
-        assert response.body == b_('Hello from sub!')
+        assert response.body == b'Hello from sub!'
 
     def test_secured_generic_controller(self):
         authorized = False
@@ -413,7 +412,7 @@ def tearDown(self):
     def test_sub_of_both_not_secret(self):
         response = self.app.get('/notsecret/hi/')
         assert response.status_int == 200
-        assert response.body == b_('Index hi')
+        assert response.body == b'Index hi'
 
     def test_protected_lookup(self):
         response = self.app.get('/secret/hi/', expect_errors=True)
@@ -422,7 +421,7 @@ def test_protected_lookup(self):
         self.secret_cls.authorized = True
         response = self.app.get('/secret/hi/')
         assert response.status_int == 200
-        assert response.body == b_('Index hi')
+        assert response.body == b'Index hi'
         assert 'secretcontroller' in self.permissions_checked
 
     def test_secured_notfound_lookup(self):
@@ -449,7 +448,7 @@ def test_layered_protection(self):
         self.deepsecret_cls.authorized = True
         response = self.app.get('/secret/hi/deepsecret/')
         assert response.status_int == 200
-        assert response.body == b_('Deep Secret')
+        assert response.body == b'Deep Secret'
         assert 'secretcontroller' in self.permissions_checked
         assert 'deepsecret' in self.permissions_checked
 
@@ -458,14 +457,14 @@ def test_cyclical_protection(self):
         self.deepsecret_cls.authorized = True
         response = self.app.get('/secret/1/deepsecret/2/deepsecret/')
         assert response.status_int == 200
-        assert response.body == b_('Deep Secret')
+        assert response.body == b'Deep Secret'
         assert 'secretcontroller' in self.permissions_checked
         assert 'deepsecret' in self.permissions_checked
 
     def test_unlocked_lookup(self):
         response = self.app.get('/notsecret/1/deepsecret/2/')
         assert response.status_int == 200
-        assert response.body == b_('Index 2')
+        assert response.body == b'Index 2'
         assert 'deepsecret' not in self.permissions_checked
 
         response = self.app.get(
@@ -493,7 +492,7 @@ def test_independent_check_success(self):
         self.secret_cls.independent_authorization = True
         response = self.app.get('/secret/independent')
         assert response.status_int == 200
-        assert response.body == b_('Independent Security')
+        assert response.body == b'Independent Security'
         assert len(self.permissions_checked) == 1
         assert 'independent' in self.permissions_checked
 
@@ -508,7 +507,7 @@ def test_wrapped_attribute_success(self):
         self.secret_cls.independent_authorization = True
         response = self.app.get('/secret/wrapped/')
         assert response.status_int == 200
-        assert response.body == b_('Index wrapped')
+        assert response.body == b'Index wrapped'
         assert len(self.permissions_checked) == 1
         assert 'independent' in self.permissions_checked
 
@@ -517,7 +516,7 @@ def test_lookup_to_wrapped_attribute_on_self(self):
         self.secret_cls.independent_authorization = True
         response = self.app.get('/secret/lookup_wrapped/')
         assert response.status_int == 200
-        assert response.body == b_('Index wrapped')
+        assert response.body == b'Index wrapped'
         assert len(self.permissions_checked) == 2
         assert 'independent' in self.permissions_checked
         assert 'secretcontroller' in self.permissions_checked
@@ -525,7 +524,7 @@ def test_lookup_to_wrapped_attribute_on_self(self):
     def test_unlocked_attribute_in_insecure(self):
         response = self.app.get('/notsecret/unlocked/')
         assert response.status_int == 200
-        assert response.body == b_('Index unlocked')
+        assert response.body == b'Index unlocked'
 
 
 class SecureControllerSharedPermissionsRegression(PecanTestCase):
diff --git a/pecan/tests/test_templating.py b/pecan/tests/test_templating.py
index 5fffb0c..07d199e 100644
--- a/pecan/tests/test_templating.py
+++ b/pecan/tests/test_templating.py
@@ -1,7 +1,5 @@
 import tempfile
 
-from six import b as b_
-
 from pecan.templating import RendererFactory, format_line_context
 from pecan.tests import PecanTestCase
 
@@ -44,7 +42,7 @@ def tearDown(self):
 
     def test_format_line_context(self):
         for i in range(11):
-            self.f.write(b_('Testing Line %d\n' % i))
+            self.f.write(b'Testing Line %d\n' % i)
         self.f.flush()
 
         assert format_line_context(self.f.name, 0).count('Testing Line') == 10
diff --git a/pecan/util.py b/pecan/util.py
index cb76cef..731be42 100644
--- a/pecan/util.py
+++ b/pecan/util.py
@@ -1,7 +1,3 @@
-import sys
-
-import six
-
 from pecan.compat import getargspec as _getargspec
 
 
@@ -22,7 +18,7 @@ def getargspec(method):
     if hasattr(method, '__func__'):
         method = method.__func__
 
-    func_closure = six.get_function_closure(method)
+    func_closure = method.__closure__
 
     # NOTE(sileht): if the closure is None we cannot look deeper,
     # so return actual argspec, this occurs when the method
@@ -37,7 +33,7 @@ def getargspec(method):
     # (has a __code__ object, and 'self' is the first argument)
     func_closure = filter(
         lambda c: (
-            six.callable(c.cell_contents) and
+            callable(c.cell_contents) and
             hasattr(c.cell_contents, '__code__')
         ),
         func_closure
diff --git a/requirements.txt b/requirements.txt
index 0d61d64..94c6136 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,4 @@
 WebOb>=1.8
 Mako>=0.4.0
 setuptools
-six
 logutils>=0.3

openSUSE Build Service is sponsored by