diff --git a/pecan-1.4.2.tar.gz b/pecan-1.4.2.tar.gz deleted file mode 100644 index dd589e2..0000000 --- a/pecan-1.4.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:49b255e701c3f1461605f5b0e8f54f0c21922d7845d414c24dd6409fe695d550 -size 124900 diff --git a/pecan-1.5.1.tar.gz b/pecan-1.5.1.tar.gz new file mode 100644 index 0000000..c225212 --- /dev/null +++ b/pecan-1.5.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6063272d5f860773fbb4b4b2ae1b09da8c954062ef871150c06cfdb2391d9355 +size 124161 diff --git a/pecan-no-kajiki.patch b/pecan-no-kajiki.patch deleted file mode 100644 index 281f29f..0000000 --- a/pecan-no-kajiki.patch +++ /dev/null @@ -1,22 +0,0 @@ -Index: pecan-1.3.2/setup.py -=================================================================== ---- pecan-1.3.2.orig/setup.py -+++ pecan-1.3.2/setup.py -@@ -35,15 +35,8 @@ tests_require = requirements + [ - - tests_require = requirements + test_requirements - --if sys.version_info < (3, 0): -- # These don't support Python3 yet - don't run their tests -- if platform.python_implementation() != 'PyPy': -- # Kajiki is not pypy-compatible -- tests_require += ['Kajiki'] -- tests_require += ['Genshi'] --else: -- # Genshi added Python3 support in 0.7 -- tests_require += ['Genshi>=0.7'] -+# Genshi added Python3 support in 0.7 -+tests_require += ['Genshi>=0.7'] - - # - # call setup diff --git a/python-pecan.changes b/python-pecan.changes index 5caa71f..2e8acda 100644 --- a/python-pecan.changes +++ b/python-pecan.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Mon Sep 9 07:08:18 UTC 2024 - Steve Kowalik + +- Update to 1.5.1: + * addressed an installation bug caused by a duplicate entry script (#142) + * pecan no longer has a dependency on six (#144) + * pecan now supports SQLAlchemy 2.0 (#143) + * pecan no longer supports SQLAlchemy 1.3 +- Drop patches pecan-no-kajiki.patch, sqlalchemy2.patch: + * No longer required. +- Switch to pyproject macros. +- No more greedy globs in %files. + ------------------------------------------------------------------- Mon May 22 11:27:36 UTC 2023 - Markéta Machová diff --git a/python-pecan.spec b/python-pecan.spec index 9097cf3..9c2c642 100644 --- a/python-pecan.spec +++ b/python-pecan.spec @@ -1,7 +1,7 @@ # # spec file for package python-pecan # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,18 +22,13 @@ %bcond_with libalternatives %endif -%{?!python_module:%define python_module() python-%{**} python3-%{**}} -%define skip_python2 1 Name: python-pecan -Version: 1.4.2 +Version: 1.5.1 Release: 0 Summary: A WSGI object-dispatching web framework License: BSD-3-Clause URL: https://github.com/pecan/pecan Source: https://files.pythonhosted.org/packages/source/p/pecan/pecan-%{version}.tar.gz -Patch0: pecan-no-kajiki.patch -#PATCH-FIX-UPSTREAM https://github.com/pecan/pecan/pull/145 remove six as a requirement, add support for SQLAlchemy 2.0, drop support for SQLAlchemy 1.3 -Patch1: sqlalchemy2.patch BuildRequires: %{python_module Genshi >= 0.7} BuildRequires: %{python_module Jinja2} BuildRequires: %{python_module Mako >= 0.4.0} @@ -42,8 +37,10 @@ BuildRequires: %{python_module WebOb >= 1.8} BuildRequires: %{python_module WebTest >= 1.3.1} BuildRequires: %{python_module gunicorn} BuildRequires: %{python_module logutils} +BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module virtualenv} +BuildRequires: %{python_module wheel} BuildRequires: uwsgi # we need sqlite module BuildRequires: %{pythons} @@ -60,7 +57,7 @@ Requires: alts BuildRequires: alts %else Requires(post): update-alternatives -Requires(postun):update-alternatives +Requires(postun): update-alternatives %endif BuildArch: noarch %if 0%{?suse_version} @@ -79,10 +76,10 @@ sed -ie "/^uwsgi$/d" test-requirements.txt sed -ie "/^pep8$/d" test-requirements.txt %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %python_clone -a %{buildroot}%{_bindir}/pecan %python_clone -a %{buildroot}%{_bindir}/gunicorn_pecan @@ -108,6 +105,7 @@ sed -ie "/^pep8$/d" test-requirements.txt %doc README.rst %python_alternative %{_bindir}/pecan %python_alternative %{_bindir}/gunicorn_pecan -%{python_sitelib}/* +%{python_sitelib}/pecan +%{python_sitelib}/pecan-%{version}.dist-info %changelog diff --git a/sqlalchemy2.patch b/sqlalchemy2.patch deleted file mode 100644 index c94d726..0000000 --- a/sqlalchemy2.patch +++ /dev/null @@ -1,4429 +0,0 @@ -From 3c4e8488b6bf0db895ca3edbe51016e5026b92a7 Mon Sep 17 00:00:00 2001 -From: Ryan Petrello -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''' -
- To disable this interface, set - ]*>)'), re.I) -+ body_re = re.compile(b'(]*>)', 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_("

Hello, Jonathan!

") in r.body -+ assert b"

Hello, Jonathan!

" in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 -- assert b_("

Hello, World!

") in r.body -+ assert b"

Hello, World!

" 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_("

Hello, Jonathan!

") in r.body -+ assert b"

Hello, Jonathan!

" in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 -- assert b_("

Hello, World!

") in r.body -+ assert b"

Hello, World!

" 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_("

Hello, Jonathan!

") in r.body -+ assert b"

Hello, Jonathan!

" in r.body - - error_msg = None - try: -@@ -1910,11 +1901,11 @@ def badtemplate(self): - ) - r = app.get('/') - assert r.status_int == 200 -- assert b_("

Hello, Jonathan!

") in r.body -+ assert b"

Hello, Jonathan!

" in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 -- assert b_("

Hello, World!

") in r.body -+ assert b"

Hello, World!

" 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_("

Hello, eoJ!

") in r.body -+ assert b"

Hello, eoJ!

" in r.body - - r = app.get('/index.html?name=Tim') - assert r.status_int == 200 -- assert b_("

Hello, miT!

") in r.body -+ assert b"

Hello, miT!

" 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_("

Hello, Jonathan!

") in r.body -+ assert b"

Hello, Jonathan!

" 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 -