From e6c2d2eb7a9608658823fc2854104c2a61284942 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 22 Sep 2011 17:13:45 -0400 Subject: anger release commit --- pyramid/asset.py | 4 +- pyramid/authentication.py | 6 +- pyramid/chameleon_text.py | 4 +- pyramid/chameleon_zpt.py | 4 +- pyramid/compat.py | 175 +++++++++++++++++++++++++++++++ pyramid/config/__init__.py | 14 ++- pyramid/config/tweens.py | 2 +- pyramid/config/util.py | 7 +- pyramid/config/views.py | 5 +- pyramid/exceptions.py | 8 +- pyramid/httpexceptions.py | 6 +- pyramid/interfaces.py | 2 +- pyramid/registry.py | 7 +- pyramid/renderers.py | 6 +- pyramid/resource.py | 2 +- pyramid/session.py | 11 +- pyramid/static.py | 5 +- pyramid/testing.py | 9 +- pyramid/tests/test_authentication.py | 7 +- pyramid/tests/test_config/test_assets.py | 2 +- pyramid/tests/test_config/test_i18n.py | 2 +- pyramid/tests/test_config/test_init.py | 2 +- pyramid/tests/test_config/test_views.py | 13 ++- pyramid/tests/test_docs.py | 3 +- pyramid/tests/test_httpexceptions.py | 7 +- pyramid/tests/test_integration.py | 9 +- pyramid/tests/test_mako_templating.py | 37 ++++--- pyramid/tests/test_paster.py | 2 +- pyramid/tests/test_request.py | 8 +- pyramid/tests/test_router.py | 4 +- pyramid/tests/test_testing.py | 6 +- pyramid/tests/test_traversal.py | 61 ++++++----- pyramid/tests/test_url.py | 14 +-- pyramid/tests/test_urldispatch.py | 21 ++-- pyramid/tests/test_util.py | 4 +- pyramid/traversal.py | 9 +- pyramid/tweens.py | 4 +- pyramid/urldispatch.py | 10 +- pyramid/util.py | 7 +- pyramid/view.py | 3 +- setup.py | 36 ++++--- 41 files changed, 408 insertions(+), 140 deletions(-) diff --git a/pyramid/asset.py b/pyramid/asset.py index 730969a4a..4bf0d7bf4 100644 --- a/pyramid/asset.py +++ b/pyramid/asset.py @@ -1,11 +1,13 @@ import os import pkg_resources +from pyramid.compat import string_types + from pyramid.path import package_path from pyramid.path import package_name def resolve_asset_spec(spec, pname='__main__'): - if pname and not isinstance(pname, basestring): + if pname and not isinstance(pname, string_types): pname = pname.__name__ # as package if os.path.isabs(spec): return None, spec diff --git a/pyramid/authentication.py b/pyramid/authentication.py index e2014b9a1..d3d5a1ecd 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -3,11 +3,14 @@ from codecs import utf_8_encode from hashlib import md5 import datetime import re +import sys import time as time_mod import urllib from zope.interface import implements +from pyramid.compat import long + from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IDebugLogger @@ -469,7 +472,8 @@ def parse_ticket(secret, ticket, ip): digest = ticket[:32] try: timestamp = int(ticket[32:40], 16) - except ValueError, e: + except ValueError: + e = sys.exc_info()[1] raise BadTicket('Timestamp is not a hex integer: %s' % e) try: userid, data = ticket[40:].split('!', 1) diff --git a/pyramid/chameleon_text.py b/pyramid/chameleon_text.py index b687ecda9..bb6531976 100644 --- a/pyramid/chameleon_text.py +++ b/pyramid/chameleon_text.py @@ -3,6 +3,8 @@ import sys from zope.deprecation import deprecated from zope.interface import implements +from pyramid.compat import reraise + try: from chameleon.zpt.template import PageTextTemplateFile # prevent pyflakes complaining about a redefinition below @@ -12,7 +14,7 @@ except ImportError: # pragma: no cover # Chameleon doesn't work on non-CPython platforms class PageTextTemplateFile(object): def __init__(self, *arg, **kw): - raise ImportError, exc, tb + reraise(ImportError, exc, tb) from pyramid.interfaces import ITemplateRenderer diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py index cfa37a65f..495835c3d 100644 --- a/pyramid/chameleon_zpt.py +++ b/pyramid/chameleon_zpt.py @@ -3,6 +3,8 @@ import sys from zope.deprecation import deprecated from zope.interface import implements +from pyramid.compat import reraise + try: from chameleon.zpt.template import PageTemplateFile PageTemplateFile # prevent pyflakes complaining about a redefinition below @@ -11,7 +13,7 @@ except ImportError: # pragma: no cover # Chameleon doesn't work on non-CPython platforms class PageTemplateFile(object): def __init__(self, *arg, **kw): - raise ImportError, exc, tb + reraise(ImportError, exc, tb) from pyramid.interfaces import ITemplateRenderer diff --git a/pyramid/compat.py b/pyramid/compat.py index 7d723715e..5ef3c4e6d 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -1,3 +1,11 @@ +import sys +import types + +try: + import cPickle as pickle +except ImportError: # pragma: no cover + import pickle + try: import json except ImportError: # pragma: no cover @@ -6,3 +14,170 @@ except ImportError: # pragma: no cover except NotImplementedError: from django.utils import simplejson as json # GAE +# True if we are running on Python 3. +PY3 = sys.version_info[0] == 3 + +if PY3: # pragma: no cover + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + long = int + def ords_(b): + return b +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + def ords_(s): + return [ord(x) for x in s] + +def text_(s, encoding='latin-1', errors='strict'): + if isinstance(s, binary_type): + return s.decode(encoding, errors) + return s + +def bytes_(s, encoding='latin-1', errors='strict'): + if isinstance(s, text_type): + return s.encode(encoding, errors) + return s + +if PY3: # pragma: no cover + def native_(s, encoding='latin-1', errors='strict'): + if isinstance(s, text_type): + return s + return str(s, encoding, errors) +else: + def native_(s, encoding='latin-1', errors='strict'): + if isinstance(s, text_type): + return s.encode(encoding, errors) + return str(s) + +if PY3: # pragma: no cover + fsenc = sys.getfilesystemencoding() + def text_to_wsgi(u): + # On Python 3, convert an environment variable to a WSGI + # "bytes-as-unicode" string + return u.encode(fsenc, 'surrogateescape').decode('latin-1') +else: + def text_to_wsgi(u): + return u.encode('latin-1', 'surrogateescape') + +try: + from queue import Queue, Empty +except ImportError: + from Queue import Queue, Empty + +try: # pragma: no cover + from urllib import parse + urlparse = parse + from urllib.parse import quote as url_quote + from urllib.parse import unquote as url_unquote + from urllib.parse import urlencode as url_encode + from urllib.request import urlopen as url_open +except ImportError: + import urlparse + from urllib import quote as url_quote + from urllib import unquote as url_unquote + from urllib import urlencode as url_encode + from urllib2 import urlopen as url_open + +if PY3: # pragma: no cover + import builtins + exec_ = getattr(builtins, "exec") + + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + + print_ = getattr(builtins, "print") + del builtins + +else: # pragma: no cover + def exec_(code, globs=None, locs=None): + """Execute code in a namespace.""" + if globs is None: + frame = sys._getframe(1) + globs = frame.f_globals + if locs is None: + locs = frame.f_locals + del frame + elif locs is None: + locs = globs + exec("""exec code in globs, locs""") + + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + + def print_(*args, **kwargs): + """The new-style print function.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + def write(data): + if not isinstance(data, basestring): + data = str(data) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) + +if PY3: # pragma: no cover + def iteritems_(d): + return d.items() + def itervalues_(d): + return d.values() +else: + def iteritems_(d): + return d.iteritems() + def itervalues_(d): + return d.itervalues() + + +if PY3: + def map_(*arg): + return list(map(*arg)) +else: + map_ = map + diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index a2014b1b5..527745ecf 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -13,6 +13,9 @@ from pyramid.interfaces import IExceptionResponse from pyramid.asset import resolve_asset_spec from pyramid.authorization import ACLAuthorizationPolicy +from pyramid.compat import text_ +from pyramid.compat import reraise +from pyramid.compat import string_types from pyramid.events import ApplicationCreated from pyramid.exceptions import ConfigurationConflictError from pyramid.exceptions import ConfigurationError @@ -42,6 +45,8 @@ from pyramid.config.util import action_method from pyramid.config.views import ViewsConfiguratorMixin from pyramid.config.zca import ZCAConfiguratorMixin +empty = text_('') + ConfigurationError = ConfigurationError # pyflakes class Configurator( @@ -283,7 +288,7 @@ class Configurator( self._set_settings(settings) self._register_response_adapters() - if isinstance(debug_logger, basestring): + if isinstance(debug_logger, string_types): debug_logger = logging.getLogger(debug_logger) if debug_logger is None: @@ -401,7 +406,7 @@ class Configurator( if not hasattr(_registry, 'registerSelfAdapter'): def registerSelfAdapter(required=None, provided=None, - name=u'', info=u'', event=True): + name=empty, info=empty, event=True): return _registry.registerAdapter(lambda x: x, required=required, provided=provided, name=name, @@ -709,7 +714,7 @@ class Configurator( when generating an absolute asset specification. If the provided ``relative_spec`` argument is already absolute, or if the ``relative_spec`` is not a string, it is simply returned.""" - if not isinstance(relative_spec, basestring): + if not isinstance(relative_spec, string_types): return relative_spec return self._make_spec(relative_spec) @@ -907,7 +912,8 @@ class ActionState(object): except: t, v, tb = sys.exc_info() try: - raise ConfigurationExecutionError(t, v, info), None, tb + reraise( + ConfigurationExecutionError(t, v, info), None, tb) finally: del t, v, tb finally: diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py index 2704b89c1..6feb1bfe6 100644 --- a/pyramid/config/tweens.py +++ b/pyramid/config/tweens.py @@ -197,7 +197,7 @@ class Tweens(object): order.append((a, b)) def add_node(node): - if not graph.has_key(node): + if not node in graph: roots.append(node) graph[node] = [0] # 0 = number of arcs coming into this node diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 7ce9adc4f..f549b1977 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -1,4 +1,5 @@ import re +import sys import traceback from pyramid.exceptions import ConfigurationError @@ -111,7 +112,8 @@ def make_predicates(xhr=None, request_method=None, path_info=None, if path_info is not None: try: path_info_val = re.compile(path_info) - except re.error, why: + except re.error: + why = sys.exc_info()[1] raise ConfigurationError(why[0]) def path_info_predicate(context, request): return path_info_val.match(request.path_info) is not None @@ -145,7 +147,8 @@ def make_predicates(xhr=None, request_method=None, path_info=None, header_name, header_val = header.split(':', 1) try: header_val = re.compile(header_val) - except re.error, why: + except re.error: + why = sys.exc_info()[1] raise ConfigurationError(why[0]) if header_val is None: text = "header %s" % header_name diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 703e3cca5..f1370a4b9 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1,6 +1,4 @@ import inspect -from urlparse import urljoin -from urlparse import urlparse from zope.interface import Interface from zope.interface import classProvides @@ -28,6 +26,7 @@ from pyramid.interfaces import IViewMapperFactory from pyramid.interfaces import PHASE1_CONFIG from pyramid import renderers +from pyramid.compat import urlparse from pyramid.exceptions import ConfigurationError from pyramid.exceptions import PredicateMismatch from pyramid.httpexceptions import HTTPForbidden @@ -43,6 +42,8 @@ from pyramid.config.util import action_method from pyramid.config.util import as_sorted_tuple from pyramid.config.util import make_predicates +urljoin = urlparse.urljoin + def wraps_view(wrapper): def inner(self, view): wrapper_view = wrapper(self, view) diff --git a/pyramid/exceptions.py b/pyramid/exceptions.py index cafdb93f0..cd234adca 100644 --- a/pyramid/exceptions.py +++ b/pyramid/exceptions.py @@ -4,6 +4,8 @@ from pyramid.httpexceptions import HTTPForbidden NotFound = HTTPNotFound # bw compat Forbidden = HTTPForbidden # bw compat +CR = '\n' + class PredicateMismatch(HTTPNotFound): """ Internal exception (not an API) raised by multiviews when no @@ -42,10 +44,10 @@ class ConfigurationConflictError(ConfigurationError): for discriminator, infos in items: r.append(" For: %s" % (discriminator, )) for info in infos: - for line in unicode(info).rstrip().split(u'\n'): - r.append(u" "+line) + for line in unicode(info).rstrip().split(CR): + r.append(" "+line) - return "\n".join(r) + return CR.join(r) class ConfigurationExecutionError(ConfigurationError): diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py index 0887b0eec..7cebfdc48 100644 --- a/pyramid/httpexceptions.py +++ b/pyramid/httpexceptions.py @@ -122,7 +122,6 @@ field. Reflecting this, these subclasses have one additional keyword argument: ``location``, which indicates the location to which to redirect. """ -import types from string import Template from zope.interface import implements @@ -131,6 +130,7 @@ from webob import html_escape as _html_escape from pyramid.interfaces import IExceptionResponse from pyramid.response import Response +from pyramid.compat import class_types def _no_escape(value): if value is None: @@ -1016,8 +1016,8 @@ def default_exceptionresponse_view(context, request): status_map={} code = None -for name, value in globals().items(): - if (isinstance(value, (type, types.ClassType)) and +for name, value in list(globals().items()): + if (isinstance(value, class_types) and issubclass(value, HTTPException) and not name.startswith('_')): code = getattr(value, 'code', None) diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index a0f27dd7a..a2b7990aa 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -42,7 +42,7 @@ class IApplicationCreated(Interface): versions before 1.0, this interface can also be imported as :class:`pyramid.interfaces.IWSGIApplicationCreatedEvent`. """ - app = Attribute(u"Created application") + app = Attribute("Created application") IWSGIApplicationCreatedEvent = IApplicationCreated # b /c diff --git a/pyramid/registry.py b/pyramid/registry.py index b88aabaff..ac706595e 100644 --- a/pyramid/registry.py +++ b/pyramid/registry.py @@ -1,7 +1,10 @@ from zope.interface.registry import Components +from pyramid.compat import text_ from pyramid.interfaces import ISettings +empty = text_('') + class Registry(Components, dict): """ A registry object is an :term:`application registry`. It is used by the framework itself to perform mappings of URLs to view callables, as @@ -34,8 +37,8 @@ class Registry(Components, dict): self.has_listeners = True return result - def registerSelfAdapter(self, required=None, provided=None, name=u'', - info=u'', event=True): + def registerSelfAdapter(self, required=None, provided=None, name=empty, + info=empty, event=True): # registerAdapter analogue which always returns the object itself # when required is matched return self.registerAdapter(lambda x: x, required=required, diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 2efe0f123..93e97de8f 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -15,6 +15,8 @@ from pyramid.interfaces import IRendererInfo from pyramid.asset import asset_spec_from_abspath from pyramid.compat import json +from pyramid.compat import string_types +from pyramid.compat import native_ from pyramid.decorator import reify from pyramid.events import BeforeRender from pyramid.path import caller_package @@ -145,8 +147,8 @@ def json_renderer_factory(info): def string_renderer_factory(info): def _render(value, system): - if not isinstance(value, basestring): - value = str(value) + if not isinstance(value, string_types): + value = native_(value, 'utf-8') request = system.get('request') if request is not None: response = request.response diff --git a/pyramid/resource.py b/pyramid/resource.py index 5e8f3c968..986c75e37 100644 --- a/pyramid/resource.py +++ b/pyramid/resource.py @@ -1,5 +1,5 @@ """ Backwards compatibility shim module (forever). """ -from asset import * # b/w compat +from pyramid.asset import * # b/w compat resolve_resource_spec = resolve_asset_spec resource_spec_from_abspath = asset_spec_from_abspath abspath_from_resource_spec = abspath_from_asset_spec diff --git a/pyramid/session.py b/pyramid/session.py index bfa80ff10..633620716 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -1,18 +1,14 @@ - -try: - import cPickle as pickle -except ImportError: # pragma: no cover - import pickle - from hashlib import sha1 import base64 import binascii import hmac +import sys import time import os from zope.interface import implements +from pyramid.compat import pickle from pyramid.interfaces import ISession def manage_accessed(wrapped): @@ -255,8 +251,9 @@ def signed_deserialize(serialized, secret, hmac=hmac): try: input_sig, pickled = (serialized[:40], base64.standard_b64decode(serialized[40:])) - except (binascii.Error, TypeError), e: + except (binascii.Error, TypeError): # Badly formed data can make base64 die + e = sys.exc_info()[1] raise ValueError('Badly formed base64 data: %s' % e) sig = hmac.new(secret, pickled, sha1).hexdigest() diff --git a/pyramid/static.py b/pyramid/static.py index eeb88bf5c..0ab4a0c79 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -15,12 +15,15 @@ from pkg_resources import resource_isdir from repoze.lru import lru_cache from pyramid.asset import resolve_asset_spec +from pyramid.compat import text_ from pyramid.httpexceptions import HTTPNotFound from pyramid.httpexceptions import HTTPMovedPermanently from pyramid.path import caller_package from pyramid.response import Response from pyramid.traversal import traversal_path +slash = text_('/') + def init_mimetypes(mimetypes): # this is a function so it can be unittested if hasattr(mimetypes, 'init'): @@ -192,6 +195,6 @@ def _secure_path(path_tuple): return None if any([_contains_slash(item) for item in path_tuple]): return None - encoded = u'/'.join(path_tuple) # will be unicode + encoded = slash.join(path_tuple) # will be unicode return encoded diff --git a/pyramid/testing.py b/pyramid/testing.py index 07f523868..862b9d6b1 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -28,6 +28,13 @@ from pyramid.request import DeprecatedRequestMethodsMixin from pyramid.request import CallbackMethodsMixin from pyramid.url import URLMethodsMixin +try: + import zope.component + zope.component + have_zca = True +except ImportError: + have_zca = False + _marker = object() def registerDummySecurityPolicy(userid=None, groupids=(), permissive=True): @@ -801,7 +808,7 @@ def setUp(registry=None, request=None, hook_zca=True, autocommit=True, # any existing renderer factory lookup system. config.add_renderer(name, renderer) config.commit() - hook_zca and config.hook_zca() + have_zca and hook_zca and config.hook_zca() config.begin(request=request) return config diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index ff96ae471..37c179caf 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -1,5 +1,6 @@ import unittest from pyramid import testing +from pyramid.compat import text_ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): def setUp(self): @@ -903,7 +904,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): helper = self._makeOne('secret') request = self._makeRequest() self.assertRaises(ValueError, helper.remember, request, 'other', - tokens=(u'foo',)) + tokens=(text_('foo'),)) def test_remember_invalid_token_format(self): helper = self._makeOne('secret') @@ -1092,8 +1093,8 @@ class Test_maybe_encode(unittest.TestCase): return maybe_encode(s, encoding) def test_unicode(self): - result = self._callFUT(u'abc') - self.assertEqual(result, 'abc') + result = self._callFUT(text_('abc')) + self.assertEqual(result, text_('abc')) class DummyContext: pass diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 322c854f5..a07753118 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -581,7 +581,7 @@ class DummyPackage: class DummyUnderOverride: def __call__(self, package, path, override_package, override_prefix, - _info=u''): + _info=''): self.package = package self.path = path self.override_package = override_package diff --git a/pyramid/tests/test_config/test_i18n.py b/pyramid/tests/test_config/test_i18n.py index 03b410445..25cb88cc3 100644 --- a/pyramid/tests/test_config/test_i18n.py +++ b/pyramid/tests/test_config/test_i18n.py @@ -92,7 +92,7 @@ class TestI18NConfiguratorMixin(unittest.TestCase): try: config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale') translate = config.registry.getUtility(IChameleonTranslate) - self.assertEqual(translate('Approve'), u'Approve') + self.assertEqual(translate('Approve'), 'Approve') finally: manager.pop() diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 1dccd00e1..750cdb94f 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -333,7 +333,7 @@ class ConfiguratorTests(unittest.TestCase): args, kw = reg.adapters[0] self.assertEqual(args[0]('abc'), 'abc') self.assertEqual(kw, - {'info': u'', 'provided': 'provided', + {'info': '', 'provided': 'provided', 'required': 'required', 'name': 'abc', 'event': True}) def test_setup_registry_calls_fix_registry(self): diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index be5143d45..84d53338e 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -1,4 +1,5 @@ import unittest +import sys from pyramid import testing from pyramid.tests.test_config import IDummy @@ -2530,7 +2531,8 @@ class TestViewDeriver(unittest.TestCase): request.url = 'url' try: result(None, request) - except HTTPForbidden, e: + except HTTPForbidden: + e = sys.exc_info()[1] self.assertEqual(e.message, 'Unauthorized: failed permission check') else: # pragma: no cover @@ -2552,7 +2554,8 @@ class TestViewDeriver(unittest.TestCase): request.url = 'url' try: result(None, request) - except HTTPForbidden, e: + except HTTPForbidden: + e = sys.exc_info()[1] self.assertEqual(e.message, 'Unauthorized: myview failed permission check') else: # pragma: no cover @@ -2570,7 +2573,8 @@ class TestViewDeriver(unittest.TestCase): request.method = 'POST' try: result(None, None) - except PredicateMismatch, e: + except PredicateMismatch: + e = sys.exc_info()[1] self.assertEqual(e.detail, 'predicate mismatch for view ') else: # pragma: no cover raise AssertionError @@ -2586,7 +2590,8 @@ class TestViewDeriver(unittest.TestCase): request.method = 'POST' try: result(None, None) - except PredicateMismatch, e: + except PredicateMismatch: + e = sys.exc_info()[1] self.assertEqual(e.detail, 'predicate mismatch for view myview') else: # pragma: no cover raise AssertionError diff --git a/pyramid/tests/test_docs.py b/pyramid/tests/test_docs.py index bf06c7ca6..eba95b210 100644 --- a/pyramid/tests/test_docs.py +++ b/pyramid/tests/test_docs.py @@ -1,4 +1,5 @@ import unittest +from pyramid.compat import print_ if 0: # no released version of manuel actually works with :lineno: @@ -31,5 +32,5 @@ if 0: if filename.endswith('.rst'): docs.append(os.path.join(root, filename)) - print path + print_(path) return manuel.testing.TestSuite(m, *docs) diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index 9c7b38e27..fe3a79593 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -1,4 +1,5 @@ import unittest +from pyramid.compat import text_ class Test_exception_response(unittest.TestCase): def _callFUT(self, *arg, **kw): @@ -48,9 +49,9 @@ class Test__no_escape(unittest.TestCase): def test_unicode(self): class DummyUnicodeObject(object): def __unicode__(self): - return u'42' + return text_('42') duo = DummyUnicodeObject() - self.assertEqual(self._callFUT(duo), u'42') + self.assertEqual(self._callFUT(duo), text_('42')) class TestWSGIHTTPException(unittest.TestCase): def _getTargetClass(self): @@ -128,7 +129,7 @@ class TestWSGIHTTPException(unittest.TestCase): self.assertEqual(exc.app_iter, ['123']) def test_ctor_with_unicode_body_doesnt_set_default_app_iter(self): - exc = self._makeOne(unicode_body=u'123') + exc = self._makeOne(unicode_body=text_('123')) self.assertEqual(exc.app_iter, ['123']) def test_ctor_with_app_iter_doesnt_set_default_app_iter(self): diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 1fa1cbbcf..40f1adf14 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -6,6 +6,7 @@ import unittest from pyramid.wsgi import wsgiapp from pyramid.view import view_config from pyramid.static import static_view +from pyramid.compat import text_ from zope.interface import Interface @@ -82,13 +83,17 @@ class TestStaticAppBase(IntegrationBase): def test_highchars_in_pathelement(self): res = self.testapp.get('/static/héhé/index.html', status=200) self._assertBody( - res.body, os.path.join(here, u'fixtures/static/héhé/index.html') + res.body, os.path.join( + here, + text_('fixtures/static/héhé/index.html', 'utf-8')) ) def test_highchars_in_filename(self): res = self.testapp.get('/static/héhé.html', status=200) self._assertBody( - res.body, os.path.join(here, u'fixtures/static/héhé.html') + res.body, os.path.join( + here, + text_('fixtures/static/héhé.html', 'utf-8')) ) def test_not_modified(self): diff --git a/pyramid/tests/test_mako_templating.py b/pyramid/tests/test_mako_templating.py index 162f774f5..9948c713c 100644 --- a/pyramid/tests/test_mako_templating.py +++ b/pyramid/tests/test_mako_templating.py @@ -2,6 +2,7 @@ import unittest from pyramid import testing +from pyramid.compat import text_ class Base(object): def setUp(self): @@ -276,7 +277,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): instance = self._makeOne('path', lookup) result = instance({}, {'system':1}) self.assertTrue(isinstance(result, unicode)) - self.assertEqual(result, u'result') + self.assertEqual(result, text_('result')) def test_call_with_system_context(self): # lame @@ -284,7 +285,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): instance = self._makeOne('path', lookup) result = instance({}, {'context':1}) self.assertTrue(isinstance(result, unicode)) - self.assertEqual(result, u'result') + self.assertEqual(result, text_('result')) self.assertEqual(lookup.values, {'_context':1}) def test_call_with_tuple_value(self): @@ -292,7 +293,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): instance = self._makeOne('path', lookup) result = instance(('fub', {}), {'context':1}) self.assertEqual(lookup.deffed, 'fub') - self.assertEqual(result, u'result') + self.assertEqual(result, text_('result')) self.assertEqual(lookup.values, {'_context':1}) def test_call_with_nondict_value(self): @@ -316,7 +317,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): instance = self._makeOne('path', lookup) result = instance.implementation().render_unicode() self.assertTrue(isinstance(result, unicode)) - self.assertEqual(result, u'result') + self.assertEqual(result, text_('result')) class TestIntegration(unittest.TestCase): def setUp(self): @@ -333,45 +334,48 @@ class TestIntegration(unittest.TestCase): def test_render(self): from pyramid.renderers import render result = render('helloworld.mak', {'a':1}).replace('\r','') - self.assertEqual(result, u'\nHello föö\n') + self.assertEqual(result, text_('\nHello föö\n', 'utf-8')) def test_render_from_fs(self): from pyramid.renderers import render self.config.add_settings({'reload_templates': True}) result = render('helloworld.mak', {'a':1}).replace('\r','') - self.assertEqual(result, u'\nHello föö\n') + self.assertEqual(result, text_('\nHello föö\n', 'utf-8')) def test_render_inheritance(self): from pyramid.renderers import render result = render('helloinherit.mak', {}).replace('\r','') - self.assertEqual(result, u'Layout\nHello World!\n') + self.assertEqual(result, text_('Layout\nHello World!\n')) def test_render_inheritance_pkg_spec(self): from pyramid.renderers import render result = render('hello_inherit_pkg.mak', {}).replace('\r','') - self.assertEqual(result, u'Layout\nHello World!\n') + self.assertEqual(result, text_('Layout\nHello World!\n')) def test_render_to_response(self): from pyramid.renderers import render_to_response result = render_to_response('helloworld.mak', {'a':1}) - self.assertEqual(result.ubody.replace('\r',''), u'\nHello föö\n') + self.assertEqual(result.ubody.replace('\r',''), + text_('\nHello föö\n', 'utf-8')) def test_render_to_response_pkg_spec(self): from pyramid.renderers import render_to_response result = render_to_response('pyramid.tests:fixtures/helloworld.mak', {'a':1}) - self.assertEqual(result.ubody.replace('\r', ''), u'\nHello föö\n') + self.assertEqual(result.ubody.replace('\r', ''), + text_('\nHello föö\n', 'utf-8')) def test_render_with_abs_path(self): from pyramid.renderers import render result = render('/helloworld.mak', {'a':1}).replace('\r','') - self.assertEqual(result, u'\nHello föö\n') + self.assertEqual(result, text_('\nHello föö\n', 'utf-8')) def test_get_renderer(self): from pyramid.renderers import get_renderer result = get_renderer('helloworld.mak') - self.assertEqual(result.implementation().render_unicode().replace('\r',''), - u'\nHello föö\n') + self.assertEqual( + result.implementation().render_unicode().replace('\r',''), + text_('\nHello föö\n', 'utf-8')) def test_template_not_found(self): from pyramid.renderers import render @@ -381,8 +385,9 @@ class TestIntegration(unittest.TestCase): def test_template_default_escaping(self): from pyramid.renderers import render - result = render('nonminimal.mak', {'name':'fred'}).replace('\r','') - self.assertEqual(result, u'Hello, <b>fred</b>!\n') + result = render('nonminimal.mak', + {'name':'fred'}).replace('\r','') + self.assertEqual(result, text_('Hello, <b>fred</b>!\n')) class TestPkgResourceTemplateLookup(unittest.TestCase): def _makeOne(self, **kw): @@ -448,7 +453,7 @@ class DummyLookup(object): if self.exc: raise self.exc self.values = values - return u'result' + return text_('result') class DummyRendererInfo(object): def __init__(self, kw): diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index 995e05d46..cf551ed5c 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1062,7 +1062,7 @@ class DummyConfigParser(object): self.section = section if self.result is None: from ConfigParser import NoSectionError - raise NoSectionError, section + raise NoSectionError(section) return self.result class DummyConfigParserFactory(object): diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 066aa9207..d48cba58d 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -1,6 +1,8 @@ import unittest from pyramid import testing +from pyramid.compat import text_ + class TestRequest(unittest.TestCase): def setUp(self): self.config = testing.setUp() @@ -50,7 +52,7 @@ class TestRequest(unittest.TestCase): } request = self._makeOne(environ) request.charset = None - self.assertEqual(request.GET['la'], u'La Pe\xf1a') + self.assertEqual(request.GET['la'], text_('La Pe\xf1a', 'utf-8')) def test_class_implements(self): from pyramid.interfaces import IRequest @@ -166,7 +168,7 @@ class TestRequest(unittest.TestCase): self.config.registry.registerUtility(mapper, IRoutesMapper) result = inst.route_url('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -184,7 +186,7 @@ class TestRequest(unittest.TestCase): self.config.registry.registerUtility(mapper, IRoutesMapper) result = inst.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_static_url(self): diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 35f2e4352..ebb76f941 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -1,3 +1,4 @@ +import sys import unittest from pyramid import testing @@ -1204,7 +1205,8 @@ class DummyLogger: def exc_raised(exc, func, *arg, **kw): try: func(*arg, **kw) - except exc, e: + except exc: + e = sys.exc_info()[1] return e else: raise AssertionError('%s not raised' % exc) # pragma: no cover diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index 41a4788ec..c131cc94b 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -1,5 +1,5 @@ - import unittest +from pyramid.compat import text_ class TestBase(unittest.TestCase): def setUp(self): @@ -46,14 +46,14 @@ class Test_registerResources(TestBase): self.assertEqual(result['context'], ob1) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'ob1',)) + self.assertEqual(result['traversed'], (text_('ob1'),)) self.assertEqual(result['virtual_root'], ob1) self.assertEqual(result['virtual_root_path'], ()) result = adapter(DummyRequest({'PATH_INFO':'/ob2'})) self.assertEqual(result['context'], ob2) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'ob2',)) + self.assertEqual(result['traversed'], (text_('ob2'),)) self.assertEqual(result['virtual_root'], ob2) self.assertEqual(result['virtual_root_path'], ()) self.assertRaises(KeyError, adapter, DummyRequest({'PATH_INFO':'/ob3'})) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 95caf21be..2f3a0017a 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -1,6 +1,7 @@ import unittest from pyramid.testing import cleanUp +from pyramid.compat import text_ class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): @@ -8,23 +9,24 @@ class TraversalPathTests(unittest.TestCase): return traversal_path(path) def test_path_startswith_endswith(self): - self.assertEqual(self._callFUT('/foo/'), (u'foo',)) + self.assertEqual(self._callFUT('/foo/'), (text_('foo'),)) def test_empty_elements(self): - self.assertEqual(self._callFUT('foo///'), (u'foo',)) + self.assertEqual(self._callFUT('foo///'), (text_('foo'),)) def test_onedot(self): - self.assertEqual(self._callFUT('foo/./bar'), (u'foo', u'bar')) + self.assertEqual(self._callFUT('foo/./bar'), + (text_('foo'), text_('bar'))) def test_twodots(self): - self.assertEqual(self._callFUT('foo/../bar'), (u'bar',)) + self.assertEqual(self._callFUT('foo/../bar'), (text_('bar'),)) def test_twodots_at_start(self): - self.assertEqual(self._callFUT('../../bar'), (u'bar',)) + self.assertEqual(self._callFUT('../../bar'), (text_('bar'),)) def test_element_urllquoted(self): self.assertEqual(self._callFUT('/foo/space%20thing/bar'), - (u'foo', u'space thing', u'bar')) + (text_('foo'), text_('space thing'), text_('bar'))) def test_segments_are_unicode(self): result = self._callFUT('/foo/bar') @@ -34,8 +36,8 @@ class TraversalPathTests(unittest.TestCase): def test_same_value_returned_if_cached(self): result1 = self._callFUT('/foo/bar') result2 = self._callFUT('/foo/bar') - self.assertEqual(result1, (u'foo', u'bar')) - self.assertEqual(result2, (u'foo', u'bar')) + self.assertEqual(result1, (text_('foo'), text_('bar'))) + self.assertEqual(result2, (text_('foo'), text_('bar'))) def test_utf8(self): import urllib @@ -54,15 +56,16 @@ class TraversalPathTests(unittest.TestCase): self.assertRaises(URLDecodeError, self._callFUT, path) def test_unicode_highorder_chars(self): - path = u'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF' - self.assertEqual(self._callFUT(path), (u'\u6d41\u884c\u8d8b\u52bf',)) + path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') + self.assertEqual(self._callFUT(path), + (text_('\u6d41\u884c\u8d8b\u52bf'),)) def test_unicode_simple(self): - path = u'/abc' - self.assertEqual(self._callFUT(path), (u'abc',)) + path = text_('/abc') + self.assertEqual(self._callFUT(path), (text_('abc'),)) def test_unicode_undecodeable_to_ascii(self): - path = unicode('/La Pe\xc3\xb1a', 'utf-8') + path = text_('/La Pe\xc3\xb1a', 'utf-8') self.assertRaises(UnicodeEncodeError, self._callFUT, path) class ResourceTreeTraverserTests(unittest.TestCase): @@ -146,7 +149,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], foo) self.assertEqual(result['view_name'], 'bar') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'foo',)) + self.assertEqual(result['traversed'], (text_('foo'),)) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], root) self.assertEqual(result['virtual_root_path'], ()) @@ -161,7 +164,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], foo) self.assertEqual(result['view_name'], 'bar') self.assertEqual(result['subpath'], ('baz', 'buz')) - self.assertEqual(result['traversed'], (u'foo',)) + self.assertEqual(result['traversed'], (text_('foo'),)) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], root) self.assertEqual(result['virtual_root_path'], ()) @@ -194,10 +197,12 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz')) + self.assertEqual(result['traversed'], + (text_('foo'), text_('bar'), text_('baz'))) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], bar) - self.assertEqual(result['virtual_root_path'], (u'foo', u'bar')) + self.assertEqual(result['virtual_root_path'], + (text_('foo'), text_('bar'))) def test_call_with_vh_root2(self): environ = self._getEnviron(PATH_INFO='/bar/baz', @@ -212,10 +217,11 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz')) + self.assertEqual(result['traversed'], + (text_('foo'), text_('bar'), text_('baz'))) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], foo) - self.assertEqual(result['virtual_root_path'], (u'foo',)) + self.assertEqual(result['virtual_root_path'], (text_('foo'),)) def test_call_with_vh_root3(self): environ = self._getEnviron(PATH_INFO='/foo/bar/baz', @@ -230,7 +236,8 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz')) + self.assertEqual(result['traversed'], + (text_('foo'), text_('bar'), text_('baz'))) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], root) self.assertEqual(result['virtual_root_path'], ()) @@ -248,10 +255,12 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['context'], baz) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz')) + self.assertEqual(result['traversed'], + (text_('foo'), text_('bar'), text_('baz'))) self.assertEqual(result['root'], root) self.assertEqual(result['virtual_root'], baz) - self.assertEqual(result['virtual_root_path'], (u'foo', u'bar', u'baz')) + self.assertEqual(result['virtual_root_path'], + (text_('foo'), text_('bar'), text_('baz'))) def test_call_with_vh_root_path_root(self): policy = self._makeOne(None) @@ -592,13 +601,15 @@ class FindResourceTests(unittest.TestCase): unprintable = DummyContext() root = DummyContext(unprintable) unprintable.__parent__ = root - unprintable.__name__ = unicode( + unprintable.__name__ = text_( '/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') root.__parent__ = None root.__name__ = None traverser = ResourceTreeTraverser self._registerTraverser(traverser) - result = self._callFUT(root, u'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') + result = self._callFUT( + root, + text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF')) self.assertEqual(result, unprintable) class ResourcePathTests(unittest.TestCase): @@ -1168,7 +1179,7 @@ class DummyContext(object): def __getitem__(self, name): if self.next is None: - raise KeyError, name + raise KeyError(name) return self.next def __repr__(self): diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 8b95374fb..452debd42 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import setUp from pyramid.testing import tearDown +from pyramid.compat import text_ class TestURLMethodsMixin(unittest.TestCase): def setUp(self): @@ -172,7 +173,7 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', a=1, b=2, c=3, _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1#foo') @@ -281,7 +282,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -294,7 +295,8 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=u"foo", _route_name='bar') + _anchor=text_("foo"), + _route_name='bar') self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -308,7 +310,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '/script_name' request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_path('extra1', 'extra2', _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, '/script_name/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_elements(self): @@ -319,7 +321,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '' result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_script_name(self): @@ -330,7 +332,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=u"foo") + _anchor=text_("foo")) self.assertEqual(result, '/foo/1/2/3/extra1/extra2?a=1#foo') def test_static_url_staticurlinfo_notfound(self): diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index 3c92e87be..6cad71d90 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -1,5 +1,6 @@ import unittest from pyramid import testing +from pyramid.compat import text_ class TestRoute(unittest.TestCase): def _getTargetClass(self): @@ -146,7 +147,7 @@ class RoutesMapperTests(unittest.TestCase): def test___call__custom_predicate_gets_info(self): mapper = self._makeOne() def pred(info, request): - self.assertEqual(info['match'], {'action':u'action1'}) + self.assertEqual(info['match'], {'action':'action1'}) self.assertEqual(info['route'], mapper.routes['foo']) return True mapper.connect('foo', 'archives/:action/article1', predicates=[pred]) @@ -269,7 +270,7 @@ class TestCompileRoute(unittest.TestCase): 'traverse':('everything', 'else', 'here')}) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) self.assertEqual(generator( - {'baz':1, 'buz':2, 'traverse':u'/a/b'}), '/foo/1/biz/2/bar/a/b') + {'baz':1, 'buz':2, 'traverse':'/a/b'}), '/foo/1/biz/2/bar/a/b') def test_with_bracket_star(self): matcher, generator = self._callFUT( @@ -364,9 +365,10 @@ class TestCompileRouteFunctional(unittest.TestCase): {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches('{x}', '/La%20Pe%C3%B1a', {'x':u'La Pe\xf1a'}) + self.matches('{x}', '/La%20Pe%C3%B1a', + {'x':text_('La Pe\xf1a', 'utf-8')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(u'La Pe\xf1a', 'x')}) + {'traverse':(text_('La Pe\xf1a', 'utf-8'), 'x')}) self.matches('/foo/{id}.html', '/foo/bar.html', {'id':'bar'}) self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def', {'num':'555', 'traverse':('abc', 'def')}) @@ -387,9 +389,10 @@ class TestCompileRouteFunctional(unittest.TestCase): {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches(':x', '/La%20Pe%C3%B1a', {'x':u'La Pe\xf1a'}) + self.matches(':x', '/La%20Pe%C3%B1a', + {'x':text_('La Pe\xf1a', 'utf-8')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(u'La Pe\xf1a', 'x')}) + {'traverse':(text_('La Pe\xf1a', 'utf-8'), 'x')}) self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'}) self.matches('/foo/:id_html', '/foo/bar_html', {'id_html':'bar_html'}) self.matches('zzz/:_', '/zzz/abc', {'_':'abc'}) @@ -413,7 +416,8 @@ class TestCompileRouteFunctional(unittest.TestCase): self.generates('/{x}*y', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', u'La Pe\xf1a')}, + self.generates('*traverse', {'traverse':('a', + text_('La Pe\xf1a', 'utf-8'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/{id}.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/{_}', {'_':'20'}, '/foo/20') @@ -433,7 +437,8 @@ class TestCompileRouteFunctional(unittest.TestCase): self.generates('/:x*y', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', u'La Pe\xf1a')}, + self.generates('*traverse', {'traverse':('a', + text_('La Pe\xf1a', 'utf-8'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/:_', {'_':'20'}, '/foo/20') diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py index 247b61dad..2c38314f4 100644 --- a/pyramid/tests/test_util.py +++ b/pyramid/tests/test_util.py @@ -1,4 +1,5 @@ import unittest +import sys class TestDottedNameResolver(unittest.TestCase): def _makeOne(self, package=None): @@ -9,7 +10,8 @@ class TestDottedNameResolver(unittest.TestCase): from pyramid.exceptions import ConfigurationError try: func(*arg, **kw) - except ConfigurationError, e: + except ConfigurationError: + e = sys.exc_info()[1] return e else: raise AssertionError('Invalid not raised') # pragma: no cover diff --git a/pyramid/traversal.py b/pyramid/traversal.py index b871b8229..7fa80e6b3 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -1,3 +1,4 @@ +import sys import urllib import warnings @@ -11,11 +12,14 @@ from pyramid.interfaces import IRequestFactory from pyramid.interfaces import ITraverser from pyramid.interfaces import VH_ROOT_KEY +from pyramid.compat import text_ from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage from pyramid.threadlocal import get_current_registry +empty = text_('') + def find_root(resource): """ Find the root node in the resource tree to which ``resource`` belongs. Note that ``resource`` should be :term:`location`-aware. @@ -478,7 +482,8 @@ def traversal_path(path): segment = urllib.unquote(segment) try: segment = segment.decode('utf-8') - except UnicodeDecodeError, e: + except UnicodeDecodeError: + e = sys.exc_info()[1] raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': continue @@ -639,7 +644,7 @@ class ResourceTreeTraverser(object): ob = next i += 1 - return {'context':ob, 'view_name':u'', 'subpath':subpath, + return {'context':ob, 'view_name':empty, 'subpath':subpath, 'traversed':vpath_tuple, 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} diff --git a/pyramid/tweens.py b/pyramid/tweens.py index b15204e9d..e40f5102f 100644 --- a/pyramid/tweens.py +++ b/pyramid/tweens.py @@ -15,11 +15,11 @@ def excview_tween_factory(handler, registry): attrs = request.__dict__ try: response = handler(request) - except Exception, exc: + except Exception: # WARNING: do not assign the result of sys.exc_info() to a # local var here, doing so will cause a leak attrs['exc_info'] = sys.exc_info() - attrs['exception'] = exc + exc = attrs['exception'] = attrs['exc_info'][1] # clear old generated request.response, if any; it may # have been mutated by the view, and its state is not # sane (e.g. caching headers) diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 73318193c..215f6a4a1 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -1,10 +1,11 @@ import re -from urllib import unquote +import sys from zope.interface import implements from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoute +from pyramid.compat import url_unquote from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.traversal import traversal_path @@ -133,14 +134,15 @@ def _compile_route(route): if m is None: return m d = {} - for k, v in m.groupdict().iteritems(): + for k, v in m.groupdict().items(): if k == star: d[k] = traversal_path(v) else: - encoded = unquote(v) + encoded = url_unquote(v) try: d[k] = encoded.decode('utf-8') - except UnicodeDecodeError, e: + except UnicodeDecodeError: + e = sys.exc_info()[1] raise URLDecodeError( e.encoding, e.object, e.start, e.end, e.reason ) diff --git a/pyramid/util.py b/pyramid/util.py index c0e7640c4..a43b50aef 100644 --- a/pyramid/util.py +++ b/pyramid/util.py @@ -2,6 +2,7 @@ import pkg_resources import sys import weakref +from pyramid.compat import string_types from pyramid.exceptions import ConfigurationError from pyramid.path import package_of @@ -69,7 +70,7 @@ class DottedNameResolver(object): self.package_name = None self.package = None else: - if isinstance(package, basestring): + if isinstance(package, string_types): try: __import__(package) except ImportError: @@ -132,12 +133,12 @@ class DottedNameResolver(object): return found def resolve(self, dotted): - if not isinstance(dotted, basestring): + if not isinstance(dotted, string_types): raise ConfigurationError('%r is not a string' % (dotted,)) return self.maybe_resolve(dotted) def maybe_resolve(self, dotted): - if isinstance(dotted, basestring): + if isinstance(dotted, string_types): if ':' in dotted: return self._pkg_resources_style(dotted) else: diff --git a/pyramid/view.py b/pyramid/view.py index 8b8ac58ce..f4d92b6ed 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -7,6 +7,7 @@ from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier +from pyramid.compat import map_ from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import default_exceptionresponse_view from pyramid.path import caller_package @@ -52,7 +53,7 @@ def render_view_to_response(context, request, name='', secure=True): disallowed. If ``secure`` is ``False``, no permission checking is done.""" - provides = [IViewClassifier] + map(providedBy, (request, context)) + provides = [IViewClassifier] + map_(providedBy, (request, context)) try: reg = request.registry except AttributeError: diff --git a/setup.py b/setup.py index b3e5deea2..4213bb628 100644 --- a/setup.py +++ b/setup.py @@ -18,6 +18,9 @@ import sys from setuptools import setup, find_packages +PY3 = sys.version_info[0] == 3 +JYTHON = platform.system() != 'Java' + here = os.path.abspath(os.path.dirname(__file__)) try: README = open(os.path.join(here, 'README.rst')).read() @@ -28,9 +31,6 @@ except IOError: install_requires=[ 'Chameleon >= 1.2.3', 'Mako >= 0.3.6', # strict_undefined - 'Paste > 1.7', # temp version pin to prevent PyPi install failure :-( - 'PasteDeploy', - 'PasteScript >= 1.7.4', # "here" in logging fileConfig 'WebOb >= 1.0.2', # no "default_charset"; request.script_name doesnt error 'repoze.lru', 'setuptools', @@ -40,21 +40,29 @@ install_requires=[ 'translationstring', ] -if platform.system() == 'Java': - tests_require = install_requires + [ - 'WebTest', - 'virtualenv', - 'zope.component>=3.11.0', - ] -else: - tests_require= install_requires + [ +if not PY3: + install_requires.extend([ + 'Paste > 1.7', # temp version pin to prevent PyPi install failure :-( + 'PasteDeploy', + 'PasteScript >= 1.7.4', # "here" in logging fileConfig + ]) + +tests_require = install_requires + [ + 'WebTest', + 'virtualenv', + ] + +if not JYTHON: + tests_require.extend([ 'Sphinx', 'docutils', 'repoze.sphinx.autointerface', - 'WebTest', - 'virtualenv', + ]) + +if not PY3: + tests_require.extend([ 'zope.component>=3.11.0', - ] + ]) if sys.version_info[:2] < (2, 6): install_requires.append('simplejson') -- cgit v1.2.3 From 16a5d32a99989f100c650d3a1b80cf60ce19f24c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 22 Sep 2011 17:56:38 -0400 Subject: fix tests on py2 --- pyramid/compat.py | 1 + pyramid/config/views.py | 3 ++- pyramid/tests/test_request.py | 2 +- pyramid/tests/test_traversal.py | 2 +- pyramid/tests/test_urldispatch.py | 23 ++++++++++------------- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index 5ef3c4e6d..21e8df6a5 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -32,6 +32,7 @@ else: class_types = (type, types.ClassType) text_type = unicode binary_type = str + long = long def ords_(s): return [ord(x) for x in s] diff --git a/pyramid/config/views.py b/pyramid/config/views.py index f1370a4b9..203f2b5c6 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -43,6 +43,7 @@ from pyramid.config.util import as_sorted_tuple from pyramid.config.util import make_predicates urljoin = urlparse.urljoin +url_parse = urlparse.urlparse def wraps_view(wrapper): def inner(self, view): @@ -1447,7 +1448,7 @@ class StaticURLInfo(object): # make sure it ends with a slash name = name + '/' - if urlparse(name)[0]: + if url_parse(name)[0]: # it's a URL # url, spec, route_name url = name diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index d48cba58d..572f14f0b 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -52,7 +52,7 @@ class TestRequest(unittest.TestCase): } request = self._makeOne(environ) request.charset = None - self.assertEqual(request.GET['la'], text_('La Pe\xf1a', 'utf-8')) + self.assertEqual(request.GET['la'], text_('La Pe\xf1a')) def test_class_implements(self): from pyramid.interfaces import IRequest diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 2f3a0017a..6231c516b 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -58,7 +58,7 @@ class TraversalPathTests(unittest.TestCase): def test_unicode_highorder_chars(self): path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') self.assertEqual(self._callFUT(path), - (text_('\u6d41\u884c\u8d8b\u52bf'),)) + (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),)) def test_unicode_simple(self): path = text_('/abc') diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index 6cad71d90..8a4252766 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -365,10 +365,9 @@ class TestCompileRouteFunctional(unittest.TestCase): {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches('{x}', '/La%20Pe%C3%B1a', - {'x':text_('La Pe\xf1a', 'utf-8')}) + self.matches('{x}', '/La%20Pe%C3%B1a', {'x':text_('La Pe\xf1a')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(text_('La Pe\xf1a', 'utf-8'), 'x')}) + {'traverse':(text_('La Pe\xf1a'), 'x')}) self.matches('/foo/{id}.html', '/foo/bar.html', {'id':'bar'}) self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def', {'num':'555', 'traverse':('abc', 'def')}) @@ -390,9 +389,9 @@ class TestCompileRouteFunctional(unittest.TestCase): self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) self.matches(':x', '/La%20Pe%C3%B1a', - {'x':text_('La Pe\xf1a', 'utf-8')}) + {'x':text_('La Pe\xf1a')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(text_('La Pe\xf1a', 'utf-8'), 'x')}) + {'traverse':(text_('La Pe\xf1a'), 'x')}) self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'}) self.matches('/foo/:id_html', '/foo/bar_html', {'id_html':'bar_html'}) self.matches('zzz/:_', '/zzz/abc', {'_':'abc'}) @@ -411,13 +410,12 @@ class TestCompileRouteFunctional(unittest.TestCase): '/zzz/abc') self.generates('zzz/{x}*traverse', {'x':'abc', 'traverse':'/def/g'}, '/zzz/abc/def/g') - self.generates('/{x}', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8')}, + self.generates('/{x}', {'x':text_('/La Pe\xc3\xb1a', 'utf-8')}, '/%2FLa%20Pe%C3%B1a') - self.generates('/{x}*y', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8'), + self.generates('/{x}*y', {'x':text_('/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', - text_('La Pe\xf1a', 'utf-8'))}, + self.generates('*traverse', {'traverse':('a', text_('La Pe\xf1a'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/{id}.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/{_}', {'_':'20'}, '/foo/20') @@ -432,13 +430,12 @@ class TestCompileRouteFunctional(unittest.TestCase): '/zzz/abc') self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':'/def/g'}, '/zzz/abc/def/g') - self.generates('/:x', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8')}, + self.generates('/:x', {'x':text_('/La Pe\xc3\xb1a', 'utf-8')}, '/%2FLa%20Pe%C3%B1a') - self.generates('/:x*y', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8'), + self.generates('/:x*y', {'x':text_('/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', - text_('La Pe\xf1a', 'utf-8'))}, + self.generates('*traverse', {'traverse':('a', text_('La Pe\xf1a'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/:_', {'_':'20'}, '/foo/20') -- cgit v1.2.3 From 3b7334af6b33a462f9bab074b92541ab6ad23d2a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 22 Sep 2011 21:25:56 -0400 Subject: implements->implementer --- pyramid/authentication.py | 10 +++++----- pyramid/authorization.py | 5 ++--- pyramid/chameleon_text.py | 4 ++-- pyramid/chameleon_zpt.py | 4 ++-- pyramid/compat.py | 5 +++++ pyramid/config/assets.py | 4 ++-- pyramid/config/settings.py | 4 ++-- pyramid/config/tweens.py | 4 ++-- pyramid/config/views.py | 8 ++++---- pyramid/events.py | 12 ++++++------ pyramid/httpexceptions.py | 4 ++-- pyramid/mako_templating.py | 4 ++-- pyramid/paster.py | 4 ++-- pyramid/renderers.py | 6 +++--- pyramid/request.py | 4 ++-- pyramid/response.py | 6 +++--- pyramid/router.py | 4 ++-- pyramid/session.py | 4 ++-- pyramid/testing.py | 6 +++--- pyramid/tests/test_config/__init__.py | 4 ++-- pyramid/tests/test_config/test_adapters.py | 14 ++++++++------ pyramid/tests/test_config/test_init.py | 24 ++++++++++++------------ pyramid/tests/test_config/test_testing.py | 5 +++-- pyramid/tests/test_config/test_views.py | 13 +++++++------ pyramid/tests/test_location.py | 4 ++-- pyramid/tests/test_paster.py | 28 +++++++++++++++------------- pyramid/tests/test_registry.py | 6 ++++-- pyramid/tests/test_router.py | 4 ++-- pyramid/tests/test_testing.py | 10 ++++++---- pyramid/tests/test_view.py | 8 +++++--- pyramid/traversal.py | 12 +++++++----- pyramid/urldispatch.py | 6 +++--- 32 files changed, 129 insertions(+), 111 deletions(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index d3d5a1ecd..898cc77a7 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -7,7 +7,7 @@ import sys import time as time_mod import urllib -from zope.interface import implements +from zope.interface import implementer from pyramid.compat import long @@ -108,6 +108,7 @@ class CallbackAuthenticationPolicy(object): ) return effective_principals +@implementer(IAuthenticationPolicy) class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` :term:`authentication policy` which obtains data from the :mod:`repoze.who` 1.X WSGI 'API' (the @@ -132,7 +133,6 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): Objects of this class implement the interface described by :class:`pyramid.interfaces.IAuthenticationPolicy`. """ - implements(IAuthenticationPolicy) def __init__(self, identifier_name='auth_tkt', callback=None): self.identifier_name = identifier_name @@ -196,6 +196,7 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): identity = self._get_identity(request) return identifier.forget(request.environ, identity) +@implementer(IAuthenticationPolicy) class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` :term:`authentication policy` which obtains data from the ``REMOTE_USER`` WSGI environment variable. @@ -225,7 +226,6 @@ class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): Objects of this class implement the interface described by :class:`pyramid.interfaces.IAuthenticationPolicy`. """ - implements(IAuthenticationPolicy) def __init__(self, environ_key='REMOTE_USER', callback=None, debug=False): self.environ_key = environ_key @@ -241,6 +241,7 @@ class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): def forget(self, request): return [] +@implementer(IAuthenticationPolicy) class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` :term:`authentication policy` which obtains data from an :class:`paste.auth.auth_tkt` cookie. @@ -343,7 +344,6 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): Objects of this class implement the interface described by :class:`pyramid.interfaces.IAuthenticationPolicy`. """ - implements(IAuthenticationPolicy) def __init__(self, secret, callback=None, @@ -747,6 +747,7 @@ class AuthTktCookieHelper(object): cookie_value = ticket.cookie_value() return self._get_cookies(environ, cookie_value, max_age) +@implementer(IAuthenticationPolicy) class SessionAuthenticationPolicy(CallbackAuthenticationPolicy): """ A :app:`Pyramid` authentication policy which gets its data from the configured :term:`session`. For this authentication policy to work, you @@ -776,7 +777,6 @@ class SessionAuthenticationPolicy(CallbackAuthenticationPolicy): or IRC channels when asking for support. """ - implements(IAuthenticationPolicy) def __init__(self, prefix='auth.', callback=None, debug=False): self.callback = callback diff --git a/pyramid/authorization.py b/pyramid/authorization.py index ac8f195f2..b1ef10033 100644 --- a/pyramid/authorization.py +++ b/pyramid/authorization.py @@ -1,4 +1,4 @@ -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IAuthorizationPolicy @@ -9,6 +9,7 @@ from pyramid.security import Allow from pyramid.security import Deny from pyramid.security import Everyone +@implementer(IAuthorizationPolicy) class ACLAuthorizationPolicy(object): """ An :term:`authorization policy` which consults an :term:`ACL` object attached to a :term:`context` to determine authorization @@ -60,8 +61,6 @@ class ACLAuthorizationPolicy(object): :class:`pyramid.interfaces.IAuthorizationPolicy` interface. """ - implements(IAuthorizationPolicy) - def permits(self, context, principals, permission): """ Return an instance of :class:`pyramid.security.ACLAllowed` instance if the policy diff --git a/pyramid/chameleon_text.py b/pyramid/chameleon_text.py index bb6531976..0539e0f29 100644 --- a/pyramid/chameleon_text.py +++ b/pyramid/chameleon_text.py @@ -1,7 +1,7 @@ import sys from zope.deprecation import deprecated -from zope.interface import implements +from zope.interface import implementer from pyramid.compat import reraise @@ -25,8 +25,8 @@ from pyramid.path import caller_package def renderer_factory(info): return renderers.template_renderer_factory(info, TextTemplateRenderer) +@implementer(ITemplateRenderer) class TextTemplateRenderer(object): - implements(ITemplateRenderer) def __init__(self, path, lookup): self.path = path self.lookup = lookup diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py index 495835c3d..dd1c47dcb 100644 --- a/pyramid/chameleon_zpt.py +++ b/pyramid/chameleon_zpt.py @@ -1,7 +1,7 @@ import sys from zope.deprecation import deprecated -from zope.interface import implements +from zope.interface import implementer from pyramid.compat import reraise @@ -24,8 +24,8 @@ from pyramid import renderers def renderer_factory(info): return renderers.template_renderer_factory(info, ZPTTemplateRenderer) +@implementer(ITemplateRenderer) class ZPTTemplateRenderer(object): - implements(ITemplateRenderer) def __init__(self, path, lookup): self.path = path self.lookup = lookup diff --git a/pyramid/compat.py b/pyramid/compat.py index 21e8df6a5..3a73b7e8f 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -182,3 +182,8 @@ if PY3: else: map_ = map +try: + import __pypy__ +except: + __pypy__ = None + diff --git a/pyramid/config/assets.py b/pyramid/config/assets.py index 1b5254072..08cc6dc38 100644 --- a/pyramid/config/assets.py +++ b/pyramid/config/assets.py @@ -1,7 +1,7 @@ import pkg_resources import sys -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IPackageOverrides @@ -80,8 +80,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): return pkg_resources.DefaultProvider.resource_listdir( self, resource_name) +@implementer(IPackageOverrides) class PackageOverrides: - implements(IPackageOverrides) # pkg_resources arg in kw args below for testing def __init__(self, package, pkg_resources=pkg_resources): if hasattr(package, '__loader__') and not isinstance(package.__loader__, diff --git a/pyramid/config/settings.py b/pyramid/config/settings.py index 6e636bf58..565a6699c 100644 --- a/pyramid/config/settings.py +++ b/pyramid/config/settings.py @@ -1,7 +1,7 @@ import os import warnings -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import ISettings @@ -54,12 +54,12 @@ class SettingsConfiguratorMixin(object): return self.registry.settings +@implementer(ISettings) class Settings(dict): """ Deployment settings. Update application settings (usually from PasteDeploy keywords) with framework-specific key/value pairs (e.g. find ``PYRAMID_DEBUG_AUTHORIZATION`` in os.environ and jam into keyword args).""" - implements(ISettings) # _environ_ is dep inj for testing def __init__(self, d=None, _environ_=os.environ, **kw): if d is None: diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py index 6feb1bfe6..0cdc55e65 100644 --- a/pyramid/config/tweens.py +++ b/pyramid/config/tweens.py @@ -1,4 +1,4 @@ -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import ITweens @@ -157,8 +157,8 @@ class CyclicDependencyError(Exception): msg = 'Implicit tween ordering cycle:' + '; '.join(L) return msg +@implementer(ITweens) class Tweens(object): - implements(ITweens) def __init__(self): self.explicit = [] self.names = [] diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 203f2b5c6..d89431bda 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -3,7 +3,7 @@ import inspect from zope.interface import Interface from zope.interface import classProvides from zope.interface import implementedBy -from zope.interface import implements +from zope.interface import implementer from zope.interface.interfaces import IInterface from pyramid.interfaces import IAuthenticationPolicy @@ -335,9 +335,9 @@ class ViewDeriver(object): return view return decorator(view) +@implementer(IViewMapper) class DefaultViewMapper(object): classProvides(IViewMapperFactory) - implements(IViewMapper) def __init__(self, **kw): self.attr = kw.get('attr') @@ -459,8 +459,8 @@ def requestonly(view, attr=None): return False +@implementer(IMultiView) class MultiView(object): - implements(IMultiView) def __init__(self, name): self.name = name @@ -1403,8 +1403,8 @@ def isexception(o): ) +@implementer(IStaticURLInfo) class StaticURLInfo(object): - implements(IStaticURLInfo) def _get_registrations(self, registry): try: diff --git a/pyramid/events.py b/pyramid/events.py index 71e923c0f..45edb8d02 100644 --- a/pyramid/events.py +++ b/pyramid/events.py @@ -1,6 +1,6 @@ import venusian -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IContextFound from pyramid.interfaces import INewRequest @@ -71,16 +71,17 @@ class subscriber(object): self.venusian.attach(wrapped, self.register, category='pyramid') return wrapped +@implementer(INewRequest) class NewRequest(object): """ An instance of this class is emitted as an :term:`event` whenever :app:`Pyramid` begins to process a new request. The even instance has an attribute, ``request``, which is a :term:`request` object. This event class implements the :class:`pyramid.interfaces.INewRequest` interface.""" - implements(INewRequest) def __init__(self, request): self.request = request +@implementer(INewResponse) class NewResponse(object): """ An instance of this class is emitted as an :term:`event` whenever any :app:`Pyramid` :term:`view` or :term:`exception @@ -112,11 +113,11 @@ class NewResponse(object): almost purely for symmetry with the :class:`pyramid.interfaces.INewRequest` event. """ - implements(INewResponse) def __init__(self, request, response): self.request = request self.response = response +@implementer(IContextFound) class ContextFound(object): """ An instance of this class is emitted as an :term:`event` after the :app:`Pyramid` :term:`router` finds a :term:`context` @@ -136,12 +137,12 @@ class ContextFound(object): purposes, this event may also be imported as :class:`pyramid.events.AfterTraversal`. """ - implements(IContextFound) def __init__(self, request): self.request = request AfterTraversal = ContextFound # b/c as of 1.0 +@implementer(IApplicationCreated) class ApplicationCreated(object): """ An instance of this class is emitted as an :term:`event` when the :meth:`pyramid.config.Configurator.make_wsgi_app` is @@ -156,13 +157,13 @@ class ApplicationCreated(object): was the name of the event class before :app:`Pyramid` 1.0. """ - implements(IApplicationCreated) def __init__(self, app): self.app = app self.object = app WSGIApplicationCreatedEvent = ApplicationCreated # b/c (as of 1.0) +@implementer(IBeforeRender) class BeforeRender(dict): """ Subscribers to this event may introspect the and modify the set of @@ -200,7 +201,6 @@ class BeforeRender(dict): See also :class:`pyramid.interfaces.IBeforeRender`. """ - implements(IBeforeRender) def __init__(self, system, rendering_val=None): dict.__init__(self, system) self.rendering_val = rendering_val diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py index 7cebfdc48..46bc1890c 100644 --- a/pyramid/httpexceptions.py +++ b/pyramid/httpexceptions.py @@ -124,7 +124,7 @@ field. Reflecting this, these subclasses have one additional keyword argument: from string import Template -from zope.interface import implements +from zope.interface import implementer from webob import html_escape as _html_escape @@ -145,8 +145,8 @@ def _no_escape(value): class HTTPException(Exception): # bw compat """ Base class for all :term:`exception response` objects.""" +@implementer(IExceptionResponse) class WSGIHTTPException(Response, HTTPException): - implements(IExceptionResponse) ## You should set in subclasses: # code = 200 diff --git a/pyramid/mako_templating.py b/pyramid/mako_templating.py index c79de7217..a12e72b86 100644 --- a/pyramid/mako_templating.py +++ b/pyramid/mako_templating.py @@ -2,7 +2,7 @@ import os import sys import threading -from zope.interface import implements +from zope.interface import implementer from zope.interface import Interface from pyramid.asset import resolve_asset_spec @@ -120,8 +120,8 @@ class MakoRenderingException(Exception): __str__ = __repr__ +@implementer(ITemplateRenderer) class MakoLookupTemplateRenderer(object): - implements(ITemplateRenderer) def __init__(self, path, lookup): self.path = path self.lookup = lookup diff --git a/pyramid/paster.py b/pyramid/paster.py index b419c1b16..4fc1812ca 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -378,7 +378,7 @@ class PViewsCommand(PCommand): configuration` within the application registry; return the view. """ from zope.interface import providedBy - from zope.interface import implements + from zope.interface import implementer from pyramid.interfaces import IRequest from pyramid.interfaces import IRootFactory from pyramid.interfaces import IRouteRequest @@ -399,8 +399,8 @@ class PViewsCommand(PCommand): adapters = registry.adapters request = None + @implementer(IMultiView) class RoutesMultiView(object): - implements(IMultiView) def __init__(self, infos, context_iface, root_factory, request): self.views = [] diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 93e97de8f..04208fcdc 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -2,7 +2,7 @@ import os import pkg_resources import threading -from zope.interface import implements +from zope.interface import implementer from zope.deprecation import deprecated from pyramid.interfaces import IChameleonLookup @@ -227,8 +227,8 @@ class JSONP(object): # utility functions, not API +@implementer(IChameleonLookup) class ChameleonRendererLookup(object): - implements(IChameleonLookup) def __init__(self, impl, registry): self.impl = impl self.registry = registry @@ -350,8 +350,8 @@ deprecated( 'the next major release. To replace it, use the ' '``pyramid.renderers.get_renderer`` API instead. ') +@implementer(IRendererInfo) class RendererHelper(object): - implements(IRendererInfo) def __init__(self, name=None, package=None, registry=None): if name and '.' in name: rtype = os.path.splitext(name)[1] diff --git a/pyramid/request.py b/pyramid/request.py index 03717031d..8188eecf1 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -1,6 +1,6 @@ from zope.deprecation import deprecate from zope.deprecation.deprecation import deprecated -from zope.interface import implements +from zope.interface import implementer from zope.interface.interface import InterfaceClass from webob import BaseRequest @@ -283,6 +283,7 @@ class CallbackMethodsMixin(object): callback = callbacks.pop(0) callback(self) +@implementer(IRequest) class Request(BaseRequest, DeprecatedRequestMethodsMixin, URLMethodsMixin, CallbackMethodsMixin): """ @@ -305,7 +306,6 @@ class Request(BaseRequest, DeprecatedRequestMethodsMixin, URLMethodsMixin, release of this :app:`Pyramid` version. See http://pythonpaste.org/webob/ for further information. """ - implements(IRequest) exception = None exc_info = None matchdict = None diff --git a/pyramid/response.py b/pyramid/response.py index db53de0c3..b0c965296 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -1,12 +1,12 @@ import venusian from webob import Response as _Response -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IResponse +@implementer(IResponse) class Response(_Response): - implements(IResponse) - + pass class response_adapter(object): """ Decorator activated via a :term:`scan` which treats the function diff --git a/pyramid/router.py b/pyramid/router.py index 746cf88cf..fb309eb03 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -1,4 +1,4 @@ -from zope.interface import implements +from zope.interface import implementer from zope.interface import providedBy from pyramid.interfaces import IDebugLogger @@ -23,8 +23,8 @@ from pyramid.traversal import DefaultRootFactory from pyramid.traversal import ResourceTreeTraverser from pyramid.tweens import excview_tween_factory +@implementer(IRouter) class Router(object): - implements(IRouter) debug_notfound = False debug_routematch = False diff --git a/pyramid/session.py b/pyramid/session.py index 633620716..b5e40c65d 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -6,7 +6,7 @@ import sys import time import os -from zope.interface import implements +from zope.interface import implementer from pyramid.compat import pickle from pyramid.interfaces import ISession @@ -84,9 +84,9 @@ def UnencryptedCookieSessionFactoryConfig( """ + @implementer(ISession) class UnencryptedCookieSessionFactory(dict): """ Dictionary-like session object """ - implements(ISession) # configuration parameters _cookie_name = cookie_name diff --git a/pyramid/testing.py b/pyramid/testing.py index 862b9d6b1..338eff9e9 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -3,7 +3,7 @@ import os from zope.deprecation import deprecated -from zope.interface import implements +from zope.interface import implementer from zope.interface import Interface from zope.interface import alsoProvides @@ -597,8 +597,8 @@ class DummyResource: DummyModel = DummyResource # b/w compat (forever) +@implementer(ISession) class DummySession(dict): - implements(ISession) created = None new = True def changed(self): @@ -628,6 +628,7 @@ class DummySession(dict): def get_csrf_token(self): return self.get('_csrft_', None) +@implementer(IRequest) class DummyRequest(DeprecatedRequestMethodsMixin, URLMethodsMixin, CallbackMethodsMixin): """ A DummyRequest object (incompletely) imitates a :term:`request` object. @@ -656,7 +657,6 @@ class DummyRequest(DeprecatedRequestMethodsMixin, URLMethodsMixin, a Request, use the :class:`pyramid.request.Request` class itself rather than this class while writing tests. """ - implements(IRequest) method = 'GET' application_url = 'http://example.com' host = 'example.com:80' diff --git a/pyramid/tests/test_config/__init__.py b/pyramid/tests/test_config/__init__.py index 2f9f516ae..5b40a8c09 100644 --- a/pyramid/tests/test_config/__init__.py +++ b/pyramid/tests/test_config/__init__.py @@ -1,6 +1,6 @@ # package -from zope.interface import implements +from zope.interface import implementer from zope.interface import Interface class IFactory(Interface): @@ -23,8 +23,8 @@ includeme = dummy_include class DummyContext: pass +@implementer(IFactory) class DummyFactory(object): - implements(IFactory) def __call__(self): """ """ diff --git a/pyramid/tests/test_config/test_adapters.py b/pyramid/tests/test_config/test_adapters.py index 29c099e0e..ff1ce52a1 100644 --- a/pyramid/tests/test_config/test_adapters.py +++ b/pyramid/tests/test_config/test_adapters.py @@ -9,12 +9,13 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): return config def test_add_subscriber_defaults(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import Interface class IEvent(Interface): pass + @implementer(IEvent) class Event: - implements(IEvent) + pass L = [] def subscriber(event): L.append(event) @@ -28,12 +29,13 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): self.assertEqual(len(L), 2) def test_add_subscriber_iface_specified(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import Interface class IEvent(Interface): pass + @implementer(IEvent) class Event: - implements(IEvent) + pass L = [] def subscriber(event): L.append(event) @@ -59,13 +61,13 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): self.assertEqual(handler.required, (INewRequest,)) def test_add_object_event_subscriber(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import Interface class IEvent(Interface): pass + @implementer(IEvent) class Event: object = 'foo' - implements(IEvent) event = Event() L = [] def subscriber(object, event): diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 750cdb94f..6b5ea06b3 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -2,6 +2,8 @@ import unittest import os +from pyramid.compat import __pypy__ + from pyramid.tests.test_config import dummy_tween_factory from pyramid.tests.test_config import dummy_include from pyramid.tests.test_config import dummy_extend @@ -9,14 +11,8 @@ from pyramid.tests.test_config import dummy_extend2 from pyramid.tests.test_config import IDummy from pyramid.tests.test_config import DummyContext -try: - import __pypy__ -except: - __pypy__ = None - from pyramid.exceptions import ConfigurationExecutionError from pyramid.exceptions import ConfigurationConflictError -from pyramid.exceptions import ConfigurationError class ConfiguratorTests(unittest.TestCase): def _makeOne(self, *arg, **kw): @@ -309,10 +305,12 @@ class ConfiguratorTests(unittest.TestCase): def test__fix_registry_queryAdapterOrSelf(self): from zope.interface import Interface + from zope.interface import implementer class IFoo(Interface): pass + @implementer(IFoo) class Foo(object): - implements(IFoo) + pass class Bar(object): pass adaptation = () @@ -1118,9 +1116,9 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase): def _registerRenderer(self, config, name='.txt'): from pyramid.interfaces import IRendererFactory from pyramid.interfaces import ITemplateRenderer - from zope.interface import implements + from zope.interface import implementer + @implementer(ITemplateRenderer) class Renderer: - implements(ITemplateRenderer) def __init__(self, info): self.__class__.info = info def __call__(self, *arg): @@ -1530,9 +1528,10 @@ class DummyThreadLocalManager(object): def pop(self): self.popped = True -from zope.interface import implements +from zope.interface import implementer +@implementer(IDummy) class DummyEvent: - implements(IDummy) + pass class DummyRegistry(object): def __init__(self, adaptation=None): @@ -1550,8 +1549,9 @@ class DummyRegistry(object): return self.adaptation from pyramid.interfaces import IResponse +@implementer(IResponse) class DummyResponse(object): - implements(IResponse) + pass from zope.interface import Interface class IOther(Interface): diff --git a/pyramid/tests/test_config/test_testing.py b/pyramid/tests/test_config/test_testing.py index 494a2b099..7f8c2c2b2 100644 --- a/pyramid/tests/test_config/test_testing.py +++ b/pyramid/tests/test_config/test_testing.py @@ -166,9 +166,10 @@ class TestingConfiguratorMixinTests(unittest.TestCase): renderer.assert_(bar=2) renderer.assert_(request=request) -from zope.interface import implements +from zope.interface import implementer +@implementer(IDummy) class DummyEvent: - implements(IDummy) + pass class DummyRequest: subpath = () diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 84d53338e..c615c5a9e 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -38,9 +38,9 @@ class TestViewsConfigurationMixin(unittest.TestCase): def _registerRenderer(self, config, name='.txt'): from pyramid.interfaces import IRendererFactory from pyramid.interfaces import ITemplateRenderer - from zope.interface import implements + from zope.interface import implementer + @implementer(ITemplateRenderer) class Renderer: - implements(ITemplateRenderer) def __init__(self, info): self.__class__.info = info def __call__(self, *arg): @@ -3461,10 +3461,11 @@ class DummyRequest: class DummyContext: pass -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IResponse +@implementer(IResponse) class DummyResponse(object): - implements(IResponse) + pass class DummyAccept(object): def __init__(self, *matches): @@ -3510,10 +3511,10 @@ class DummyConfig: def action(self, discriminator, callable): callable() -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IMultiView +@implementer(IMultiView) class DummyMultiView: - implements(IMultiView) def __init__(self): self.views = [] self.name = 'name' diff --git a/pyramid/tests/test_location.py b/pyramid/tests/test_location.py index 3d30c9954..e1f47f4ab 100644 --- a/pyramid/tests/test_location.py +++ b/pyramid/tests/test_location.py @@ -34,7 +34,7 @@ class TestLineage(unittest.TestCase): self.assertEqual(result, [o1]) from pyramid.interfaces import ILocation -from zope.interface import implements +from zope.interface import implementer +@implementer(ILocation) class Location(object): - implements(ILocation) __name__ = __parent__ = None diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index cf551ed5c..f46aca49d 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -397,7 +397,7 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(result, None) def test__find_view_no_match_multiview_registered(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import providedBy from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier @@ -405,8 +405,9 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.traversal import DefaultRootFactory from pyramid.registry import Registry registry = Registry() + @implementer(IMultiView) class View1(object): - implements(IMultiView) + pass request = DummyRequest({'PATH_INFO':'/a'}) root = DefaultRootFactory(request) root_iface = providedBy(root) @@ -439,7 +440,7 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(result, view1) def test__find_view_traversal_multiview(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import providedBy from pyramid.interfaces import IRequest from pyramid.interfaces import IViewClassifier @@ -447,8 +448,9 @@ class TestPViewsCommand(unittest.TestCase): from pyramid.traversal import DefaultRootFactory from pyramid.registry import Registry registry = Registry() + @implementer(IMultiView) class View1(object): - implements(IMultiView) + pass request = DummyRequest({'PATH_INFO':'/a'}) root = DefaultRootFactory(request) root_iface = providedBy(root) @@ -463,7 +465,7 @@ class TestPViewsCommand(unittest.TestCase): def test__find_view_route_no_multiview(self): from zope.interface import Interface - from zope.interface import implements + from zope.interface import implementer from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView @@ -478,8 +480,8 @@ class TestPViewsCommand(unittest.TestCase): (IViewClassifier, IMyRoute, IMyRoot), IView, '') registry.registerUtility(IMyRoute, IRouteRequest, name='a') + @implementer(IMyRoot) class Factory(object): - implements(IMyRoot) def __init__(self, request): pass routes = [DummyRoute('a', '/a', factory=Factory, matchdict={}), @@ -491,7 +493,7 @@ class TestPViewsCommand(unittest.TestCase): def test__find_view_route_multiview_no_view_registered(self): from zope.interface import Interface - from zope.interface import implements + from zope.interface import implementer from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IMultiView from pyramid.interfaces import IRootFactory @@ -507,8 +509,8 @@ class TestPViewsCommand(unittest.TestCase): pass registry.registerUtility(IMyRoute1, IRouteRequest, name='a') registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) class Factory(object): - implements(IMyRoot) def __init__(self, request): pass registry.registerUtility(Factory, IRootFactory) @@ -521,7 +523,7 @@ class TestPViewsCommand(unittest.TestCase): def test__find_view_route_multiview(self): from zope.interface import Interface - from zope.interface import implements + from zope.interface import implementer from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IView @@ -545,8 +547,8 @@ class TestPViewsCommand(unittest.TestCase): IView, '') registry.registerUtility(IMyRoute1, IRouteRequest, name='a') registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + @implementer(IMyRoot) class Factory(object): - implements(IMyRoot) def __init__(self, request): pass registry.registerUtility(Factory, IRootFactory) @@ -1042,10 +1044,10 @@ class DummyView(object): def __init__(self, **attrs): self.__request_attrs__ = attrs +from zope.interface import implementer +from pyramid.interfaces import IMultiView +@implementer(IMultiView) class DummyMultiView(object): - from zope.interface import implements - from pyramid.interfaces import IMultiView - implements(IMultiView) def __init__(self, *views, **attrs): self.views = [(None, view, None) for view in views] diff --git a/pyramid/tests/test_registry.py b/pyramid/tests/test_registry.py index 6a20eaa5d..c3104bd31 100644 --- a/pyramid/tests/test_registry.py +++ b/pyramid/tests/test_registry.py @@ -48,9 +48,11 @@ class DummyModule: __file__ = '' from zope.interface import Interface -from zope.interface import implements +from zope.interface import implementer class IDummyEvent(Interface): pass +@implementer(IDummyEvent) class DummyEvent(object): - implements(IDummyEvent) + pass + diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index ebb76f941..6a1cfd0d2 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -1165,10 +1165,10 @@ class DummyStartResponse: self.headers = headers from pyramid.interfaces import IResponse -from zope.interface import implements +from zope.interface import implementer +@implementer(IResponse) class DummyResponse(object): - implements(IResponse) headerlist = () app_iter = () environ = None diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index c131cc94b..919546a73 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -222,12 +222,12 @@ class Test_registerAdapter(TestBase): class Test_registerUtility(TestBase): def test_registerUtility(self): - from zope.interface import implements + from zope.interface import implementer from zope.interface import Interface class iface(Interface): pass + @implementer(iface) class impl: - implements(iface) def __call__(self): return 'foo' utility = impl() @@ -888,13 +888,15 @@ class TestDummySession(unittest.TestCase): from zope.interface import Interface -from zope.interface import implements +from zope.interface import implementer class IDummy(Interface): pass +@implementer(IDummy) class DummyEvent: - implements(IDummy) + pass + class DummyRequest: application_url = 'http://example.com' diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index 7f66a7563..29e468cd2 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -1,6 +1,8 @@ import unittest import sys +from zope.interface import implementer + from pyramid.testing import setUp from pyramid.testing import tearDown @@ -406,8 +408,9 @@ class TestViewConfigDecorator(unittest.TestCase): def test_call_with_renderer_IRendererInfo(self): import pyramid.tests from pyramid.interfaces import IRendererInfo + @implementer(IRendererInfo) class DummyRendererHelper(object): - implements(IRendererInfo) + pass renderer_helper = DummyRendererHelper() decorator = self._makeOne(renderer=renderer_helper) venusian = DummyVenusian() @@ -588,10 +591,9 @@ class DummyRequest: self.environ = environ from pyramid.interfaces import IResponse -from zope.interface import implements +@implementer(IResponse) class DummyResponse(object): - implements(IResponse) headerlist = () app_iter = () status = '200 OK' diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 7fa80e6b3..de525e503 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -2,7 +2,7 @@ import sys import urllib import warnings -from zope.interface import implements +from zope.interface import implementer from zope.interface.interfaces import IInterface from repoze.lru import lru_cache @@ -12,7 +12,9 @@ from pyramid.interfaces import IRequestFactory from pyramid.interfaces import ITraverser from pyramid.interfaces import VH_ROOT_KEY +from pyramid.compat import native_ from pyramid.compat import text_ +from pyramid.compat import text_type from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage @@ -529,22 +531,22 @@ def quote_path_segment(segment, safe=''): try: return _segment_cache[(segment, safe)] except KeyError: - if segment.__class__ is unicode: # isinstance slighly slower (~15%) + if segment.__class__ is text_type: # isinstance slighly slower (~15%) result = url_quote(segment.encode('utf-8'), safe) else: - result = url_quote(str(segment), safe) + result = url_quote(native_(segment), safe) # we don't need a lock to mutate _segment_cache, as the below # will generate exactly one Python bytecode (STORE_SUBSCR) _segment_cache[(segment, safe)] = result return result +@implementer(ITraverser) class ResourceTreeTraverser(object): """ A resource tree traverser that should be used (for speed) when every resource in the tree supplies a ``__name__`` and ``__parent__`` attribute (ie. every resource in the tree is :term:`location` aware) .""" - implements(ITraverser) VIEW_SELECTOR = '@@' @@ -650,10 +652,10 @@ class ResourceTreeTraverser(object): ModelGraphTraverser = ResourceTreeTraverser # b/w compat, not API, used in wild +@implementer(IContextURL) class TraversalContextURL(object): """ The IContextURL adapter used to generate URLs for a resource in a resource tree""" - implements(IContextURL) vroot_varname = VH_ROOT_KEY diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 215f6a4a1..043203b79 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -1,6 +1,6 @@ import re import sys -from zope.interface import implements +from zope.interface import implementer from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoute @@ -13,8 +13,8 @@ from pyramid.traversal import quote_path_segment _marker = object() +@implementer(IRoute) class Route(object): - implements(IRoute) def __init__(self, name, pattern, factory=None, predicates=(), pregenerator=None): self.pattern = pattern @@ -25,8 +25,8 @@ class Route(object): self.predicates = predicates self.pregenerator = pregenerator +@implementer(IRoutesMapper) class RoutesMapper(object): - implements(IRoutesMapper) def __init__(self): self.routelist = [] self.routes = {} -- cgit v1.2.3 From 475532de0651ec26a81b893d2b8016b11ae25010 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 22 Sep 2011 21:54:59 -0400 Subject: had about all i can take for a while --- pyramid/compat.py | 9 +++++++++ pyramid/config/tweens.py | 12 +++++++----- pyramid/config/views.py | 3 ++- pyramid/interfaces.py | 24 ++++++++++++++---------- pyramid/scaffolds/__init__.py | 13 +++++++++++-- pyramid/security.py | 3 ++- pyramid/session.py | 11 +++++++---- pyramid/tests/test_httpexceptions.py | 8 ++++---- pyramid/tests/test_request.py | 4 ++-- pyramid/tests/test_testing.py | 13 +++++++------ pyramid/tests/test_traversal.py | 1 + 11 files changed, 66 insertions(+), 35 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index 3a73b7e8f..a03fc893d 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -187,3 +187,12 @@ try: except: __pypy__ = None +if PY3: # pragma: no cover + def is_nonstr_iter(v): + if isinstance(v, str): + return False + return hasattr(v, '__iter__') +else: + def is_nonstr_iter(v): + return hasattr(v, '__iter__') + diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py index 0cdc55e65..c7d50248f 100644 --- a/pyramid/config/tweens.py +++ b/pyramid/config/tweens.py @@ -2,6 +2,8 @@ from zope.interface import implementer from pyramid.interfaces import ITweens +from pyramid.compat import string_types +from pyramid.compat import is_nonstr_iter from pyramid.exceptions import ConfigurationError from pyramid.tweens import excview_tween_factory from pyramid.tweens import MAIN, INGRESS, EXCVIEW @@ -110,7 +112,7 @@ class TweensConfiguratorMixin(object): tween_factory = self.maybe_dotted(tween_factory) def is_string_or_iterable(v): - if isinstance(v, basestring): + if isinstance(v, string_types): return True if hasattr(v, '__iter__'): return True @@ -121,10 +123,10 @@ class TweensConfiguratorMixin(object): raise ConfigurationError( '"%s" must be a string or iterable, not %s' % (t, p)) - if over is INGRESS or hasattr(over, '__iter__') and INGRESS in over: + if over is INGRESS or is_nonstr_iter(over) and INGRESS in over: raise ConfigurationError('%s cannot be over INGRESS' % name) - if under is MAIN or hasattr(under, '__iter__') and MAIN in under: + if under is MAIN or is_nonstr_iter(under) and MAIN in under: raise ConfigurationError('%s cannot be under MAIN' % name) registry = self.registry @@ -176,12 +178,12 @@ class Tweens(object): if under is None and over is None: under = INGRESS if under is not None: - if not hasattr(under, '__iter__'): + if not is_nonstr_iter(under): under = (under,) self.order += [(u, name) for u in under] self.req_under.add(name) if over is not None: - if not hasattr(over, '__iter__'): + if not is_nonstr_iter(over): #hasattr(over, '__iter__'): over = (over,) self.order += [(name, o) for o in over] self.req_over.add(name) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index d89431bda..51f13f69f 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -26,6 +26,7 @@ from pyramid.interfaces import IViewMapperFactory from pyramid.interfaces import PHASE1_CONFIG from pyramid import renderers +from pyramid.compat import string_types from pyramid.compat import urlparse from pyramid.exceptions import ConfigurationError from pyramid.exceptions import PredicateMismatch @@ -913,7 +914,7 @@ class ViewsConfiguratorMixin(object): if not IInterface.providedBy(r_context): r_context = implementedBy(r_context) - if isinstance(renderer, basestring): + if isinstance(renderer, string_types): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry = self.registry) diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index a2b7990aa..5f7108e89 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -1,6 +1,8 @@ from zope.interface import Attribute from zope.interface import Interface +from pyramid.compat import PY3 + # public API interfaces class IContextFound(Interface): @@ -292,25 +294,27 @@ class IDict(Interface): """ Return the value for key ``k`` from the renderer dictionary, or the default if no such value exists.""" - has_key = __contains__ - def items(): """ Return a list of [(k,v)] pairs from the dictionary """ - def iteritems(): - """ Return an iterator of (k,v) pairs from the dictionary """ - def keys(): """ Return a list of keys from the dictionary """ - def iterkeys(): - """ Return an iterator of keys from the dictionary """ - def values(): """ Return a list of values from the dictionary """ - def itervalues(): - """ Return an iterator of values from the dictionary """ + if not PY3: + + def iterkeys(): + """ Return an iterator of keys from the dictionary """ + + def iteritems(): + """ Return an iterator of (k,v) pairs from the dictionary """ + + def itervalues(): + """ Return an iterator of values from the dictionary """ + + has_key = __contains__ def pop(k, default=None): """ Pop the key k from the dictionary and return its value. If k diff --git a/pyramid/scaffolds/__init__.py b/pyramid/scaffolds/__init__.py index a49bbd9f6..ef93a53c7 100644 --- a/pyramid/scaffolds/__init__.py +++ b/pyramid/scaffolds/__init__.py @@ -1,7 +1,16 @@ import os -from paste.script.templates import Template -from paste.util.template import paste_script_template_renderer +try: + from paste.script.templates import Template +except ImportError: + class Template(object): + pass + +try: + from paste.util.template import paste_script_template_renderer +except ImportError: + def paste_script_template_renderer(self): + pass class PyramidTemplate(Template): def pre(self, command, output_dir, vars): diff --git a/pyramid/security.py b/pyramid/security.py index a001f7073..4355737b7 100644 --- a/pyramid/security.py +++ b/pyramid/security.py @@ -5,6 +5,7 @@ from pyramid.interfaces import IAuthorizationPolicy from pyramid.interfaces import ISecuredView from pyramid.interfaces import IViewClassifier +from pyramid.compat import map_ from pyramid.threadlocal import get_current_registry Everyone = 'system.Everyone' @@ -132,7 +133,7 @@ def view_execution_permitted(context, request, name=''): reg = request.registry except AttributeError: reg = get_current_registry() # b/c - provides = [IViewClassifier] + map(providedBy, (request, context)) + provides = [IViewClassifier] + map_(providedBy, (request, context)) view = reg.adapters.lookup(provides, ISecuredView, name=name) if view is None: return Allowed( diff --git a/pyramid/session.py b/pyramid/session.py index b5e40c65d..7d7edab1b 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -9,6 +9,7 @@ import os from zope.interface import implementer from pyramid.compat import pickle +from pyramid.compat import PY3 from pyramid.interfaces import ISession def manage_accessed(wrapped): @@ -140,16 +141,18 @@ def UnencryptedCookieSessionFactoryConfig( get = manage_accessed(dict.get) __getitem__ = manage_accessed(dict.__getitem__) items = manage_accessed(dict.items) - iteritems = manage_accessed(dict.iteritems) values = manage_accessed(dict.values) - itervalues = manage_accessed(dict.itervalues) keys = manage_accessed(dict.keys) - iterkeys = manage_accessed(dict.iterkeys) __contains__ = manage_accessed(dict.__contains__) - has_key = manage_accessed(dict.has_key) __len__ = manage_accessed(dict.__len__) __iter__ = manage_accessed(dict.__iter__) + if not PY3: + iteritems = manage_accessed(dict.iteritems) + itervalues = manage_accessed(dict.itervalues) + iterkeys = manage_accessed(dict.iterkeys) + has_key = manage_accessed(dict.has_key) + # modifying dictionary methods clear = manage_accessed(dict.clear) update = manage_accessed(dict.update) diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index fe3a79593..6a3ea7367 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -126,15 +126,15 @@ class TestWSGIHTTPException(unittest.TestCase): def test_ctor_with_body_doesnt_set_default_app_iter(self): exc = self._makeOne(body='123') - self.assertEqual(exc.app_iter, ['123']) + self.assertEqual(exc.app_iter, [b'123']) def test_ctor_with_unicode_body_doesnt_set_default_app_iter(self): exc = self._makeOne(unicode_body=text_('123')) - self.assertEqual(exc.app_iter, ['123']) + self.assertEqual(exc.app_iter, [b'123']) def test_ctor_with_app_iter_doesnt_set_default_app_iter(self): - exc = self._makeOne(app_iter=['123']) - self.assertEqual(exc.app_iter, ['123']) + exc = self._makeOne(app_iter=[b'123']) + self.assertEqual(exc.app_iter, [b'123']) def test_ctor_with_body_sets_default_app_iter_html(self): cls = self._getTargetSubclass() diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 572f14f0b..f1338e331 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -372,8 +372,8 @@ class TestRequestDeprecatedMethods(unittest.TestCase): def test_values(self): environ = {'zooma':1} inst = self._makeOne(environ) - result = inst.values() - self.assertEqual(result, environ.values()) + result = list(inst.values()) + self.assertEqual(result, list(environ.values())) def test_response_content_type(self): inst = self._makeOne() diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index 919546a73..f428fa40a 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -132,7 +132,7 @@ class Test_registerView(TestBase): request = DummyRequest() request.registry = self.registry response = render_view_to_response(None, request, 'moo.html') - self.assertEqual(response.body, 'yo') + self.assertEqual(response.body, b'yo') def test_registerView_custom(self): from pyramid import testing @@ -146,7 +146,7 @@ class Test_registerView(TestBase): request = DummyRequest() request.registry = self.registry response = render_view_to_response(None, request, 'moo.html') - self.assertEqual(response.body, '123') + self.assertEqual(response.body, b'123') def test_registerView_with_permission_denying(self): from pyramid import testing @@ -188,7 +188,7 @@ class Test_registerView(TestBase): request = DummyRequest() request.registry = self.registry result = render_view_to_response(None, request, 'moo.html') - self.assertEqual(result.app_iter, ['123']) + self.assertEqual(result.app_iter, [b'123']) class Test_registerAdapter(TestBase): @@ -380,9 +380,10 @@ class TestDummyResource(unittest.TestCase): resource = self._makeOne() resource['abc'] = Dummy() resource['def'] = Dummy() - self.assertEqual(resource.values(), resource.subs.values()) - self.assertEqual(resource.items(), resource.subs.items()) - self.assertEqual(resource.keys(), resource.subs.keys()) + L = list + self.assertEqual(L(resource.values()), L(resource.subs.values())) + self.assertEqual(L(resource.items()), L(resource.subs.items())) + self.assertEqual(L(resource.keys()), L(resource.subs.keys())) self.assertEqual(len(resource), 2) def test_nonzero(self): diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 6231c516b..6abaf403d 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -770,6 +770,7 @@ class QuotePathSegmentTests(unittest.TestCase): self.assertEqual(result, '12345') def test_long(self): + from pyramid.compat import long import sys s = long(sys.maxint + 1) result = self._callFUT(s) -- cgit v1.2.3 From e916390ce0ac464e4d1356a7c33edc9c55c7cb7f Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Sep 2011 22:40:59 -0500 Subject: Backed out syntax changes specific to 2.5. --- pyramid/authentication.py | 4 +--- pyramid/config/util.py | 7 ++----- pyramid/session.py | 4 +--- pyramid/tests/test_config/test_views.py | 13 ++++--------- pyramid/tests/test_router.py | 4 +--- pyramid/tests/test_util.py | 4 +--- pyramid/traversal.py | 4 +--- pyramid/urldispatch.py | 4 +--- 8 files changed, 12 insertions(+), 32 deletions(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index 898cc77a7..2bbe4d191 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -3,7 +3,6 @@ from codecs import utf_8_encode from hashlib import md5 import datetime import re -import sys import time as time_mod import urllib @@ -472,8 +471,7 @@ def parse_ticket(secret, ticket, ip): digest = ticket[:32] try: timestamp = int(ticket[32:40], 16) - except ValueError: - e = sys.exc_info()[1] + except ValueError as e: raise BadTicket('Timestamp is not a hex integer: %s' % e) try: userid, data = ticket[40:].split('!', 1) diff --git a/pyramid/config/util.py b/pyramid/config/util.py index f549b1977..53a390c7e 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -1,5 +1,4 @@ import re -import sys import traceback from pyramid.exceptions import ConfigurationError @@ -112,8 +111,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, if path_info is not None: try: path_info_val = re.compile(path_info) - except re.error: - why = sys.exc_info()[1] + except re.error as why: raise ConfigurationError(why[0]) def path_info_predicate(context, request): return path_info_val.match(request.path_info) is not None @@ -147,8 +145,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, header_name, header_val = header.split(':', 1) try: header_val = re.compile(header_val) - except re.error: - why = sys.exc_info()[1] + except re.error as why: raise ConfigurationError(why[0]) if header_val is None: text = "header %s" % header_name diff --git a/pyramid/session.py b/pyramid/session.py index 7d7edab1b..3a179e2fd 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -2,7 +2,6 @@ from hashlib import sha1 import base64 import binascii import hmac -import sys import time import os @@ -254,9 +253,8 @@ def signed_deserialize(serialized, secret, hmac=hmac): try: input_sig, pickled = (serialized[:40], base64.standard_b64decode(serialized[40:])) - except (binascii.Error, TypeError): + except (binascii.Error, TypeError) as e: # Badly formed data can make base64 die - e = sys.exc_info()[1] raise ValueError('Badly formed base64 data: %s' % e) sig = hmac.new(secret, pickled, sha1).hexdigest() diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index c615c5a9e..0ea9d6cd0 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -1,5 +1,4 @@ import unittest -import sys from pyramid import testing from pyramid.tests.test_config import IDummy @@ -2531,8 +2530,7 @@ class TestViewDeriver(unittest.TestCase): request.url = 'url' try: result(None, request) - except HTTPForbidden: - e = sys.exc_info()[1] + except HTTPForbidden as e: self.assertEqual(e.message, 'Unauthorized: failed permission check') else: # pragma: no cover @@ -2554,8 +2552,7 @@ class TestViewDeriver(unittest.TestCase): request.url = 'url' try: result(None, request) - except HTTPForbidden: - e = sys.exc_info()[1] + except HTTPForbidden as e: self.assertEqual(e.message, 'Unauthorized: myview failed permission check') else: # pragma: no cover @@ -2573,8 +2570,7 @@ class TestViewDeriver(unittest.TestCase): request.method = 'POST' try: result(None, None) - except PredicateMismatch: - e = sys.exc_info()[1] + except PredicateMismatch as e: self.assertEqual(e.detail, 'predicate mismatch for view ') else: # pragma: no cover raise AssertionError @@ -2590,8 +2586,7 @@ class TestViewDeriver(unittest.TestCase): request.method = 'POST' try: result(None, None) - except PredicateMismatch: - e = sys.exc_info()[1] + except PredicateMismatch as e: self.assertEqual(e.detail, 'predicate mismatch for view myview') else: # pragma: no cover raise AssertionError diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 6a1cfd0d2..1bee26e6a 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -1,4 +1,3 @@ -import sys import unittest from pyramid import testing @@ -1205,8 +1204,7 @@ class DummyLogger: def exc_raised(exc, func, *arg, **kw): try: func(*arg, **kw) - except exc: - e = sys.exc_info()[1] + except exc as e: return e else: raise AssertionError('%s not raised' % exc) # pragma: no cover diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py index 2c38314f4..eb165ef69 100644 --- a/pyramid/tests/test_util.py +++ b/pyramid/tests/test_util.py @@ -1,5 +1,4 @@ import unittest -import sys class TestDottedNameResolver(unittest.TestCase): def _makeOne(self, package=None): @@ -10,8 +9,7 @@ class TestDottedNameResolver(unittest.TestCase): from pyramid.exceptions import ConfigurationError try: func(*arg, **kw) - except ConfigurationError: - e = sys.exc_info()[1] + except ConfigurationError as e: return e else: raise AssertionError('Invalid not raised') # pragma: no cover diff --git a/pyramid/traversal.py b/pyramid/traversal.py index de525e503..d586c30d9 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -1,4 +1,3 @@ -import sys import urllib import warnings @@ -484,8 +483,7 @@ def traversal_path(path): segment = urllib.unquote(segment) try: segment = segment.decode('utf-8') - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': continue diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 043203b79..8484fa549 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -1,5 +1,4 @@ import re -import sys from zope.interface import implementer from pyramid.interfaces import IRoutesMapper @@ -141,8 +140,7 @@ def _compile_route(route): encoded = url_unquote(v) try: d[k] = encoded.decode('utf-8') - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: raise URLDecodeError( e.encoding, e.object, e.start, e.end, e.reason ) -- cgit v1.2.3 From 10b4f1c76c13df070224fa6b298b013d03ccddbc Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Sep 2011 23:05:41 -0500 Subject: Removed py25 from tox.ini. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 40711a5f2..58980e805 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py25,py26,py27,jython,pypy,cover + py26,py27,jython,pypy,cover [testenv] commands = -- cgit v1.2.3 From 07ee180bf7561f7a6330c91b6d4833f55328b8f3 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 00:18:24 -0400 Subject: prevent a syntax error (this is not really correct) --- pyramid/authentication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index 2bbe4d191..d75549d36 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -9,6 +9,7 @@ import urllib from zope.interface import implementer from pyramid.compat import long +from pyramid.compat import text_type from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IDebugLogger @@ -548,7 +549,7 @@ class AuthTktCookieHelper(object): userid_type_encoders = { int: ('int', str), long: ('int', str), - unicode: ('b64unicode', lambda x: b64encode(utf_8_encode(x)[0])), + text_type: ('b64unicode', lambda x: b64encode(utf_8_encode(x)[0])), str: ('b64str', lambda x: b64encode(x)), } -- cgit v1.2.3 From 2544cfc1e50ac12a4c4e017bde43770d903c8eb1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Sep 2011 23:27:04 -0500 Subject: Fixed some files to be read as binary. --- pyramid/tests/test_config/test_assets.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index a07753118..1d0e89429 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -163,7 +163,7 @@ class TestOverrideProvider(unittest.TestCase): import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, resource_name)).read() + expected = read_(os.path.join(here, resource_name)) result = provider.get_resource_stream(None, resource_name) self.assertEqual(result.read().replace('\r', ''), expected) @@ -173,7 +173,7 @@ class TestOverrideProvider(unittest.TestCase): import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, resource_name)).read() + expected = read_(os.path.join(here, resource_name)) result = provider.get_resource_string(None, resource_name) self.assertEqual(result.replace('\r', ''), expected) @@ -221,9 +221,10 @@ class TestOverrideProvider(unittest.TestCase): import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, resource_name)).read() + expected = read_(os.path.join(here, resource_name)) result = provider.get_resource_stream(None, resource_name) self.assertEqual(result.read(), expected) + result.close() def test_get_resource_string_override_returns_None(self): overrides = DummyOverrides(None) @@ -233,7 +234,7 @@ class TestOverrideProvider(unittest.TestCase): import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, resource_name)).read() + expected = read_(os.path.join(here, resource_name)) result = provider.get_resource_string(None, resource_name) self.assertEqual(result, expected) @@ -419,7 +420,7 @@ class TestPackageOverrides(unittest.TestCase): po = self._makeOne(package) po.overrides= overrides here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, 'test_assets.py')).read() + expected = read_(os.path.join(here, 'test_assets.py')) self.assertEqual(po.get_stream('whatever').read().replace('\r', ''), expected) @@ -439,7 +440,7 @@ class TestPackageOverrides(unittest.TestCase): po = self._makeOne(package) po.overrides= overrides here = os.path.dirname(os.path.abspath(__file__)) - expected = open(os.path.join(here, 'test_assets.py')).read() + expected = read_(os.path.join(here, 'test_assets.py')) self.assertEqual(po.get_string('whatever').replace('\r', ''), expected) def test_get_string_file_doesnt_exist(self): @@ -587,3 +588,8 @@ class DummyUnderOverride: self.override_package = override_package self.override_prefix = override_prefix +def read_(src): + with open(src, 'rb') as f: + contents = f.read() + return contents + -- cgit v1.2.3 From a83e10d04ad728f8145abc03e13dcd6c6495ae95 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Sep 2011 23:36:35 -0500 Subject: Fixed an open resource error. --- pyramid/tests/test_config/test_assets.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 1d0e89429..73f0a12ad 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -164,8 +164,8 @@ class TestOverrideProvider(unittest.TestCase): provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, resource_name)) - result = provider.get_resource_stream(None, resource_name) - self.assertEqual(result.read().replace('\r', ''), expected) + with provider.get_resource_stream(None, resource_name) as result: + self.assertEqual(result.read().replace('\r', ''), expected) def test_get_resource_string_no_overrides(self): import os @@ -222,9 +222,8 @@ class TestOverrideProvider(unittest.TestCase): provider = self._makeOne(pyramid.tests.test_config) here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, resource_name)) - result = provider.get_resource_stream(None, resource_name) - self.assertEqual(result.read(), expected) - result.close() + with provider.get_resource_stream(None, resource_name) as result: + self.assertEqual(result.read(), expected) def test_get_resource_string_override_returns_None(self): overrides = DummyOverrides(None) @@ -278,8 +277,8 @@ class TestOverrideProvider(unittest.TestCase): import pyramid.tests.test_config self._registerOverrides(overrides) provider = self._makeOne(pyramid.tests.test_config) - result = provider.get_resource_stream(None, 'test_assets.py') - self.assertEqual(result, 'value') + with provider.get_resource_stream(None, 'test_assets.py') as result: + self.assertEqual(result, 'value') def test_get_resource_string_override_returns_value(self): overrides = DummyOverrides('value') @@ -421,8 +420,9 @@ class TestPackageOverrides(unittest.TestCase): po.overrides= overrides here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, 'test_assets.py')) - self.assertEqual(po.get_stream('whatever').read().replace('\r', ''), - expected) + with po.get_stream('whatever') as stream: + self.assertEqual(stream.read().replace('\r', ''), + expected) def test_get_stream_file_doesnt_exist(self): overrides = [ DummyOverride(None), DummyOverride( -- cgit v1.2.3 From 2029b2fe9c3f1ee0e15348a4e5ad8ae19cff8d39 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 04:42:46 -0400 Subject: only self-loathing makes me continue --- pyramid/compat.py | 4 ++++ pyramid/config/views.py | 7 +++++-- pyramid/tests/test_config/test_assets.py | 7 ++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index a03fc893d..64648911e 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -196,3 +196,7 @@ else: def is_nonstr_iter(v): return hasattr(v, '__iter__') +if PY3: # pragma: no cover + im_func = '__func__' +else: + im_func = 'im_func' diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 51f13f69f..e186d2430 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -28,6 +28,7 @@ from pyramid.interfaces import PHASE1_CONFIG from pyramid import renderers from pyramid.compat import string_types from pyramid.compat import urlparse +from pyramid.compat import im_func from pyramid.exceptions import ConfigurationError from pyramid.exceptions import PredicateMismatch from pyramid.httpexceptions import HTTPForbidden @@ -417,6 +418,7 @@ class DefaultViewMapper(object): return _attr_view def requestonly(view, attr=None): + ismethod = False if attr is None: attr = '__call__' if inspect.isfunction(view): @@ -426,6 +428,7 @@ def requestonly(view, attr=None): fn = view.__init__ except AttributeError: return False + ismethod = hasattr(fn, '__call__') else: try: fn = getattr(view, attr) @@ -439,8 +442,8 @@ def requestonly(view, attr=None): args = argspec[0] - if hasattr(fn, 'im_func'): - # it's an instance method + if hasattr(fn, im_func) or ismethod: + # it's an instance method (or unbound method on py2) if not args: return False args = args[1:] diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 73f0a12ad..876a921b4 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -273,12 +273,13 @@ class TestOverrideProvider(unittest.TestCase): self.assertEqual(result, 'value') def test_get_resource_stream_override_returns_value(self): - overrides = DummyOverrides('value') + from io import StringIO + overrides = DummyOverrides(StringIO('value')) import pyramid.tests.test_config self._registerOverrides(overrides) provider = self._makeOne(pyramid.tests.test_config) - with provider.get_resource_stream(None, 'test_assets.py') as result: - self.assertEqual(result, 'value') + with provider.get_resource_stream(None, 'test_assets.py') as stream: + self.assertEqual(stream.getvalue(), 'value') def test_get_resource_string_override_returns_value(self): overrides = DummyOverrides('value') -- cgit v1.2.3 From 8e606da0d09f7e99baa08b91fe97dba4b5b5d4b2 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 06:28:50 -0400 Subject: more rusty knife in the eye changes --- pyramid/authentication.py | 26 +++---- pyramid/compat.py | 10 +++ pyramid/config/tweens.py | 3 +- pyramid/config/util.py | 12 ++- pyramid/config/views.py | 6 +- pyramid/encode.py | 18 +++-- pyramid/exceptions.py | 5 +- pyramid/httpexceptions.py | 13 +++- pyramid/i18n.py | 2 +- pyramid/mako_templating.py | 14 ++-- pyramid/paster.py | 27 ++++--- pyramid/renderers.py | 3 +- pyramid/request.py | 14 ++-- pyramid/scaffolds/__init__.py | 4 +- pyramid/session.py | 3 +- pyramid/settings.py | 5 +- pyramid/static.py | 2 + pyramid/tests/test_authentication.py | 13 +--- pyramid/tests/test_chameleon_text.py | 2 +- pyramid/tests/test_chameleon_zpt.py | 7 +- pyramid/tests/test_config/test_init.py | 10 +-- pyramid/tests/test_config/test_views.py | 20 ++--- pyramid/tests/test_encode.py | 7 +- pyramid/tests/test_httpexceptions.py | 38 +++++----- pyramid/tests/test_integration.py | 126 ++++++++++++++++---------------- pyramid/tests/test_mako_templating.py | 9 ++- pyramid/tests/test_renderers.py | 27 +++---- pyramid/tests/test_request.py | 8 +- pyramid/tests/test_router.py | 8 +- pyramid/tests/test_settings.py | 2 +- pyramid/tests/test_static.py | 28 +++---- pyramid/tests/test_testing.py | 6 +- pyramid/tests/test_traversal.py | 17 +++-- pyramid/tests/test_url.py | 10 +-- pyramid/tests/test_util.py | 8 +- pyramid/traversal.py | 23 +++--- pyramid/url.py | 10 ++- pyramid/urldispatch.py | 9 ++- 38 files changed, 299 insertions(+), 256 deletions(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index d75549d36..a84983447 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -1,15 +1,18 @@ from codecs import utf_8_decode from codecs import utf_8_encode from hashlib import md5 +import base64 import datetime import re import time as time_mod -import urllib from zope.interface import implementer from pyramid.compat import long from pyramid.compat import text_type +from pyramid.compat import url_unquote +from pyramid.compat import url_quote +from pyramid.compat import bytes_ from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IDebugLogger @@ -386,10 +389,10 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): return self.cookie.forget(request) def b64encode(v): - return v.encode('base64').strip().replace('\n', '') + return base64.b64encode(v).strip().replace('\n', '') def b64decode(v): - return v.decode('base64') + return base64.b64decode(v) # this class licensed under the MIT license (stolen from Paste) class AuthTicket(object): @@ -443,7 +446,7 @@ class AuthTicket(object): def cookie_value(self): v = '%s%08x%s!' % (self.digest(), int(self.time), - urllib.quote(self.userid)) + url_quote(self.userid)) if self.tokens: v += self.tokens + '!' v += self.user_data @@ -478,7 +481,7 @@ def parse_ticket(secret, ticket, ip): userid, data = ticket[40:].split('!', 1) except ValueError: raise BadTicket('userid is not followed by !') - userid = urllib.unquote(userid) + userid = url_unquote(userid) if '!' in data: tokens, user_data = data.split('!', 1) else: # pragma: no cover (never generated) @@ -499,10 +502,10 @@ def parse_ticket(secret, ticket, ip): # this function licensed under the MIT license (stolen from Paste) def calculate_digest(ip, timestamp, secret, userid, tokens, user_data): - secret = maybe_encode(secret) - userid = maybe_encode(userid) - tokens = maybe_encode(tokens) - user_data = maybe_encode(user_data) + secret = bytes_(secret, 'utf-8') + userid = bytes_(userid, 'utf-8') + tokens = bytes_(tokens, 'utf-8') + user_data = bytes_(user_data, 'utf-8') digest0 = md5( encode_ip_timestamp(ip, timestamp) + secret + userid + '\0' + tokens + '\0' + user_data).hexdigest() @@ -520,11 +523,6 @@ def encode_ip_timestamp(ip, timestamp): ts_chars = ''.join(map(chr, ts)) return ip_chars + ts_chars -def maybe_encode(s, encoding='utf8'): - if isinstance(s, unicode): - s = s.encode(encoding) - return s - EXPIRE = object() class AuthTktCookieHelper(object): diff --git a/pyramid/compat.py b/pyramid/compat.py index 64648911e..a6f7f025e 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -169,11 +169,15 @@ if PY3: # pragma: no cover return d.items() def itervalues_(d): return d.values() + def iterkeys_(d): + return d.keys() else: def iteritems_(d): return d.iteritems() def itervalues_(d): return d.itervalues() + def iterkeys_(d): + return d.iterkeys() if PY3: @@ -200,3 +204,9 @@ if PY3: # pragma: no cover im_func = '__func__' else: im_func = 'im_func' + +try: + import configparser +except ImportError: + import ConfigParser + configparser = ConfigParser diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py index c7d50248f..3c7ee384f 100644 --- a/pyramid/config/tweens.py +++ b/pyramid/config/tweens.py @@ -4,6 +4,7 @@ from pyramid.interfaces import ITweens from pyramid.compat import string_types from pyramid.compat import is_nonstr_iter +from pyramid.compat import string_types from pyramid.exceptions import ConfigurationError from pyramid.tweens import excview_tween_factory from pyramid.tweens import MAIN, INGRESS, EXCVIEW @@ -98,7 +99,7 @@ class TweensConfiguratorMixin(object): @action_method def _add_tween(self, tween_factory, under=None, over=None, explicit=False): - if not isinstance(tween_factory, basestring): + if not isinstance(tween_factory, string_types): raise ConfigurationError( 'The "tween_factory" argument to add_tween must be a ' 'dotted name to a globally importable object, not %r' % diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 53a390c7e..7980a78e3 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -1,6 +1,8 @@ import re import traceback +from pyramid.compat import string_types +from pyramid.compat import bytes_ from pyramid.exceptions import ConfigurationError from pyramid.traversal import find_interface from pyramid.traversal import traversal_path @@ -177,7 +179,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, containment_predicate.__text__ = "containment = %s" % containment weights.append(1 << 7) predicates.append(containment_predicate) - h.update('containment:%r' % hash(containment)) + h.update('containment:%r' % hash_(containment)) if request_type is not None: def request_type_predicate(context, request): @@ -186,10 +188,10 @@ def make_predicates(xhr=None, request_method=None, path_info=None, request_type_predicate.__text__ = text % request_type weights.append(1 << 8) predicates.append(request_type_predicate) - h.update('request_type:%r' % hash(request_type)) + h.update('request_type:%r' % hash_(request_type)) if match_param is not None: - if isinstance(match_param, basestring): + if isinstance(match_param, string_types): match_param, match_param_val = match_param.split('=', 1) match_param = {match_param: match_param_val} text = "match_param %s" % match_param @@ -222,7 +224,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, # functions for custom predicates, so that the hash output # of predicate instances which are "logically the same" # may compare equal. - h.update('custom%s:%r' % (num, hash(predicate))) + h.update('custom%s:%r' % (num, hash_(predicate))) weights.append(1 << 10) if traverse is not None: @@ -259,3 +261,5 @@ def as_sorted_tuple(val): val = tuple(sorted(val)) return val +def hash_(v): + return bytes_(hash(v)) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index e186d2430..326aa801e 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1153,7 +1153,7 @@ class ViewsConfiguratorMixin(object): mapper=None, http_cache=None): view = self.maybe_dotted(view) mapper = self.maybe_dotted(mapper) - if isinstance(renderer, basestring): + if isinstance(renderer, string_types): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry = self.registry) @@ -1211,7 +1211,7 @@ class ViewsConfiguratorMixin(object): The ``wrapper`` argument should be the name of another view which will wrap this view when rendered (see the ``add_view`` method's ``wrapper`` argument for a description).""" - if isinstance(renderer, basestring): + if isinstance(renderer, string_types): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry = self.registry) @@ -1253,7 +1253,7 @@ class ViewsConfiguratorMixin(object): which will wrap this view when rendered (see the ``add_view`` method's ``wrapper`` argument for a description). """ - if isinstance(renderer, basestring): + if isinstance(renderer, string_types): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry=self.registry) diff --git a/pyramid/encode.py b/pyramid/encode.py index 826e6a662..ee574a0eb 100644 --- a/pyramid/encode.py +++ b/pyramid/encode.py @@ -1,5 +1,9 @@ import re +from pyramid.compat import text_type +from pyramid.compat import native_ +from pyramid.compat import is_nonstr_iter + always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789' '_.-') @@ -88,19 +92,19 @@ def urlencode(query, doseq=True): prefix = '' for (k, v) in query: - if k.__class__ is unicode: - k = k.encode('utf-8') + if k.__class__ is text_type: + k = native_(k, 'utf-8') k = quote_plus(str(k)) - if hasattr(v, '__iter__'): + if is_nonstr_iter(v): for x in v: - if x.__class__ is unicode: - x = x.encode('utf-8') + if x.__class__ is text_type: + x = native_(x, 'utf-8') x = quote_plus(str(x)) result += '%s%s=%s' % (prefix, k, x) prefix = '&' else: - if v.__class__ is unicode: - v = v.encode('utf-8') + if v.__class__ is text_type: + v = native_(v, 'utf-8') v = quote_plus(str(v)) result += '%s%s=%s' % (prefix, k, v) prefix = '&' diff --git a/pyramid/exceptions.py b/pyramid/exceptions.py index cd234adca..ff598fe2d 100644 --- a/pyramid/exceptions.py +++ b/pyramid/exceptions.py @@ -39,12 +39,11 @@ class ConfigurationConflictError(ConfigurationError): def __str__(self): r = ["Conflicting configuration actions"] - items = self._conflicts.items() - items.sort() + items = sorted(self._conflicts.items()) for discriminator, infos in items: r.append(" For: %s" % (discriminator, )) for info in infos: - for line in unicode(info).rstrip().split(CR): + for line in str(info).rstrip().split(CR): r.append(" "+line) return CR.join(r) diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py index 46bc1890c..4dbca7021 100644 --- a/pyramid/httpexceptions.py +++ b/pyramid/httpexceptions.py @@ -131,15 +131,20 @@ from webob import html_escape as _html_escape from pyramid.interfaces import IExceptionResponse from pyramid.response import Response from pyramid.compat import class_types +from pyramid.compat import text_type +from pyramid.compat import binary_type +from pyramid.compat import text_ def _no_escape(value): if value is None: return '' - if not isinstance(value, basestring): + if not isinstance(value, text_type): if hasattr(value, '__unicode__'): - value = unicode(value) + value = value.__unicode__() + if isinstance(value, binary_type): + value = text_(value, 'utf-8') else: - value = str(value) + value = text_type(value) return value class HTTPException(Exception): # bw compat @@ -259,7 +264,7 @@ ${body}''') args[k.lower()] = escape(v) body = body_tmpl.substitute(args) page = page_template.substitute(status=self.status, body=body) - if isinstance(page, unicode): + if isinstance(page, text_type): page = page.encode(self.charset) self.app_iter = [page] self.body = page diff --git a/pyramid/i18n.py b/pyramid/i18n.py index f16aeb378..040e581b5 100644 --- a/pyramid/i18n.py +++ b/pyramid/i18n.py @@ -231,7 +231,7 @@ class Translations(gettext.GNUTranslations, object): # this domain; see https://github.com/Pylons/pyramid/issues/235 self.plural = lambda n: int(n != 1) gettext.GNUTranslations.__init__(self, fp=fileobj) - self.files = filter(None, [getattr(fileobj, 'name', None)]) + self.files = list(filter(None, [getattr(fileobj, 'name', None)])) self.domain = domain self._domains = {} diff --git a/pyramid/mako_templating.py b/pyramid/mako_templating.py index a12e72b86..29be339f2 100644 --- a/pyramid/mako_templating.py +++ b/pyramid/mako_templating.py @@ -7,6 +7,7 @@ from zope.interface import Interface from pyramid.asset import resolve_asset_spec from pyramid.asset import abspath_from_asset_spec +from pyramid.compat import is_nonstr_iter from pyramid.exceptions import ConfigurationError from pyramid.interfaces import ITemplateRenderer from pyramid.settings import asbool @@ -74,8 +75,8 @@ def renderer_factory(info): if directories is None: raise ConfigurationError( 'Mako template used without a ``mako.directories`` setting') - if not hasattr(directories, '__iter__'): - directories = filter(None, directories.splitlines()) + if not is_nonstr_iter(directories): + directories = list(filter(None, directories.splitlines())) directories = [ abspath_from_asset_spec(d) for d in directories ] if module_directory is not None: module_directory = abspath_from_asset_spec(module_directory) @@ -83,11 +84,12 @@ def renderer_factory(info): dotted = DottedNameResolver(info.package) error_handler = dotted.maybe_resolve(error_handler) if default_filters is not None: - if not hasattr(default_filters, '__iter__'): - default_filters = filter(None, default_filters.splitlines()) + if not is_nonstr_iter(default_filters): + default_filters = list(filter( + None, default_filters.splitlines())) if imports is not None: - if not hasattr(imports, '__iter__'): - imports = filter(None, imports.splitlines()) + if not is_nonstr_iter(imports): + imports = list(filter(None, imports.splitlines())) strict_undefined = asbool(strict_undefined) if preprocessor is not None: dotted = DottedNameResolver(info.package) diff --git a/pyramid/paster.py b/pyramid/paster.py index 4fc1812ca..0085c279e 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -1,19 +1,28 @@ -import ConfigParser import os import sys from code import interact import zope.deprecation -from paste.deploy import loadapp -from paste.script.command import Command +try: + from paste.deploy import loadapp +except ImportError: # pragma: no cover + def loadapp(*arg, **kw): + raise NotImplementedError + +try: + from paste.script.command import Command +except ImportError: + class Command: + pass from pyramid.interfaces import IMultiView from pyramid.interfaces import ITweens +from pyramid.compat import print_ +from pyramid.compat import configparser from pyramid.scripting import prepare from pyramid.util import DottedNameResolver - from pyramid.tweens import MAIN from pyramid.tweens import INGRESS @@ -136,7 +145,7 @@ class PShellCommand(PCommand): "option will override the 'setup' key in the " "[pshell] ini section.")) - ConfigParser = ConfigParser.ConfigParser # testing + ConfigParser = configparser.ConfigParser # testing loaded_objects = {} object_help = {} @@ -147,7 +156,7 @@ class PShellCommand(PCommand): config.read(filename) try: items = config.items('pshell') - except ConfigParser.NoSectionError: + except configparser.NoSectionError: return resolver = DottedNameResolver(None) @@ -299,7 +308,7 @@ class PRoutesCommand(PCommand): return config.get_routes_mapper() def out(self, msg): # pragma: no cover - print msg + print_(msg) def command(self): from pyramid.interfaces import IRouteRequest @@ -358,7 +367,7 @@ class PViewsCommand(PCommand): parser = Command.standard_parser(simulate=True) def out(self, msg): # pragma: no cover - print msg + print_(msg) def _find_multi_routes(self, mapper, request): infos = [] @@ -604,7 +613,7 @@ class PTweensCommand(PCommand): return config.registry.queryUtility(ITweens) def out(self, msg): # pragma: no cover - print msg + print_(msg) def show_chain(self, chain): fmt = '%-10s %-65s' diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 04208fcdc..2d420f67a 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -16,6 +16,7 @@ from pyramid.interfaces import IRendererInfo from pyramid.asset import asset_spec_from_abspath from pyramid.compat import json from pyramid.compat import string_types +from pyramid.compat import text_type from pyramid.compat import native_ from pyramid.decorator import reify from pyramid.events import BeforeRender @@ -439,7 +440,7 @@ class RendererHelper(object): if result is None: result = '' - if isinstance(result, unicode): + if isinstance(result, text_type): response.unicode_body = result else: response.body = result diff --git a/pyramid/request.py b/pyramid/request.py index 8188eecf1..fda233388 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -11,6 +11,8 @@ from pyramid.interfaces import ISessionFactory from pyramid.interfaces import IResponseFactory from pyramid.compat import json +from pyramid.compat import native_ +from pyramid.compat import iterkeys_, itervalues_, iteritems_ from pyramid.exceptions import ConfigurationError from pyramid.decorator import reify from pyramid.response import Response @@ -64,15 +66,15 @@ class DeprecatedRequestMethodsMixin(object): @deprecate(dictlike) def iteritems(self): - return self.environ.iteritems() + return iteritems_(self.environ) @deprecate(dictlike) def iterkeys(self): - return self.environ.iterkeys() + return iterkeys_(self.environ) @deprecate(dictlike) def itervalues(self): - return self.environ.itervalues() + return itervalues_(self.environ) @deprecate(dictlike) def keys(self): @@ -399,12 +401,12 @@ def call_app_with_subpath_as_path_info(request, app): environ = request.environ script_name = environ.get('SCRIPT_NAME', '') path_info = environ.get('PATH_INFO', '/') - subpath = list(getattr(request, 'subpath', ())) + subpath = getattr(request, 'subpath', ()) new_script_name = '' # compute new_path_info - new_path_info = '/' + '/'.join([x.encode('utf-8') for x in subpath]) + new_path_info = '/' + '/'.join([native_(x, 'utf-8') for x in subpath]) if new_path_info != '/': # don't want a sole double-slash if path_info != '/': # if orig path_info is '/', we're already done @@ -422,7 +424,7 @@ def call_app_with_subpath_as_path_info(request, app): break el = workback.pop() if el: - tmp.insert(0, el.decode('utf-8')) + tmp.insert(0, native_(el, 'utf-8')) # strip all trailing slashes from workback to avoid appending undue slashes # to end of script_name diff --git a/pyramid/scaffolds/__init__.py b/pyramid/scaffolds/__init__.py index ef93a53c7..e00a9f83b 100644 --- a/pyramid/scaffolds/__init__.py +++ b/pyramid/scaffolds/__init__.py @@ -3,13 +3,13 @@ import os try: from paste.script.templates import Template except ImportError: - class Template(object): + class Template: pass try: from paste.util.template import paste_script_template_renderer except ImportError: - def paste_script_template_renderer(self): + def paste_script_template_renderer(): pass class PyramidTemplate(Template): diff --git a/pyramid/session.py b/pyramid/session.py index 3a179e2fd..cd685e51c 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -9,6 +9,7 @@ from zope.interface import implementer from pyramid.compat import pickle from pyramid.compat import PY3 +from pyramid.compat import text_ from pyramid.interfaces import ISession def manage_accessed(wrapped): @@ -181,7 +182,7 @@ def UnencryptedCookieSessionFactoryConfig( # CSRF API methods @manage_accessed def new_csrf_token(self): - token = os.urandom(20).encode('hex') + token = text_(binascii.hexlify(os.urandom(20))) self['_csrft_'] = token return token diff --git a/pyramid/settings.py b/pyramid/settings.py index 3c376c4a9..de91042eb 100644 --- a/pyramid/settings.py +++ b/pyramid/settings.py @@ -1,6 +1,7 @@ from zope.deprecation import deprecated from pyramid.threadlocal import get_current_registry +from pyramid.compat import string_types def get_settings(): """ @@ -39,9 +40,9 @@ def asbool(s): return s.lower() in ('t', 'true', 'y', 'yes', 'on', '1') def aslist_cronly(value): - if isinstance(value, basestring): + if isinstance(value, string_types): value = filter(None, [x.strip() for x in value.splitlines()]) - return value + return list(value) def aslist(value): values = aslist_cronly(value) diff --git a/pyramid/static.py b/pyramid/static.py index 0ab4a0c79..edb20b54f 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -75,6 +75,8 @@ class _FileIter(object): raise StopIteration return data + __next__ = next # py3 + def close(self): self.file.close() diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index 37c179caf..7f64af705 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -586,7 +586,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): result = helper.identify(request) self.assertEqual(len(result), 4) self.assertEqual(result['tokens'], ()) - self.assertEqual(result['userid'], unicode('\xc3\xa9ncoded', 'utf-8')) + self.assertEqual(result['userid'], text_('\xc3\xa9ncoded', 'utf-8')) self.assertEqual(result['userdata'], 'userid_type:b64unicode') self.assertEqual(result['timestamp'], 0) environ = request.environ @@ -856,7 +856,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): def test_remember_unicode_userid(self): helper = self._makeOne('secret') request = self._makeRequest() - userid = unicode('\xc2\xa9', 'utf-8') + userid = text_('\xc2\xa9', 'utf-8') result = helper.remember(request, userid) values = self._parseHeaders(result) self.assertEqual(len(result), 3) @@ -1087,15 +1087,6 @@ class TestSessionAuthenticationPolicy(unittest.TestCase): self.assertEqual(request.session.get('userid'), None) self.assertEqual(result, []) -class Test_maybe_encode(unittest.TestCase): - def _callFUT(self, s, encoding='utf-8'): - from pyramid.authentication import maybe_encode - return maybe_encode(s, encoding) - - def test_unicode(self): - result = self._callFUT(text_('abc')) - self.assertEqual(result, text_('abc')) - class DummyContext: pass diff --git a/pyramid/tests/test_chameleon_text.py b/pyramid/tests/test_chameleon_text.py index 213f25f51..cae52c2f4 100644 --- a/pyramid/tests/test_chameleon_text.py +++ b/pyramid/tests/test_chameleon_text.py @@ -149,7 +149,7 @@ class RenderTemplateToResponseTests(Base, unittest.TestCase): result = self._callFUT(minimal) from webob import Response self.assertTrue(isinstance(result, Response)) - self.assertEqual(result.app_iter, ['Hello.\n']) + self.assertEqual(result.app_iter, [b'Hello.\n']) self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) diff --git a/pyramid/tests/test_chameleon_zpt.py b/pyramid/tests/test_chameleon_zpt.py index 84eaedcf4..6a38bd329 100644 --- a/pyramid/tests/test_chameleon_zpt.py +++ b/pyramid/tests/test_chameleon_zpt.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import skip_on from pyramid import testing +from pyramid.compat import text_type class Base(object): def setUp(self): @@ -51,7 +52,7 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne(minimal, lookup) result = instance({}, {}) - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result.rstrip('\n'), '
\n
') @@ -126,7 +127,7 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne(minimal, lookup) result = instance.implementation()() - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result.rstrip('\n'), '
\n
') @@ -140,7 +141,7 @@ class RenderTemplateTests(Base, unittest.TestCase): def test_it(self): minimal = self._getTemplatePath('minimal.pt') result = self._callFUT(minimal) - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result.rstrip('\n'), '
\n
') diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 6b5ea06b3..0decd28ad 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -915,7 +915,7 @@ pyramid.tests.test_config.dummy_include2""", c.scan(selfscan) try: c.commit() - except ConfigurationConflictError, why: + except ConfigurationConflictError as why: def scanconflicts(e): conflicts = e._conflicts.values() for conflict in conflicts: @@ -985,7 +985,7 @@ pyramid.tests.test_config.dummy_include2""", config.include(includeme2) try: config.commit() - except ConfigurationConflictError, why: + except ConfigurationConflictError as why: c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'includeme1') self.assertEqual(c2, 'includeme2') @@ -1029,7 +1029,7 @@ pyramid.tests.test_config.dummy_include2""", config.set_notfound_view(view2) try: config.commit() - except ConfigurationConflictError, why: + except ConfigurationConflictError as why: c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'test_conflict_set_notfound_view') self.assertEqual(c2, 'test_conflict_set_notfound_view') @@ -1044,7 +1044,7 @@ pyramid.tests.test_config.dummy_include2""", config.set_forbidden_view(view2) try: config.commit() - except ConfigurationConflictError, why: + except ConfigurationConflictError as why: c1, c2 = _conflictFunctions(why) self.assertEqual(c1, 'test_conflict_set_forbidden_view') self.assertEqual(c2, 'test_conflict_set_forbidden_view') @@ -1284,7 +1284,7 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase): config.add_route('a', '/a', view=view2) try: config.commit() - except ConfigurationConflictError, why: + except ConfigurationConflictError as why: c1, c2, c3, c4, c5, c6 = _conflictFunctions(why) self.assertEqual(c1, 'test_conflict_route_with_view') self.assertEqual(c2, 'test_conflict_route_with_view') diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 0ea9d6cd0..eceea94d5 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -103,7 +103,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): self._registerRenderer(config, name='dummy') config.add_view(renderer='dummy') view = self._getViewCallable(config) - self.assertTrue('Hello!' in view(None, None).body) + self.assertTrue(b'Hello!' in view(None, None).body) def test_add_view_wrapped_view_is_decorated(self): def view(request): # request-only wrapper @@ -891,7 +891,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): wrapper = self._getViewCallable(config) request = self._makeRequest(config) result = wrapper(None, request) - self.assertEqual(result.body, 'Hello!') + self.assertEqual(result.body, b'Hello!') settings = config.registry.queryUtility(ISettings) result = renderer.info self.assertEqual(result.registry, config.registry) @@ -919,7 +919,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): wrapper = self._getViewCallable(config) request = self._makeRequest(config) result = wrapper(None, request) - self.assertEqual(result.body, 'moo') + self.assertEqual(result.body, b'moo') def test_add_view_with_template_renderer_no_callable(self): from pyramid.tests import test_config @@ -931,7 +931,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): wrapper = self._getViewCallable(config) request = self._makeRequest(config) result = wrapper(None, request) - self.assertEqual(result.body, 'Hello!') + self.assertEqual(result.body, b'Hello!') settings = config.registry.queryUtility(ISettings) result = renderer.info self.assertEqual(result.registry, config.registry) @@ -1392,7 +1392,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): return 'OK' result = config.derive_view(view) self.assertFalse(result is view) - self.assertEqual(result(None, None).body, 'moo') + self.assertEqual(result(None, None).body, b'moo') def test_derive_view_with_default_renderer_with_explicit_renderer(self): class moo(object): pass @@ -1410,7 +1410,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): result = config.derive_view(view, renderer='foo') self.assertFalse(result is view) request = self._makeRequest(config) - self.assertEqual(result(None, request).body, 'foo') + self.assertEqual(result(None, request).body, b'foo') def test_add_static_view_here_no_utility_registered(self): from pyramid.renderers import null_renderer @@ -1545,7 +1545,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): result = view(None, request) finally: config.end() - self.assertTrue('div' in result.body) + self.assertTrue(b'div' in result.body) @testing.skip_on('java') def test_set_forbidden_view_with_renderer(self): @@ -1566,7 +1566,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): result = view(None, request) finally: config.end() - self.assertTrue('div' in result.body) + self.assertTrue(b'div' in result.body) def test_set_view_mapper(self): from pyramid.interfaces import IViewMapperFactory @@ -2110,7 +2110,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.override_renderer = 'moo' context = testing.DummyResource() - self.assertEqual(result(context, request).body, 'moo') + self.assertEqual(result(context, request).body, b'moo') def test_requestonly_function_with_renderer_request_has_view(self): response = DummyResponse() @@ -2666,7 +2666,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(inner_view.__doc__, result.__doc__) request = self._makeRequest() response = result(None, request) - self.assertEqual(response.body, 'outer OK') + self.assertEqual(response.body, b'outer OK') def test_with_wrapper_viewname_notfound(self): from pyramid.response import Response diff --git a/pyramid/tests/test_encode.py b/pyramid/tests/test_encode.py index 741a24393..738efeea2 100644 --- a/pyramid/tests/test_encode.py +++ b/pyramid/tests/test_encode.py @@ -1,4 +1,5 @@ import unittest +from pyramid.compat import text_ class UrlEncodeTests(unittest.TestCase): def _callFUT(self, query, doseq=False): @@ -10,17 +11,17 @@ class UrlEncodeTests(unittest.TestCase): self.assertEqual(result, 'a=1&b=2') def test_unicode_key(self): - la = unicode('LaPe\xc3\xb1a', 'utf-8') + la = text_('LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([(la, 1), ('b',2)]) self.assertEqual(result, 'LaPe%C3%B1a=1&b=2') def test_unicode_val_single(self): - la = unicode('LaPe\xc3\xb1a', 'utf-8') + la = text_('LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([('a', la), ('b',2)]) self.assertEqual(result, 'a=LaPe%C3%B1a&b=2') def test_unicode_val_multiple(self): - la = [unicode('LaPe\xc3\xb1a', 'utf-8')] * 2 + la = [text_('LaPe\xc3\xb1a', 'utf-8')] * 2 result = self._callFUT([('a', la), ('b',2)], doseq=True) self.assertEqual(result, 'a=LaPe%C3%B1a&a=LaPe%C3%B1a&b=2') diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index 6a3ea7367..60c97b5b4 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -125,7 +125,7 @@ class TestWSGIHTTPException(unittest.TestCase): self.assertEqual(exc.content_length, None) def test_ctor_with_body_doesnt_set_default_app_iter(self): - exc = self._makeOne(body='123') + exc = self._makeOne(body=b'123') self.assertEqual(exc.app_iter, [b'123']) def test_ctor_with_unicode_body_doesnt_set_default_app_iter(self): @@ -143,10 +143,10 @@ class TestWSGIHTTPException(unittest.TestCase): environ['HTTP_ACCEPT'] = 'text/html' start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] - self.assertTrue(body.startswith('' in body) + self.assertTrue(b'' in body) def test__default_app_iter_with_comment_html2(self): cls = self._getTargetSubclass() @@ -233,7 +233,7 @@ class TestWSGIHTTPException(unittest.TestCase): environ['HTTP_ACCEPT'] = 'text/html' start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] - self.assertTrue('' in body) + self.assertTrue(b'' in body) def test_custom_body_template(self): cls = self._getTargetSubclass() @@ -241,7 +241,7 @@ class TestWSGIHTTPException(unittest.TestCase): environ = _makeEnviron() start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] - self.assertEqual(body, '200 OK\n\nGET') + self.assertEqual(body, b'200 OK\n\nGET') def test_custom_body_template_with_custom_variable_doesnt_choke(self): cls = self._getTargetSubclass() @@ -252,16 +252,16 @@ class TestWSGIHTTPException(unittest.TestCase): environ['gardentheory.user'] = Choke() start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] - self.assertEqual(body, '200 OK\n\nGET') + self.assertEqual(body, b'200 OK\n\nGET') def test_body_template_unicode(self): cls = self._getTargetSubclass() - la = unicode('/La Pe\xc3\xb1a', 'utf-8') + la = text_('/La Pe\xc3\xb1a', 'utf-8') environ = _makeEnviron(unicodeval=la) exc = cls(body_template='${unicodeval}') start_response = DummyStartResponse() body = list(exc(environ, start_response))[0] - self.assertEqual(body, '200 OK\n\n/La Pe\xc3\xb1a') + self.assertEqual(body, b'200 OK\n\n/La Pe\xc3\xb1a') class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): def _doit(self, content_type): @@ -310,8 +310,8 @@ class Test_HTTPMove(unittest.TestCase): start_response = DummyStartResponse() app_iter = exc(environ, start_response) self.assertEqual(app_iter[0], - ('None None\n\nThe resource has been moved to foo; ' - 'you should be redirected automatically.\n\n')) + (b'None None\n\nThe resource has been moved to foo; ' + b'you should be redirected automatically.\n\n')) class TestHTTPForbidden(unittest.TestCase): def _makeOne(self, *arg, **kw): @@ -337,8 +337,8 @@ class TestHTTPMethodNotAllowed(unittest.TestCase): start_response = DummyStartResponse() app_iter = exc(environ, start_response) self.assertEqual(app_iter[0], - ('405 Method Not Allowed\n\nThe method GET is not ' - 'allowed for this resource. \n\n\n')) + (b'405 Method Not Allowed\n\nThe method GET is not ' + b'allowed for this resource. \n\n\n')) class DummyRequest(object): diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 40f1adf14..9db03c28b 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -66,7 +66,7 @@ class TestStaticAppBase(IntegrationBase): def _assertBody(self, body, filename): self.assertEqual( body.replace('\r', ''), - open(filename, 'r').read() + open(filename, 'rb').read() ) def test_basic(self): @@ -100,7 +100,7 @@ class TestStaticAppBase(IntegrationBase): self.testapp.extra_environ = { 'HTTP_IF_MODIFIED_SINCE':httpdate(pow(2, 32)-1)} res = self.testapp.get('/minimal.pt', status=304) - self.assertEqual(res.body, '') + self.assertEqual(res.body, b'') def test_file_in_subdir(self): fn = os.path.join(here, 'fixtures/static/index.html') @@ -130,12 +130,12 @@ class TestStaticAppBase(IntegrationBase): def test_range_inclusive(self): self.testapp.extra_environ = {'HTTP_RANGE':'bytes=1-2'} res = self.testapp.get('/static/index.html', status=206) - self.assertEqual(res.body, 'ht') + self.assertEqual(res.body, b'ht') def test_range_tilend(self): self.testapp.extra_environ = {'HTTP_RANGE':'bytes=-5'} res = self.testapp.get('/static/index.html', status=206) - self.assertEqual(res.body, 'tml>\n') + self.assertEqual(res.body, b'tml>\n') def test_range_notbytes(self): self.testapp.extra_environ = {'HTTP_RANGE':'kHz=-5'} @@ -176,7 +176,7 @@ class TestStaticAppNoSubpath(unittest.TestCase): staticapp = static_view(os.path.join(here, 'fixtures'), use_subpath=False) def _makeRequest(self, extra): from pyramid.request import Request - from StringIO import StringIO + from io import BytesIO kw = {'PATH_INFO':'', 'SCRIPT_NAME':'', 'SERVER_NAME':'localhost', @@ -184,7 +184,7 @@ class TestStaticAppNoSubpath(unittest.TestCase): 'REQUEST_METHOD':'GET', 'wsgi.version':(1,0), 'wsgi.url_scheme':'http', - 'wsgi.input':StringIO()} + 'wsgi.input':BytesIO()} kw.update(extra) request = Request(kw) return request @@ -192,7 +192,7 @@ class TestStaticAppNoSubpath(unittest.TestCase): def _assertBody(self, body, filename): self.assertEqual( body.replace('\r', ''), - open(filename, 'r').read() + open(filename, 'rb').read() ) def test_basic(self): @@ -207,7 +207,7 @@ class TestStaticAppWithRoutePrefix(IntegrationBase, unittest.TestCase): def _assertBody(self, body, filename): self.assertEqual( body.replace('\r', ''), - open(filename, 'r').read() + open(filename, 'rb').read() ) def test_includelevel1(self): @@ -225,18 +225,18 @@ class TestFixtureApp(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.fixtureapp' def test_another(self): res = self.testapp.get('/another.html', status=200) - self.assertEqual(res.body, 'fixture') + self.assertEqual(res.body, b'fixture') def test_root(self): res = self.testapp.get('/', status=200) - self.assertEqual(res.body, 'fixture') + self.assertEqual(res.body, b'fixture') def test_dummyskin(self): self.testapp.get('/dummyskin.html', status=404) def test_error(self): res = self.testapp.get('/error.html', status=200) - self.assertEqual(res.body, 'supressed') + self.assertEqual(res.body, b'supressed') def test_protected(self): self.testapp.get('/protected.html', status=403) @@ -247,8 +247,8 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): def test_allowed(self): result = self.testapp.get('/allowed/index.html', status=200) self.assertEqual( - result.body.replace('\r', ''), - open(os.path.join(here, 'fixtures/static/index.html'), 'r').read()) + result.body.replace(b'\r', b''), + open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) def test_denied_via_acl_global_root_factory(self): self.testapp.extra_environ = {'REMOTE_USER':'bob'} @@ -258,8 +258,8 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): self.testapp.extra_environ = {'REMOTE_USER':'fred'} result = self.testapp.get('/protected/index.html', status=200) self.assertEqual( - result.body.replace('\r', ''), - open(os.path.join(here, 'fixtures/static/index.html'), 'r').read()) + result.body.replace(b'\r', b''), + open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) def test_denied_via_acl_local_root_factory(self): self.testapp.extra_environ = {'REMOTE_USER':'fred'} @@ -269,8 +269,8 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): self.testapp.extra_environ = {'REMOTE_USER':'bob'} result = self.testapp.get('/factory_protected/index.html', status=200) self.assertEqual( - result.body.replace('\r', ''), - open(os.path.join(here, 'fixtures/static/index.html'), 'r').read()) + result.body.replace(b'\r', b''), + open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) class TestCCBug(IntegrationBase, unittest.TestCase): # "unordered" as reported in IRC by author of @@ -278,11 +278,11 @@ class TestCCBug(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.ccbugapp' def test_rdf(self): res = self.testapp.get('/licenses/1/v1/rdf', status=200) - self.assertEqual(res.body, 'rdf') + self.assertEqual(res.body, b'rdf') def test_juri(self): res = self.testapp.get('/licenses/1/v1/juri', status=200) - self.assertEqual(res.body, 'juri') + self.assertEqual(res.body, b'juri') class TestHybridApp(IntegrationBase, unittest.TestCase): # make sure views registered for a route "win" over views registered @@ -291,19 +291,19 @@ class TestHybridApp(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.hybridapp' def test_root(self): res = self.testapp.get('/', status=200) - self.assertEqual(res.body, 'global') + self.assertEqual(res.body, b'global') def test_abc(self): res = self.testapp.get('/abc', status=200) - self.assertEqual(res.body, 'route') + self.assertEqual(res.body, b'route') def test_def(self): res = self.testapp.get('/def', status=200) - self.assertEqual(res.body, 'route2') + self.assertEqual(res.body, b'route2') def test_ghi(self): res = self.testapp.get('/ghi', status=200) - self.assertEqual(res.body, 'global') + self.assertEqual(res.body, b'global') def test_jkl(self): self.testapp.get('/jkl', status=404) @@ -313,41 +313,41 @@ class TestHybridApp(IntegrationBase, unittest.TestCase): def test_pqr_global2(self): res = self.testapp.get('/pqr/global2', status=200) - self.assertEqual(res.body, 'global2') + self.assertEqual(res.body, b'global2') def test_error(self): res = self.testapp.get('/error', status=200) - self.assertEqual(res.body, 'supressed') + self.assertEqual(res.body, b'supressed') def test_error2(self): res = self.testapp.get('/error2', status=200) - self.assertEqual(res.body, 'supressed2') + self.assertEqual(res.body, b'supressed2') def test_error_sub(self): res = self.testapp.get('/error_sub', status=200) - self.assertEqual(res.body, 'supressed2') + self.assertEqual(res.body, b'supressed2') class TestRestBugApp(IntegrationBase, unittest.TestCase): # test bug reported by delijati 2010/2/3 (http://pastebin.com/d4cc15515) package = 'pyramid.tests.pkgs.restbugapp' def test_it(self): res = self.testapp.get('/pet', status=200) - self.assertEqual(res.body, 'gotten') + self.assertEqual(res.body, b'gotten') class TestForbiddenAppHasResult(IntegrationBase, unittest.TestCase): # test that forbidden exception has ACLDenied result attached package = 'pyramid.tests.pkgs.forbiddenapp' def test_it(self): res = self.testapp.get('/x', status=403) - message, result = [x.strip() for x in res.body.split('\n')] - self.assertTrue(message.endswith('failed permission check')) + message, result = [x.strip() for x in res.body.split(b'\n')] + self.assertTrue(message.endswith(b'failed permission check')) self.assertTrue( - result.startswith("ACLDenied permission 'private' via ACE " - "'' in ACL " - "'' on context")) + result.startswith(b"ACLDenied permission 'private' via ACE " + b"'' in ACL " + b"'' on context")) self.assertTrue( - result.endswith("for principals ['system.Everyone']")) + result.endswith(b"for principals ['system.Everyone']")) class TestViewDecoratorApp(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.viewdecoratorapp' @@ -362,20 +362,20 @@ class TestViewDecoratorApp(IntegrationBase, unittest.TestCase): # we use mako here instead of chameleon because it works on Jython self._configure_mako() res = self.testapp.get('/first', status=200) - self.assertTrue('OK' in res.body) + self.assertTrue(b'OK' in res.body) def test_second(self): # we use mako here instead of chameleon because it works on Jython self._configure_mako() res = self.testapp.get('/second', status=200) - self.assertTrue('OK2' in res.body) + self.assertTrue(b'OK2' in res.body) class TestViewPermissionBug(IntegrationBase, unittest.TestCase): # view_execution_permitted bug as reported by Shane at http://lists.repoze.org/pipermail/repoze-dev/2010-October/003603.html package = 'pyramid.tests.pkgs.permbugapp' def test_test(self): res = self.testapp.get('/test', status=200) - self.assertTrue('ACLDenied' in res.body) + self.assertTrue(b'ACLDenied' in res.body) def test_x(self): self.testapp.get('/x', status=403) @@ -385,15 +385,15 @@ class TestDefaultViewPermissionBug(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.defpermbugapp' def test_x(self): res = self.testapp.get('/x', status=403) - self.assertTrue('failed permission check' in res.body) + self.assertTrue(b'failed permission check' in res.body) def test_y(self): res = self.testapp.get('/y', status=403) - self.assertTrue('failed permission check' in res.body) + self.assertTrue(b'failed permission check' in res.body) def test_z(self): res = self.testapp.get('/z', status=200) - self.assertTrue('public' in res.body) + self.assertTrue(b'public' in res.body) from pyramid.tests.pkgs.exceptionviewapp.models import \ AnException, NotAnException @@ -405,31 +405,31 @@ class TestExceptionViewsApp(IntegrationBase, unittest.TestCase): root_factory = lambda *arg: excroot def test_root(self): res = self.testapp.get('/', status=200) - self.assertTrue('maybe' in res.body) + self.assertTrue(b'maybe' in res.body) def test_notanexception(self): res = self.testapp.get('/notanexception', status=200) - self.assertTrue('no' in res.body) + self.assertTrue(b'no' in res.body) def test_anexception(self): res = self.testapp.get('/anexception', status=200) - self.assertTrue('yes' in res.body) + self.assertTrue(b'yes' in res.body) def test_route_raise_exception(self): res = self.testapp.get('/route_raise_exception', status=200) - self.assertTrue('yes' in res.body) + self.assertTrue(b'yes' in res.body) def test_route_raise_exception2(self): res = self.testapp.get('/route_raise_exception2', status=200) - self.assertTrue('yes' in res.body) + self.assertTrue(b'yes' in res.body) def test_route_raise_exception3(self): res = self.testapp.get('/route_raise_exception3', status=200) - self.assertTrue('whoa' in res.body) + self.assertTrue(b'whoa' in res.body) def test_route_raise_exception4(self): res = self.testapp.get('/route_raise_exception4', status=200) - self.assertTrue('whoa' in res.body) + self.assertTrue(b'whoa' in res.body) class TestConflictApp(unittest.TestCase): package = 'pyramid.tests.pkgs.conflictapp' @@ -445,9 +445,9 @@ class TestConflictApp(unittest.TestCase): from webtest import TestApp self.testapp = TestApp(app) res = self.testapp.get('/') - self.assertTrue('a view' in res.body) + self.assertTrue(b'a view' in res.body) res = self.testapp.get('/route') - self.assertTrue('route view' in res.body) + self.assertTrue(b'route view' in res.body) def test_overridden_autoresolved_view(self): from pyramid.response import Response @@ -460,7 +460,7 @@ class TestConflictApp(unittest.TestCase): from webtest import TestApp self.testapp = TestApp(app) res = self.testapp.get('/') - self.assertTrue('this view' in res.body) + self.assertTrue(b'this view' in res.body) def test_overridden_route_view(self): from pyramid.response import Response @@ -473,7 +473,7 @@ class TestConflictApp(unittest.TestCase): from webtest import TestApp self.testapp = TestApp(app) res = self.testapp.get('/route') - self.assertTrue('this view' in res.body) + self.assertTrue(b'this view' in res.body) def test_nonoverridden_authorization_policy(self): config = self._makeConfig() @@ -482,7 +482,7 @@ class TestConflictApp(unittest.TestCase): from webtest import TestApp self.testapp = TestApp(app) res = self.testapp.get('/protected', status=403) - self.assertTrue('403 Forbidden' in res) + self.assertTrue(b'403 Forbidden' in res.body) def test_overridden_authorization_policy(self): config = self._makeConfig() @@ -512,15 +512,15 @@ class ImperativeIncludeConfigurationTest(unittest.TestCase): def test_root(self): res = self.testapp.get('/', status=200) - self.assertTrue('root' in res.body) + self.assertTrue(b'root' in res.body) def test_two(self): res = self.testapp.get('/two', status=200) - self.assertTrue('two' in res.body) + self.assertTrue(b'two' in res.body) def test_three(self): res = self.testapp.get('/three', status=200) - self.assertTrue('three' in res.body) + self.assertTrue(b'three' in res.body) class SelfScanAppTest(unittest.TestCase): def setUp(self): @@ -536,11 +536,11 @@ class SelfScanAppTest(unittest.TestCase): def test_root(self): res = self.testapp.get('/', status=200) - self.assertTrue('root' in res.body) + self.assertTrue(b'root' in res.body) def test_two(self): res = self.testapp.get('/two', status=200) - self.assertTrue('two' in res.body) + self.assertTrue(b'two' in res.body) class WSGIApp2AppTest(unittest.TestCase): def setUp(self): @@ -556,18 +556,18 @@ class WSGIApp2AppTest(unittest.TestCase): def test_hello(self): res = self.testapp.get('/hello', status=200) - self.assertTrue('Hello' in res.body) + self.assertTrue(b'Hello' in res.body) if os.name != 'java': # uses chameleon class RendererScanAppTest(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.rendererscanapp' def test_root(self): res = self.testapp.get('/one', status=200) - self.assertTrue('One!' in res.body) + self.assertTrue(b'One!' in res.body) def test_two(self): res = self.testapp.get('/two', status=200) - self.assertTrue('Two!' in res.body) + self.assertTrue(b'Two!' in res.body) def test_rescan(self): self.config.scan('pyramid.tests.pkgs.rendererscanapp') @@ -575,9 +575,9 @@ if os.name != 'java': # uses chameleon from webtest import TestApp testapp = TestApp(app) res = testapp.get('/one', status=200) - self.assertTrue('One!' in res.body) + self.assertTrue(b'One!' in res.body) res = testapp.get('/two', status=200) - self.assertTrue('Two!' in res.body) + self.assertTrue(b'Two!' in res.body) class DummyContext(object): pass diff --git a/pyramid/tests/test_mako_templating.py b/pyramid/tests/test_mako_templating.py index 9948c713c..074d28b85 100644 --- a/pyramid/tests/test_mako_templating.py +++ b/pyramid/tests/test_mako_templating.py @@ -3,6 +3,7 @@ import unittest from pyramid import testing from pyramid.compat import text_ +from pyramid.compat import text_type class Base(object): def setUp(self): @@ -276,7 +277,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne('path', lookup) result = instance({}, {'system':1}) - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result, text_('result')) def test_call_with_system_context(self): @@ -284,7 +285,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne('path', lookup) result = instance({}, {'context':1}) - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result, text_('result')) self.assertEqual(lookup.values, {'_context':1}) @@ -307,7 +308,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): instance = self._makeOne('path', lookup) try: instance({}, {}) - except MakoRenderingException, e: + except MakoRenderingException as e: self.assertTrue('NotImplementedError' in e.text) else: # pragma: no cover raise AssertionError @@ -316,7 +317,7 @@ class MakoLookupTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne('path', lookup) result = instance.implementation().render_unicode() - self.assertTrue(isinstance(result, unicode)) + self.assertTrue(isinstance(result, text_type)) self.assertEqual(result, text_('result')) class TestIntegration(unittest.TestCase): diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 48b1bed65..758331788 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import cleanUp from pyramid import testing +from pyramid.compat import text_ class TestTemplateRendererFactory(unittest.TestCase): def setUp(self): @@ -433,7 +434,7 @@ class Test_string_renderer_factory(unittest.TestCase): def test_it_unicode(self): renderer = self._callFUT(None) - value = unicode('La Pe\xc3\xb1a', 'utf-8') + value = text_('La Pe\xc3\xb1a', 'utf-8') result = renderer(value, {}) self.assertEqual(result, value) @@ -593,7 +594,7 @@ class TestRendererHelper(unittest.TestCase): request = None helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_request_is_None_response_factory_exists(self): self._registerResponseFactory() @@ -601,14 +602,14 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) self.assertEqual(response.__class__.__name__, 'ResponseFactory') - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_result_is_unicode(self): from pyramid.response import Response request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') - la = unicode('/La Pe\xc3\xb1a', 'utf-8') + la = text_('/La Pe\xc3\xb1a', 'utf-8') response = helper._make_response(la, request) self.assertEqual(response.body, la.encode('utf-8')) @@ -617,7 +618,7 @@ class TestRendererHelper(unittest.TestCase): request = testing.DummyRequest() request.response = Response() helper = self._makeOne('loo.foo') - la = unicode('/La Pe\xc3\xb1a', 'utf-8') + la = text_('/La Pe\xc3\xb1a', 'utf-8') response = helper._make_response(la.encode('utf-8'), request) self.assertEqual(response.body, la.encode('utf-8')) @@ -630,7 +631,7 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) self.assertEqual(response.content_type, 'text/nonsense') - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_with_headerlist(self): from pyramid.response import Response @@ -645,7 +646,7 @@ class TestRendererHelper(unittest.TestCase): ('Content-Length', '3'), ('a', '1'), ('b', '2')]) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_with_status(self): from pyramid.response import Response @@ -656,7 +657,7 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) self.assertEqual(response.status, '406 You Lose') - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_with_charset(self): from pyramid.response import Response @@ -688,7 +689,7 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) self.assertEqual(response.__class__, ResponseFactory) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test__make_response_with_real_request(self): # functional @@ -699,7 +700,7 @@ class TestRendererHelper(unittest.TestCase): helper = self._makeOne('loo.foo') response = helper._make_response('abc', request) self.assertEqual(response.status, '406 You Lose') - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') def test_clone_noargs(self): helper = self._makeOne('name', 'package', 'registry') @@ -811,7 +812,7 @@ class Test_render_to_response(unittest.TestCase): 'pyramid.tests:abc/def.pt') renderer.string_response = 'abc' response = self._callFUT('abc/def.pt', dict(a=1)) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') renderer.assert_(a=1) renderer.assert_(request=None) @@ -822,7 +823,7 @@ class Test_render_to_response(unittest.TestCase): request = testing.DummyRequest() response = self._callFUT('abc/def.pt', dict(a=1), request=request) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') renderer.assert_(a=1) renderer.assert_(request=request) @@ -834,7 +835,7 @@ class Test_render_to_response(unittest.TestCase): request = testing.DummyRequest() response = self._callFUT('abc/def.pt', dict(a=1), request=request, package=pyramid.tests) - self.assertEqual(response.body, 'abc') + self.assertEqual(response.body, b'abc') renderer.assert_(a=1) renderer.assert_(request=request) diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index f1338e331..2dadb7d52 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -237,19 +237,19 @@ class TestRequest(unittest.TestCase): def test_json_body_invalid_json(self): request = self._makeOne({'REQUEST_METHOD':'POST'}) - request.body = '{' + request.body = b'{' self.assertRaises(ValueError, getattr, request, 'json_body') def test_json_body_valid_json(self): request = self._makeOne({'REQUEST_METHOD':'POST'}) - request.body = '{"a":1}' + request.body = b'{"a":1}' self.assertEqual(request.json_body, {'a':1}) def test_json_body_alternate_charset(self): from pyramid.compat import json request = self._makeOne({'REQUEST_METHOD':'POST'}) request.charset = 'latin-1' - la = unicode('La Pe\xc3\xb1a', 'utf-8') + la = text_('La Pe\xc3\xb1a', 'utf-8') body = json.dumps({'a':la}, encoding='latin-1') request.body = body self.assertEqual(request.json_body, {'a':la}) @@ -501,7 +501,7 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): def test_subpath_path_info_and_script_name_have_utf8(self): la = 'La Pe\xc3\xb1a' request = DummyRequest({'PATH_INFO':'/'+la, 'SCRIPT_NAME':'/'+la}) - request.subpath = (unicode(la, 'utf-8'), ) + request.subpath = (text_(la, 'utf-8'), ) response = self._callFUT(request, 'app') self.assertTrue(request.copied) self.assertEqual(response, 'app') diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 1bee26e6a..1e3261b77 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -177,7 +177,7 @@ class TestRouter(unittest.TestCase): return Response(s) router.registry.registerAdapter(make_response, (str,), IResponse) app_iter = router(environ, start_response) - self.assertEqual(app_iter, ['abc']) + self.assertEqual(app_iter, [b'abc']) self.assertEqual(start_response.status, '200 OK') self.assertEqual(environ['handled'], ['two', 'one']) @@ -310,7 +310,7 @@ class TestRouter(unittest.TestCase): return Response(s) router.registry.registerAdapter(make_response, (str,), IResponse) app_iter = router(environ, start_response) - self.assertEqual(app_iter, ['abc']) + self.assertEqual(app_iter, [b'abc']) self.assertEqual(start_response.status, '200 OK') def test_call_view_registered_nonspecific_default_path(self): @@ -466,7 +466,7 @@ class TestRouter(unittest.TestCase): raise KeyError def exc_view(context, request): self.assertFalse(hasattr(request.response, 'a')) - request.response.body = 'OK' + request.response.body = b'OK' return request.response environ = self._makeEnviron() self._registerView(view, '', IViewClassifier, IRequest, IContext) @@ -475,7 +475,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() itera = router(environ, start_response) - self.assertEqual(itera, ['OK']) + self.assertEqual(itera, [b'OK']) def test_call_request_has_response_callbacks(self): from zope.interface import Interface diff --git a/pyramid/tests/test_settings.py b/pyramid/tests/test_settings.py index 5cc4ce561..d02b3cd3e 100644 --- a/pyramid/tests/test_settings.py +++ b/pyramid/tests/test_settings.py @@ -87,7 +87,7 @@ class Test_aslist(unittest.TestCase): def test_with_list(self): result = self._callFUT(['abc', 'def']) - self.assertEqual(result, ['abc', 'def']) + self.assertEqual(list(result), ['abc', 'def']) def test_with_string(self): result = self._callFUT('abc def') diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py index 6dc38fc57..427b03c80 100644 --- a/pyramid/tests/test_static.py +++ b/pyramid/tests/test_static.py @@ -37,14 +37,14 @@ class Test_static_view_use_subpath_False(unittest.TestCase): response = inst(context, request) response.prepare(request.environ) self.assertEqual(response.status, '301 Moved Permanently') - self.assertTrue('http://example.com:6543/' in response.body) + self.assertTrue(b'http://example.com:6543/' in response.body) def test_path_info_slash_means_index_html(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest() context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_oob_singledot(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -52,7 +52,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_oob_emptyelement(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -60,7 +60,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '200 OK') - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_oob_dotdotslash(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -99,21 +99,21 @@ class Test_static_view_use_subpath_False(unittest.TestCase): request = self._makeRequest({'PATH_INFO':'/subdir/'}) context = DummyContext() response = inst(context, request) - self.assertTrue('subdir' in response.body) + self.assertTrue(b'subdir' in response.body) def test_resource_is_file(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest({'PATH_INFO':'/index.html'}) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_resource_is_file_with_cache_max_age(self): inst = self._makeOne('pyramid.tests:fixtures/static', cache_max_age=600) request = self._makeRequest({'PATH_INFO':'/index.html'}) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) self.assertEqual(len(response.headerlist), 5) header_names = [ x[0] for x in response.headerlist ] header_names.sort() @@ -127,7 +127,7 @@ class Test_static_view_use_subpath_False(unittest.TestCase): request = self._makeRequest({'PATH_INFO':'/index.html'}) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) self.assertEqual(len(response.headerlist), 3) header_names = [ x[0] for x in response.headerlist ] header_names.sort() @@ -192,7 +192,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): response = inst(context, request) response.prepare(request.environ) self.assertEqual(response.status, '301 Moved Permanently') - self.assertTrue('http://example.com:6543/' in response.body) + self.assertTrue(b'http://example.com:6543/' in response.body) def test_path_info_slash_means_index_html(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -200,7 +200,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = () context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_oob_singledot(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -258,7 +258,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('subdir',) context = DummyContext() response = inst(context, request) - self.assertTrue('subdir' in response.body) + self.assertTrue(b'subdir' in response.body) def test_resource_is_file(self): inst = self._makeOne('pyramid.tests:fixtures/static') @@ -266,7 +266,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('index.html',) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) def test_resource_is_file_with_cache_max_age(self): inst = self._makeOne('pyramid.tests:fixtures/static', cache_max_age=600) @@ -274,7 +274,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('index.html',) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) self.assertEqual(len(response.headerlist), 5) header_names = [ x[0] for x in response.headerlist ] header_names.sort() @@ -289,7 +289,7 @@ class Test_static_view_use_subpath_True(unittest.TestCase): request.subpath = ('index.html',) context = DummyContext() response = inst(context, request) - self.assertTrue('static' in response.body) + self.assertTrue(b'static' in response.body) self.assertEqual(len(response.headerlist), 3) header_names = [ x[0] for x in response.headerlist ] header_names.sort() diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index f428fa40a..4768daa9e 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -35,8 +35,10 @@ class Test_registerDummySecurityPolicy(TestBase): class Test_registerResources(TestBase): def test_it(self): - ob1 = object() - ob2 = object() + class Dummy: + pass + ob1 = Dummy() + ob2 = Dummy() resources = {'/ob1':ob1, '/ob2':ob2} from pyramid import testing testing.registerResources(resources) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 6abaf403d..837b2afc8 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import cleanUp from pyramid.compat import text_ +from pyramid.compat import text_type class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): @@ -30,8 +31,8 @@ class TraversalPathTests(unittest.TestCase): def test_segments_are_unicode(self): result = self._callFUT('/foo/bar') - self.assertEqual(type(result[0]), unicode) - self.assertEqual(type(result[1]), unicode) + self.assertEqual(type(result[0]), text_type) + self.assertEqual(type(result[1]), text_type) def test_same_value_returned_if_cached(self): result1 = self._callFUT('/foo/bar') @@ -43,14 +44,14 @@ class TraversalPathTests(unittest.TestCase): import urllib la = 'La Pe\xc3\xb1a' encoded = urllib.quote(la) - decoded = unicode(la, 'utf-8') + decoded = text_(la, 'utf-8') path = '/'.join([encoded, encoded]) self.assertEqual(self._callFUT(path), (decoded, decoded)) def test_utf16(self): from pyramid.exceptions import URLDecodeError import urllib - la = unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-16') + la = text_('La Pe\xc3\xb1a', 'utf-8').encode('utf-16') encoded = urllib.quote(la) path = '/'.join([encoded, encoded]) self.assertRaises(URLDecodeError, self._callFUT, path) @@ -280,7 +281,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) - segment = unicode('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') + segment = text_('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) from pyramid.exceptions import URLDecodeError @@ -290,7 +291,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) - segment = unicode('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') + segment = text_('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) from pyramid.exceptions import URLDecodeError @@ -755,7 +756,7 @@ class QuotePathSegmentTests(unittest.TestCase): return quote_path_segment(s) def test_unicode(self): - la = unicode('/La Pe\xc3\xb1a', 'utf-8') + la = text_('/La Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) self.assertEqual(result, '%2FLa%20Pe%C3%B1a') @@ -845,7 +846,7 @@ class TraversalContextURLTests(unittest.TestCase): root.__name__ = None one = DummyContext() one.__parent__ = root - one.__name__ = unicode('La Pe\xc3\xb1a', 'utf-8') + one.__name__ = text_('La Pe\xc3\xb1a', 'utf-8') two = DummyContext() two.__parent__ = one two.__name__ = 'La Pe\xc3\xb1a' diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 452debd42..22eacd758 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -49,7 +49,7 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_unicode_in_element_names(self): request = self._makeOne() self._registerContextURL(request.registry) - uc = unicode('La Pe\xc3\xb1a', 'utf-8') + uc = text_('La Pe\xc3\xb1a', 'utf-8') context = DummyContext() result = request.resource_url(context, uc) self.assertEqual(result, @@ -74,7 +74,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = unicode('La Pe\xc3\xb1a', 'utf-8') + uc = text_('La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query={'a':uc}) self.assertEqual(result, 'http://example.com/context/a?a=La+Pe%C3%B1a') @@ -83,7 +83,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = unicode('La Pe\xc3\xb1a', 'utf-8') + uc = text_('La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query=[('a', 'hi there'), ('b', uc)]) self.assertEqual(result, @@ -118,7 +118,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = unicode('La Pe\xc3\xb1a', 'utf-8') + uc = text_('La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, anchor=uc) self.assertEqual(result, 'http://example.com/context/#La Pe\xc3\xb1a') @@ -191,7 +191,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - anchor = unicode('La Pe\xc3\xb1a', 'utf-8') + anchor = text_('La Pe\xc3\xb1a', 'utf-8') result = request.route_url('flub', _anchor=anchor) self.assertEqual(result, 'http://example.com:5432/1/2/3#La Pe\xc3\xb1a') diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py index eb165ef69..2883a968c 100644 --- a/pyramid/tests/test_util.py +++ b/pyramid/tests/test_util.py @@ -190,7 +190,7 @@ class Test_WeakOrderedSet(unittest.TestCase): reg = Dummy() wos.add(reg) self.assertEqual(list(wos), [reg]) - self.assert_(reg in wos) + self.assertTrue(reg in wos) self.assertEqual(wos.last, reg) def test_add_multiple_items(self): @@ -201,8 +201,8 @@ class Test_WeakOrderedSet(unittest.TestCase): wos.add(reg2) self.assertEqual(len(wos), 2) self.assertEqual(list(wos), [reg1, reg2]) - self.assert_(reg1 in wos) - self.assert_(reg2 in wos) + self.assertTrue(reg1 in wos) + self.assertTrue(reg2 in wos) self.assertEqual(wos.last, reg2) def test_add_duplicate_items(self): @@ -212,7 +212,7 @@ class Test_WeakOrderedSet(unittest.TestCase): wos.add(reg) self.assertEqual(len(wos), 1) self.assertEqual(list(wos), [reg]) - self.assert_(reg in wos) + self.assertTrue(reg in wos) self.assertEqual(wos.last, reg) def test_weakref_removal(self): diff --git a/pyramid/traversal.py b/pyramid/traversal.py index d586c30d9..897e01751 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -1,4 +1,3 @@ -import urllib import warnings from zope.interface import implementer @@ -14,6 +13,8 @@ from pyramid.interfaces import VH_ROOT_KEY from pyramid.compat import native_ from pyramid.compat import text_ from pyramid.compat import text_type +from pyramid.compat import url_unquote +from pyramid.compat import is_nonstr_iter from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage @@ -278,7 +279,7 @@ def traverse(resource, path): and will be URL-decoded. """ - if hasattr(path, '__iter__'): + if is_nonstr_iter(path): # the traverser factory expects PATH_INFO to be a string, not # unicode and it expects path segments to be utf-8 and # urlencoded (it's the same traverser which accepts PATH_INFO @@ -296,8 +297,8 @@ def traverse(resource, path): # step rather than later down the line as the result of calling # ``traversal_path``). - if isinstance(path, unicode): - path = path.encode('ascii') + if isinstance(path, text_type): + path = native_(path, 'ascii') if path and path[0] == '/': resource = find_root(resource) @@ -475,14 +476,14 @@ def traversal_path(path): their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ - if isinstance(path, unicode): - path = path.encode('ascii') + if isinstance(path, text_type): + path = native_(path, 'ascii') path = path.strip('/') clean = [] for segment in path.split('/'): - segment = urllib.unquote(segment) + segment = url_unquote(segment) try: - segment = segment.decode('utf-8') + segment = native_(segment, 'utf-8') except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': @@ -530,7 +531,7 @@ def quote_path_segment(segment, safe=''): return _segment_cache[(segment, safe)] except KeyError: if segment.__class__ is text_type: # isinstance slighly slower (~15%) - result = url_quote(segment.encode('utf-8'), safe) + result = url_quote(native_(segment, 'utf-8'), safe) else: result = url_quote(native_(segment), safe) # we don't need a lock to mutate _segment_cache, as the below @@ -568,12 +569,12 @@ class ResourceTreeTraverser(object): matchdict = environ['bfg.routes.matchdict'] path = matchdict.get('traverse', '/') or '/' - if hasattr(path, '__iter__'): + if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) path = '/'.join([quote_path_segment(x) for x in path]) or '/' subpath = matchdict.get('subpath', ()) - if not hasattr(subpath, '__iter__'): + if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) subpath = traversal_path(subpath) diff --git a/pyramid/url.py b/pyramid/url.py index a28228290..c0c623aeb 100644 --- a/pyramid/url.py +++ b/pyramid/url.py @@ -8,6 +8,8 @@ from pyramid.interfaces import IContextURL from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IStaticURLInfo +from pyramid.compat import native_ +from pyramid.compat import text_type from pyramid.encode import urlencode from pyramid.path import caller_package from pyramid.threadlocal import get_current_registry @@ -135,8 +137,8 @@ class URLMethodsMixin(object): if '_anchor' in kw: anchor = kw.pop('_anchor') - if isinstance(anchor, unicode): - anchor = anchor.encode('utf-8') + if isinstance(anchor, text_type): + anchor = native_(anchor, 'utf-8') anchor = '#' + anchor if '_app_url' in kw: @@ -300,8 +302,8 @@ class URLMethodsMixin(object): if 'anchor' in kw: anchor = kw['anchor'] - if isinstance(anchor, unicode): - anchor = anchor.encode('utf-8') + if isinstance(anchor, text_type): + anchor = native_(anchor, 'utf-8') anchor = '#' + anchor if elements: diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 8484fa549..a25bd58a9 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -5,6 +5,9 @@ from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoute from pyramid.compat import url_unquote +from pyramid.compat import native_ +from pyramid.compat import text_type +from pyramid.compat import text_ from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.traversal import traversal_path @@ -139,7 +142,7 @@ def _compile_route(route): else: encoded = url_unquote(v) try: - d[k] = encoded.decode('utf-8') + d[k] = text_(encoded, 'utf-8') except UnicodeDecodeError as e: raise URLDecodeError( e.encoding, e.object, e.start, e.end, e.reason @@ -153,8 +156,8 @@ def _compile_route(route): def generator(dict): newdict = {} for k, v in dict.items(): - if isinstance(v, unicode): - v = v.encode('utf-8') + if isinstance(v, text_type): + v = native_(v, 'utf-8') if k == star and hasattr(v, '__iter__'): v = '/'.join([quote_path_segment(x) for x in v]) elif k != star: -- cgit v1.2.3 From e84232ed948179d019974f04ad77b5c11a8e5a3f Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 06:38:31 -0400 Subject: fix on python 2 --- pyramid/request.py | 6 +++--- pyramid/traversal.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyramid/request.py b/pyramid/request.py index fda233388..cfab88860 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -401,12 +401,12 @@ def call_app_with_subpath_as_path_info(request, app): environ = request.environ script_name = environ.get('SCRIPT_NAME', '') path_info = environ.get('PATH_INFO', '/') - subpath = getattr(request, 'subpath', ()) + subpath = list(getattr(request, 'subpath', ())) new_script_name = '' # compute new_path_info - new_path_info = '/' + '/'.join([native_(x, 'utf-8') for x in subpath]) + new_path_info = '/' + '/'.join([x.encode('utf-8') for x in subpath]) if new_path_info != '/': # don't want a sole double-slash if path_info != '/': # if orig path_info is '/', we're already done @@ -424,7 +424,7 @@ def call_app_with_subpath_as_path_info(request, app): break el = workback.pop() if el: - tmp.insert(0, native_(el, 'utf-8')) + tmp.insert(0, el.decode('utf-8')) # strip all trailing slashes from workback to avoid appending undue slashes # to end of script_name diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 897e01751..d05805c06 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -483,7 +483,7 @@ def traversal_path(path): for segment in path.split('/'): segment = url_unquote(segment) try: - segment = native_(segment, 'utf-8') + segment = text_(segment, 'utf-8') except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': @@ -531,7 +531,7 @@ def quote_path_segment(segment, safe=''): return _segment_cache[(segment, safe)] except KeyError: if segment.__class__ is text_type: # isinstance slighly slower (~15%) - result = url_quote(native_(segment, 'utf-8'), safe) + result = url_quote(segment.encode('utf-8'), safe) else: result = url_quote(native_(segment), safe) # we don't need a lock to mutate _segment_cache, as the below -- cgit v1.2.3 From f11a02035e8f055d778737427fe413fa225a07bc Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 16:50:21 -0400 Subject: coverage under py2 --- pyramid/compat.py | 37 +++++++++------------------------- pyramid/paster.py | 2 +- pyramid/scaffolds/__init__.py | 4 ++-- pyramid/testing.py | 2 +- pyramid/tests/test_config/test_init.py | 4 ++-- 5 files changed, 16 insertions(+), 33 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index a6f7f025e..a19c61034 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -1,6 +1,13 @@ import sys import types +try: # pragma: no cover + import __pypy__ + PYPY = True +except: # pragma: no cover + __pypy__ = None + PYPY = False + try: import cPickle as pickle except ImportError: # pragma: no cover @@ -24,8 +31,6 @@ if PY3: # pragma: no cover text_type = str binary_type = bytes long = int - def ords_(b): - return b else: string_types = basestring, integer_types = (int, long) @@ -33,8 +38,6 @@ else: text_type = unicode binary_type = str long = long - def ords_(s): - return [ord(x) for x in s] def text_(s, encoding='latin-1', errors='strict'): if isinstance(s, binary_type): @@ -57,21 +60,6 @@ else: return s.encode(encoding, errors) return str(s) -if PY3: # pragma: no cover - fsenc = sys.getfilesystemencoding() - def text_to_wsgi(u): - # On Python 3, convert an environment variable to a WSGI - # "bytes-as-unicode" string - return u.encode(fsenc, 'surrogateescape').decode('latin-1') -else: - def text_to_wsgi(u): - return u.encode('latin-1', 'surrogateescape') - -try: - from queue import Queue, Empty -except ImportError: - from Queue import Queue, Empty - try: # pragma: no cover from urllib import parse urlparse = parse @@ -180,17 +168,12 @@ else: return d.iterkeys() -if PY3: +if PY3: # pragma: no cover def map_(*arg): return list(map(*arg)) else: map_ = map -try: - import __pypy__ -except: - __pypy__ = None - if PY3: # pragma: no cover def is_nonstr_iter(v): if isinstance(v, str): @@ -205,8 +188,8 @@ if PY3: # pragma: no cover else: im_func = 'im_func' -try: +try: # pragma: no cover import configparser -except ImportError: +except ImportError: # pragma: no cover import ConfigParser configparser = ConfigParser diff --git a/pyramid/paster.py b/pyramid/paster.py index 0085c279e..ab764ba59 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -12,7 +12,7 @@ except ImportError: # pragma: no cover try: from paste.script.command import Command -except ImportError: +except ImportError: # pragma: no cover class Command: pass diff --git a/pyramid/scaffolds/__init__.py b/pyramid/scaffolds/__init__.py index e00a9f83b..1595c37eb 100644 --- a/pyramid/scaffolds/__init__.py +++ b/pyramid/scaffolds/__init__.py @@ -2,13 +2,13 @@ import os try: from paste.script.templates import Template -except ImportError: +except ImportError: # pragma: no cover class Template: pass try: from paste.util.template import paste_script_template_renderer -except ImportError: +except ImportError: # pragma: no cover def paste_script_template_renderer(): pass diff --git a/pyramid/testing.py b/pyramid/testing.py index 338eff9e9..862d31459 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -32,7 +32,7 @@ try: import zope.component zope.component have_zca = True -except ImportError: +except ImportError: # pragma: no cover have_zca = False _marker = object() diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 0decd28ad..d3db47369 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -2,7 +2,7 @@ import unittest import os -from pyramid.compat import __pypy__ +from pyramid.compat import PYPY from pyramid.tests.test_config import dummy_tween_factory from pyramid.tests.test_config import dummy_include @@ -66,7 +66,7 @@ class ConfiguratorTests(unittest.TestCase): config.commit() self.assertTrue(config.registry.getUtility(IRendererFactory, 'json')) self.assertTrue(config.registry.getUtility(IRendererFactory, 'string')) - if not __pypy__: + if not PYPY: self.assertTrue(config.registry.getUtility(IRendererFactory, '.pt')) self.assertTrue(config.registry.getUtility(IRendererFactory,'.txt')) self.assertTrue(config.registry.getUtility(IRendererFactory, '.mak')) -- cgit v1.2.3 From 9549997d246ff0428c72609951ebcb70056cedc4 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 18:05:47 -0400 Subject: beat me, whip me --- pyramid/compat.py | 4 ++++ pyramid/tests/pkgs/wsgiapp2app/__init__.py | 2 +- pyramid/tests/test_chameleon_text.py | 17 +++++++++-------- pyramid/tests/test_config/test_init.py | 4 ++-- pyramid/tests/test_config/test_views.py | 2 +- pyramid/tests/test_httpexceptions.py | 2 +- pyramid/tests/test_session.py | 20 +++++++------------- pyramid/tests/test_traversal.py | 5 +++-- pyramid/traversal.py | 15 +++++++-------- pyramid/urldispatch.py | 11 ++++++----- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index a19c61034..d83205c87 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -65,6 +65,7 @@ try: # pragma: no cover urlparse = parse from urllib.parse import quote as url_quote from urllib.parse import unquote as url_unquote + url_unquote_text = url_unquote from urllib.parse import urlencode as url_encode from urllib.request import urlopen as url_open except ImportError: @@ -73,6 +74,9 @@ except ImportError: from urllib import unquote as url_unquote from urllib import urlencode as url_encode from urllib2 import urlopen as url_open + def url_unquote_text(v, encoding='utf-8', errors='replace'): + v = url_unquote(v) + return v.decode(encoding, errors) if PY3: # pragma: no cover import builtins diff --git a/pyramid/tests/pkgs/wsgiapp2app/__init__.py b/pyramid/tests/pkgs/wsgiapp2app/__init__.py index 0880556ef..e2024198e 100644 --- a/pyramid/tests/pkgs/wsgiapp2app/__init__.py +++ b/pyramid/tests/pkgs/wsgiapp2app/__init__.py @@ -8,7 +8,7 @@ def hello(environ, start_response): assert environ['SCRIPT_NAME'] == '/hello' response_headers = [('Content-Type', 'text/plain')] start_response('200 OK', response_headers) - return ['Hello!'] + return [b'Hello!'] def main(): from pyramid.config import Configurator diff --git a/pyramid/tests/test_chameleon_text.py b/pyramid/tests/test_chameleon_text.py index cae52c2f4..8d23c8753 100644 --- a/pyramid/tests/test_chameleon_text.py +++ b/pyramid/tests/test_chameleon_text.py @@ -1,5 +1,6 @@ import unittest +from pyramid.compat import binary_type from pyramid.testing import skip_on from pyramid import testing @@ -98,8 +99,8 @@ class TextTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne(minimal, lookup) result = instance({}, {}) - self.assertTrue(isinstance(result, str)) - self.assertEqual(result, 'Hello.\n') + self.assertTrue(isinstance(result, binary_type)) + self.assertEqual(result, b'Hello.\n') @skip_on('java') def test_call_with_nondict_value(self): @@ -114,8 +115,8 @@ class TextTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne(nonminimal, lookup) result = instance({'name':'Chris'}, {}) - self.assertTrue(isinstance(result, str)) - self.assertEqual(result, 'Hello, Chris!\n') + self.assertTrue(isinstance(result, binary_type)) + self.assertEqual(result, b'Hello, Chris!\n') @skip_on('java') def test_implementation(self): @@ -123,8 +124,8 @@ class TextTemplateRendererTests(Base, unittest.TestCase): lookup = DummyLookup() instance = self._makeOne(minimal, lookup) result = instance.implementation()() - self.assertTrue(isinstance(result, str)) - self.assertEqual(result, 'Hello.\n') + self.assertTrue(isinstance(result, binary_type)) + self.assertEqual(result, b'Hello.\n') class RenderTemplateTests(Base, unittest.TestCase): def _callFUT(self, name, **kw): @@ -135,8 +136,8 @@ class RenderTemplateTests(Base, unittest.TestCase): def test_it(self): minimal = self._getTemplatePath('minimal.txt') result = self._callFUT(minimal) - self.assertTrue(isinstance(result, str)) - self.assertEqual(result, 'Hello.\n') + self.assertTrue(isinstance(result, binary_type)) + self.assertEqual(result, b'Hello.\n') class RenderTemplateToResponseTests(Base, unittest.TestCase): def _callFUT(self, name, **kw): diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index d3db47369..302a185f2 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -1218,7 +1218,7 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase): request_type = self._getRouteRequestIface(config, 'name') wrapper = self._getViewCallable(config, None, request_type) self._assertRoute(config, 'name', 'path') - self.assertEqual(wrapper(None, None).body, 'Hello!') + self.assertEqual(wrapper(None, None).body, b'Hello!') def test_add_route_with_view_attr(self): from pyramid.renderers import null_renderer @@ -1246,7 +1246,7 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase): request_type = self._getRouteRequestIface(config, 'name') wrapper = self._getViewCallable(config, None, request_type) self._assertRoute(config, 'name', 'path') - self.assertEqual(wrapper(None, None).body, 'Hello!') + self.assertEqual(wrapper(None, None).body, b'Hello!') def test_add_route_with_view_permission(self): from pyramid.interfaces import IAuthenticationPolicy diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index eceea94d5..141b60e87 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -2276,7 +2276,7 @@ class TestViewDeriver(unittest.TestCase): self.assertFalse(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) - self.assertTrue('instance' in result.__name__) + self.assertTrue('test_views' in result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), response) diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index 60c97b5b4..b58145be8 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -256,7 +256,7 @@ class TestWSGIHTTPException(unittest.TestCase): def test_body_template_unicode(self): cls = self._getTargetSubclass() - la = text_('/La Pe\xc3\xb1a', 'utf-8') + la = text_(b'/La Pe\xc3\xb1a', 'utf-8') environ = _makeEnviron(unicodeval=la) exc = cls(body_template='${unicodeval}') start_response = DummyStartResponse() diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py index 5c6454a38..6d75c7950 100644 --- a/pyramid/tests/test_session.py +++ b/pyramid/tests/test_session.py @@ -263,21 +263,15 @@ class Test_manage_accessed(unittest.TestCase): self.assertEqual(session.response, response) def serialize(data, secret): - try: - from hashlib import sha1 - except ImportError: # pragma: no cover - import sha as sha1 - - try: - import cPickle as pickle - except ImportError: # pragma: no cover - import pickle - import hmac import base64 - pickled = pickle.dumps('123', pickle.HIGHEST_PROTOCOL) - sig = hmac.new(secret, pickled, sha1).hexdigest() - return sig + base64.standard_b64encode(pickled) + from hashlib import sha1 + from pyramid.compat import bytes_ + from pyramid.compat import native_ + from pyramid.compat import pickle + pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) + sig = hmac.new(bytes_(secret), pickled, sha1).hexdigest() + return sig + native_(base64.b64encode(pickled)) class Test_signed_serialize(unittest.TestCase): def _callFUT(self, data, secret): diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 837b2afc8..cd48d0268 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -2,6 +2,7 @@ import unittest from pyramid.testing import cleanUp from pyramid.compat import text_ +from pyramid.compat import native_ from pyramid.compat import text_type class TraversalPathTests(unittest.TestCase): @@ -281,7 +282,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) - segment = text_('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') + segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) from pyramid.exceptions import URLDecodeError @@ -291,7 +292,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) - segment = text_('LaPe\xc3\xb1a', 'utf-8').encode('utf-16') + segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) from pyramid.exceptions import URLDecodeError diff --git a/pyramid/traversal.py b/pyramid/traversal.py index d05805c06..e535da657 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -13,7 +13,7 @@ from pyramid.interfaces import VH_ROOT_KEY from pyramid.compat import native_ from pyramid.compat import text_ from pyramid.compat import text_type -from pyramid.compat import url_unquote +from pyramid.compat import url_unquote_text from pyramid.compat import is_nonstr_iter from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError @@ -477,13 +477,12 @@ def traversal_path(path): writing applications in :app:`Pyramid`. """ if isinstance(path, text_type): - path = native_(path, 'ascii') + path = native_(path.encode('ascii')) path = path.strip('/') clean = [] for segment in path.split('/'): - segment = url_unquote(segment) try: - segment = text_(segment, 'utf-8') + segment = url_unquote_text(segment, 'utf-8', 'strict') except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': @@ -530,10 +529,10 @@ def quote_path_segment(segment, safe=''): try: return _segment_cache[(segment, safe)] except KeyError: - if segment.__class__ is text_type: # isinstance slighly slower (~15%) - result = url_quote(segment.encode('utf-8'), safe) - else: - result = url_quote(native_(segment), safe) + ## if segment.__class__ is text_type: # isinstance slighly slower (~15%) + ## result = url_quote(segment.encode('utf-8'), safe) + ## else: + result = url_quote(native_(segment, 'utf-8'), safe) # we don't need a lock to mutate _segment_cache, as the below # will generate exactly one Python bytecode (STORE_SUBSCR) _segment_cache[(segment, safe)] = result diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index a25bd58a9..696b69f89 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -4,10 +4,10 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoute -from pyramid.compat import url_unquote +from pyramid.compat import url_unquote_text from pyramid.compat import native_ from pyramid.compat import text_type -from pyramid.compat import text_ +from pyramid.compat import is_nonstr_iter from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.traversal import traversal_path @@ -140,9 +140,10 @@ def _compile_route(route): if k == star: d[k] = traversal_path(v) else: - encoded = url_unquote(v) try: - d[k] = text_(encoded, 'utf-8') + val = url_unquote_text( + v, encoding='utf-8', errors='strict') + d[k] = val except UnicodeDecodeError as e: raise URLDecodeError( e.encoding, e.object, e.start, e.end, e.reason @@ -158,7 +159,7 @@ def _compile_route(route): for k, v in dict.items(): if isinstance(v, text_type): v = native_(v, 'utf-8') - if k == star and hasattr(v, '__iter__'): + if k == star and is_nonstr_iter(v): v = '/'.join([quote_path_segment(x) for x in v]) elif k != star: try: -- cgit v1.2.3 From 5e21d5cefc4b7441e84f1412af3556a395f13489 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 23 Sep 2011 20:13:23 -0400 Subject: whats the safe word --- pyramid/config/util.py | 23 +++++++++++------------ pyramid/scaffolds/__init__.py | 4 +++- pyramid/tests/test_integration.py | 4 ++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 7980a78e3..0b3d14f07 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -95,7 +95,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, xhr_predicate.__text__ = "xhr = True" weights.append(1 << 1) predicates.append(xhr_predicate) - h.update('xhr:%r' % bool(xhr)) + h.update(bytes_('xhr:%r' % bool(xhr))) if request_method is not None: if not hasattr(request_method, '__iter__'): @@ -108,7 +108,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, weights.append(1 << 2) predicates.append(request_method_predicate) for m in request_method: - h.update('request_method:%r' % m) + h.update(bytes_('request_method:%r' % m)) if path_info is not None: try: @@ -121,7 +121,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, path_info_predicate.__text__ = text % path_info weights.append(1 << 3) predicates.append(path_info_predicate) - h.update('path_info:%r' % path_info) + h.update(bytes_('path_info:%r' % path_info)) if request_param is not None: request_param_val = None @@ -138,7 +138,8 @@ def make_predicates(xhr=None, request_method=None, path_info=None, request_param_predicate.__text__ = text weights.append(1 << 4) predicates.append(request_param_predicate) - h.update('request_param:%r=%r' % (request_param, request_param_val)) + h.update( + bytes_('request_param:%r=%r' % (request_param, request_param_val))) if header is not None: header_name = header @@ -163,7 +164,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, header_predicate.__text__ = text weights.append(1 << 5) predicates.append(header_predicate) - h.update('header:%r=%r' % (header_name, header_val)) + h.update(bytes_('header:%r=%r' % (header_name, header_val))) if accept is not None: def accept_predicate(context, request): @@ -171,7 +172,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, accept_predicate.__text__ = "accept = %s" % accept weights.append(1 << 6) predicates.append(accept_predicate) - h.update('accept:%r' % accept) + h.update(bytes_('accept:%r' % accept)) if containment is not None: def containment_predicate(context, request): @@ -179,7 +180,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, containment_predicate.__text__ = "containment = %s" % containment weights.append(1 << 7) predicates.append(containment_predicate) - h.update('containment:%r' % hash_(containment)) + h.update(bytes_('containment:%r' % containment)) if request_type is not None: def request_type_predicate(context, request): @@ -188,7 +189,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, request_type_predicate.__text__ = text % request_type weights.append(1 << 8) predicates.append(request_type_predicate) - h.update('request_type:%r' % hash_(request_type)) + h.update(bytes_('request_type:%r' % request_type)) if match_param is not None: if isinstance(match_param, string_types): @@ -203,7 +204,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, match_param_predicate.__text__ = text weights.append(1 << 9) predicates.append(match_param_predicate) - h.update('match_param:%r' % match_param) + h.update(bytes_('match_param:%r' % match_param)) if custom: for num, predicate in enumerate(custom): @@ -224,7 +225,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, # functions for custom predicates, so that the hash output # of predicate instances which are "logically the same" # may compare equal. - h.update('custom%s:%r' % (num, hash_(predicate))) + h.update(bytes_('custom%s:%r' % (num, predicate))) weights.append(1 << 10) if traverse is not None: @@ -261,5 +262,3 @@ def as_sorted_tuple(val): val = tuple(sorted(val)) return val -def hash_(v): - return bytes_(hash(v)) diff --git a/pyramid/scaffolds/__init__.py b/pyramid/scaffolds/__init__.py index 1595c37eb..673f22e21 100644 --- a/pyramid/scaffolds/__init__.py +++ b/pyramid/scaffolds/__init__.py @@ -1,5 +1,7 @@ import os +from pyramid.compat import print_ + try: from paste.script.templates import Template except ImportError: # pragma: no cover @@ -27,7 +29,7 @@ class PyramidTemplate(Template): return Template.post(self, command, output_dir, vars) def out(self, msg): # pragma: no cover (replaceable testing hook) - print msg + print_(msg) class StarterProjectTemplate(PyramidTemplate): _template_dir = 'starter' diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 9db03c28b..3c970e3bc 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -65,7 +65,7 @@ here = os.path.dirname(__file__) class TestStaticAppBase(IntegrationBase): def _assertBody(self, body, filename): self.assertEqual( - body.replace('\r', ''), + body.replace(b'\r', b''), open(filename, 'rb').read() ) @@ -206,7 +206,7 @@ class TestStaticAppWithRoutePrefix(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.static_routeprefix' def _assertBody(self, body, filename): self.assertEqual( - body.replace('\r', ''), + body.replace(b'\r', b''), open(filename, 'rb').read() ) -- cgit v1.2.3 From 790c71521786cadeba729b062997f91b5f46e8a2 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 00:21:59 -0400 Subject: fix tests on py2 --- pyramid/config/util.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 0b3d14f07..febef4b8f 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -3,6 +3,7 @@ import traceback from pyramid.compat import string_types from pyramid.compat import bytes_ +from pyramid.compat import is_nonstr_iter from pyramid.exceptions import ConfigurationError from pyramid.traversal import find_interface from pyramid.traversal import traversal_path @@ -180,7 +181,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, containment_predicate.__text__ = "containment = %s" % containment weights.append(1 << 7) predicates.append(containment_predicate) - h.update(bytes_('containment:%r' % containment)) + h.update(bytes_('containment:%r' % hash(containment))) if request_type is not None: def request_type_predicate(context, request): @@ -189,7 +190,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, request_type_predicate.__text__ = text % request_type weights.append(1 << 8) predicates.append(request_type_predicate) - h.update(bytes_('request_type:%r' % request_type)) + h.update(bytes_('request_type:%r' % hash(request_type))) if match_param is not None: if isinstance(match_param, string_types): @@ -225,7 +226,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, # functions for custom predicates, so that the hash output # of predicate instances which are "logically the same" # may compare equal. - h.update(bytes_('custom%s:%r' % (num, predicate))) + h.update(bytes_('custom%s:%r' % (num, hash(predicate)))) weights.append(1 << 10) if traverse is not None: @@ -257,7 +258,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, return order, predicates, phash def as_sorted_tuple(val): - if not hasattr(val, '__iter__'): + if not is_nonstr_iter(val): val = (val,) val = tuple(sorted(val)) return val -- cgit v1.2.3 From d97398af4fbcda3a90baa88a412a77fcadb53906 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 00:29:22 -0400 Subject: fix testing tests in the face of a missing zope.component --- pyramid/tests/test_testing.py | 139 ++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 67 deletions(-) diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index 4768daa9e..05ef36fe9 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -589,87 +589,73 @@ class Test_setUp(unittest.TestCase): from pyramid.testing import setUp return setUp(**kw) + def tearDown(self): + from pyramid.threadlocal import manager + manager.clear() + getSiteManager = self._getSM() + if getSiteManager is not None: + getSiteManager.reset() + + def _getSM(self): + try: + from zope.component import getSiteManager + except ImportError: # pragma: no cover + getSiteManager = None + return getSiteManager + + def _assertSMHook(self, hook): + getSiteManager = self._getSM() + if getSiteManager is not None: + result = getSiteManager.sethook(None) + self.assertEqual(result, hook) + def test_it_defaults(self): from pyramid.threadlocal import manager from pyramid.threadlocal import get_current_registry from pyramid.registry import Registry - from zope.component import getSiteManager old = True manager.push(old) - try: - config = self._callFUT() - current = manager.get() - self.assertFalse(current is old) - self.assertEqual(config.registry, current['registry']) - self.assertEqual(current['registry'].__class__, Registry) - self.assertEqual(current['request'], None) - finally: - result = getSiteManager.sethook(None) - self.assertEqual(result, get_current_registry) - getSiteManager.reset() - manager.clear() + config = self._callFUT() + current = manager.get() + self.assertFalse(current is old) + self.assertEqual(config.registry, current['registry']) + self.assertEqual(current['registry'].__class__, Registry) + self.assertEqual(current['request'], None) + self._assertSMHook(get_current_registry) def test_it_with_registry(self): from pyramid.registry import Registry - from zope.component import getSiteManager from pyramid.threadlocal import manager registry = Registry() - try: - self._callFUT(registry=registry) - current = manager.get() - self.assertEqual(current['registry'], registry) - finally: - getSiteManager.reset() - manager.clear() + self._callFUT(registry=registry) + current = manager.get() + self.assertEqual(current['registry'], registry) def test_it_with_request(self): - from zope.component import getSiteManager from pyramid.threadlocal import manager request = object() - try: - self._callFUT(request=request) - current = manager.get() - self.assertEqual(current['request'], request) - finally: - getSiteManager.reset() - manager.clear() + self._callFUT(request=request) + current = manager.get() + self.assertEqual(current['request'], request) def test_it_with_hook_zca_false(self): - from zope.component import getSiteManager - from pyramid.threadlocal import manager from pyramid.registry import Registry registry = Registry() - try: - self._callFUT(registry=registry, hook_zca=False) + self._callFUT(registry=registry, hook_zca=False) + getSiteManager = self._getSM() + if getSiteManager is not None: sm = getSiteManager() self.assertFalse(sm is registry) - finally: - getSiteManager.reset() - manager.clear() def test_it_with_settings_passed_explicit_registry(self): - from zope.component import getSiteManager - from pyramid.threadlocal import manager from pyramid.registry import Registry registry = Registry() - try: - self._callFUT(registry=registry, hook_zca=False, - settings=dict(a=1)) - self.assertEqual(registry.settings['a'], 1) - finally: - getSiteManager.reset() - manager.clear() + self._callFUT(registry=registry, hook_zca=False, settings=dict(a=1)) + self.assertEqual(registry.settings['a'], 1) def test_it_with_settings_passed_implicit_registry(self): - from zope.component import getSiteManager - from pyramid.threadlocal import manager - try: - config = self._callFUT(hook_zca=False, - settings=dict(a=1)) - self.assertEqual(config.registry.settings['a'], 1) - finally: - getSiteManager.reset() - manager.clear() + config = self._callFUT(hook_zca=False, settings=dict(a=1)) + self.assertEqual(config.registry.settings['a'], 1) class Test_cleanUp(Test_setUp): def _callFUT(self, *arg, **kw): @@ -681,24 +667,48 @@ class Test_tearDown(unittest.TestCase): from pyramid.testing import tearDown return tearDown(**kw) + def tearDown(self): + from pyramid.threadlocal import manager + manager.clear() + getSiteManager = self._getSM() + if getSiteManager is not None: + getSiteManager.reset() + + def _getSM(self): + try: + from zope.component import getSiteManager + except ImportError: # pragma: no cover + getSiteManager = None + return getSiteManager + + def _assertSMHook(self, hook): + getSiteManager = self._getSM() + if getSiteManager is not None: + result = getSiteManager.sethook(None) + self.assertEqual(result, hook) + + def _setSMHook(self, hook): + getSiteManager = self._getSM() + if getSiteManager is not None: + getSiteManager.sethook(hook) + def test_defaults(self): from pyramid.threadlocal import manager - from zope.component import getSiteManager registry = DummyRegistry() old = {'registry':registry} hook = lambda *arg: None try: - getSiteManager.sethook(hook) + self._setSMHook(hook) manager.push(old) self._callFUT() current = manager.get() self.assertNotEqual(current, old) self.assertEqual(registry.inited, 2) finally: - result = getSiteManager.sethook(None) - self.assertNotEqual(result, hook) - getSiteManager.reset() - manager.clear() + getSiteManager = self._getSM() + if getSiteManager is not None: + result = getSiteManager.sethook(None) + self.assertNotEqual(result, hook) def test_registry_cannot_be_inited(self): from pyramid.threadlocal import manager @@ -717,17 +727,12 @@ class Test_tearDown(unittest.TestCase): manager.clear() def test_unhook_zc_false(self): - from pyramid.threadlocal import manager - from zope.component import getSiteManager hook = lambda *arg: None try: - getSiteManager.sethook(hook) + self._setSMHook(hook) self._callFUT(unhook_zca=False) finally: - result = getSiteManager.sethook(None) - self.assertEqual(result, hook) - getSiteManager.reset() - manager.clear() + self._assertSMHook(hook) class TestDummyRendererFactory(unittest.TestCase): def _makeOne(self, name, factory): -- cgit v1.2.3 From 6df90b7035cb06412a451881e6f4e31438fc570b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 00:40:11 -0400 Subject: beat down more test failures --- pyramid/config/util.py | 2 +- pyramid/tests/pkgs/exceptionviewapp/views.py | 2 +- pyramid/tests/pkgs/fixtureapp/__init__.py | 2 +- pyramid/tests/pkgs/forbiddenapp/__init__.py | 3 ++- pyramid/tests/test_httpexceptions.py | 4 +++- pyramid/tests/test_integration.py | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyramid/config/util.py b/pyramid/config/util.py index febef4b8f..73bd053bd 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -99,7 +99,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, h.update(bytes_('xhr:%r' % bool(xhr))) if request_method is not None: - if not hasattr(request_method, '__iter__'): + if not is_nonstr_iter(request_method): request_method = (request_method,) request_method = sorted(request_method) def request_method_predicate(context, request): diff --git a/pyramid/tests/pkgs/exceptionviewapp/views.py b/pyramid/tests/pkgs/exceptionviewapp/views.py index 1432618cf..33b97671e 100644 --- a/pyramid/tests/pkgs/exceptionviewapp/views.py +++ b/pyramid/tests/pkgs/exceptionviewapp/views.py @@ -1,5 +1,5 @@ from webob import Response -from models import AnException +from .models import AnException def no(request): return Response('no') diff --git a/pyramid/tests/pkgs/fixtureapp/__init__.py b/pyramid/tests/pkgs/fixtureapp/__init__.py index c74747bfd..27063aae2 100644 --- a/pyramid/tests/pkgs/fixtureapp/__init__.py +++ b/pyramid/tests/pkgs/fixtureapp/__init__.py @@ -5,7 +5,7 @@ def includeme(config): config.add_view('.views.erroneous_view', name='error.html') config.add_view('.views.fixture_view', name='dummyskin.html', request_type='.views.IDummy') - from models import fixture, IFixture + from .models import fixture, IFixture config.registry.registerUtility(fixture, IFixture) config.add_view('.views.fixture_view', name='another.html') diff --git a/pyramid/tests/pkgs/forbiddenapp/__init__.py b/pyramid/tests/pkgs/forbiddenapp/__init__.py index 7001b87f5..888dc9317 100644 --- a/pyramid/tests/pkgs/forbiddenapp/__init__.py +++ b/pyramid/tests/pkgs/forbiddenapp/__init__.py @@ -1,5 +1,6 @@ from webob import Response from pyramid.httpexceptions import HTTPForbidden +from pyramid.compat import bytes_ def x_view(request): # pragma: no cover return Response('this is private!') @@ -9,7 +10,7 @@ def forbidden_view(context, request): result = context.result message = msg + '\n' + str(result) resp = HTTPForbidden() - resp.body = message + resp.body = bytes_(message) return resp def includeme(config): diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index b58145be8..6bc7fbb30 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -1,4 +1,6 @@ import unittest + +from pyramid.compat import bytes_ from pyramid.compat import text_ class Test_exception_response(unittest.TestCase): @@ -277,7 +279,7 @@ class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): if exc.empty_body: self.assertEqual(result, '') else: - self.assertTrue(exc.status in result) + self.assertTrue(bytes_(exc.status) in result) L.append(result) self.assertEqual(len(L), len(status_map)) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 3c970e3bc..ca6301105 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -191,7 +191,7 @@ class TestStaticAppNoSubpath(unittest.TestCase): def _assertBody(self, body, filename): self.assertEqual( - body.replace('\r', ''), + body.replace(r'\r', r''), open(filename, 'rb').read() ) -- cgit v1.2.3 From 2e409a88b60be27f8868c95f0fff806fb6cdc155 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 00:57:12 -0400 Subject: fail right --- pyramid/tests/test_urldispatch.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index 8a4252766..2f6182a66 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -365,9 +365,9 @@ class TestCompileRouteFunctional(unittest.TestCase): {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches('{x}', '/La%20Pe%C3%B1a', {'x':text_('La Pe\xf1a')}) + self.matches('{x}', '/La%20Pe%C3%B1a', {'x':text_(b'La Pe\xf1a')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(text_('La Pe\xf1a'), 'x')}) + {'traverse':(text_(b'La Pe\xf1a'), 'x')}) self.matches('/foo/{id}.html', '/foo/bar.html', {'id':'bar'}) self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def', {'num':'555', 'traverse':('abc', 'def')}) @@ -389,9 +389,9 @@ class TestCompileRouteFunctional(unittest.TestCase): self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) self.matches(':x', '/La%20Pe%C3%B1a', - {'x':text_('La Pe\xf1a')}) + {'x':text_(b'La Pe\xf1a')}) self.matches('*traverse', '/La%20Pe%C3%B1a/x', - {'traverse':(text_('La Pe\xf1a'), 'x')}) + {'traverse':(text_(b'La Pe\xf1a'), 'x')}) self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'}) self.matches('/foo/:id_html', '/foo/bar_html', {'id_html':'bar_html'}) self.matches('zzz/:_', '/zzz/abc', {'_':'abc'}) @@ -410,12 +410,12 @@ class TestCompileRouteFunctional(unittest.TestCase): '/zzz/abc') self.generates('zzz/{x}*traverse', {'x':'abc', 'traverse':'/def/g'}, '/zzz/abc/def/g') - self.generates('/{x}', {'x':text_('/La Pe\xc3\xb1a', 'utf-8')}, + self.generates('/{x}', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, '/%2FLa%20Pe%C3%B1a') - self.generates('/{x}*y', {'x':text_('/La Pe\xc3\xb1a', 'utf-8'), + self.generates('/{x}*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', text_('La Pe\xf1a'))}, + self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/{id}.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/{_}', {'_':'20'}, '/foo/20') @@ -430,12 +430,12 @@ class TestCompileRouteFunctional(unittest.TestCase): '/zzz/abc') self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':'/def/g'}, '/zzz/abc/def/g') - self.generates('/:x', {'x':text_('/La Pe\xc3\xb1a', 'utf-8')}, + self.generates('/:x', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, '/%2FLa%20Pe%C3%B1a') - self.generates('/:x*y', {'x':text_('/La Pe\xc3\xb1a', 'utf-8'), + self.generates('/:x*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), 'y':'/rest/of/path'}, '/%2FLa%20Pe%C3%B1a/rest/of/path') - self.generates('*traverse', {'traverse':('a', text_('La Pe\xf1a'))}, + self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, '/a/La%20Pe%C3%B1a') self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html') self.generates('/foo/:_', {'_':'20'}, '/foo/20') -- cgit v1.2.3 From a84e17d716774ac1bab5f6a0edf422e21eef96c9 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 03:56:29 -0400 Subject: slog --- pyramid/compat.py | 4 +- pyramid/encode.py | 84 ++++++++------------------------- pyramid/testing.py | 35 ++++++++------ pyramid/tests/test_config/test_views.py | 13 ++--- pyramid/tests/test_encode.py | 39 +++++++-------- pyramid/tests/test_httpexceptions.py | 2 +- pyramid/tests/test_paster.py | 7 +++ pyramid/tests/test_scaffolds.py | 2 + pyramid/tests/test_traversal.py | 21 ++++----- pyramid/tests/test_url.py | 24 +++++----- pyramid/urldispatch.py | 4 +- 11 files changed, 100 insertions(+), 135 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index d83205c87..ecb661ce9 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -64,13 +64,15 @@ try: # pragma: no cover from urllib import parse urlparse = parse from urllib.parse import quote as url_quote + from urllib.parse import quote_plus as url_quote_plus from urllib.parse import unquote as url_unquote - url_unquote_text = url_unquote from urllib.parse import urlencode as url_encode from urllib.request import urlopen as url_open + url_unquote_text = url_unquote except ImportError: import urlparse from urllib import quote as url_quote + from urllib import quote_plus as url_quote_plus from urllib import unquote as url_unquote from urllib import urlencode as url_encode from urllib2 import urlopen as url_open diff --git a/pyramid/encode.py b/pyramid/encode.py index ee574a0eb..a259d1414 100644 --- a/pyramid/encode.py +++ b/pyramid/encode.py @@ -1,62 +1,11 @@ -import re - from pyramid.compat import text_type -from pyramid.compat import native_ +from pyramid.compat import binary_type from pyramid.compat import is_nonstr_iter +from pyramid.compat import url_quote as _url_quote +from pyramid.compat import url_quote_plus as quote_plus # bw compat api (dnr) -always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' - 'abcdefghijklmnopqrstuvwxyz' - '0123456789' '_.-') -_safemaps = {} -_must_quote = {} - -def url_quote(s, safe=''): - """quote('abc def') -> 'abc%20def' - - Each part of a URL, e.g. the path info, the query, etc., has a - different set of reserved characters that must be quoted. - - RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists - the following reserved characters:: - - reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | - "$" | "," - - Each of these characters is reserved in some component of a URL, - but not necessarily in all of them. - - Unlike the default version of this function in the Python stdlib, by - default, the url_quote function is intended for quoting individual path - segments instead of an already composed path that might have ``/`` - characters in it. Thus, it *will* encode any ``/`` character it finds in a - string unless ``/`` is marked as 'safe'. It is also slightly faster than - the stdlib version. - """ - cachekey = (safe, always_safe) - try: - safe_map = _safemaps[cachekey] - if not _must_quote[cachekey].search(s): - return s - except KeyError: - safe += always_safe - _must_quote[cachekey] = re.compile(r'[^%s]' % safe) - safe_map = {} - for i in range(256): - c = chr(i) - if c in safe: - safe_map[c] = c - else: - safe_map[c] = '%%%02X' % i - _safemaps[cachekey] = safe_map - res = map(safe_map.__getitem__, s) - return ''.join(res) - -def quote_plus(s, safe=''): - """ Version of stdlib quote_plus which uses faster url_quote """ - if ' ' in s: - s = url_quote(s, safe + ' ') - return s.replace(' ', '+') - return url_quote(s, safe) +def url_quote(s, safe=''): # bw compat api + return _url_quote(s, safe=safe) def urlencode(query, doseq=True): """ @@ -92,21 +41,26 @@ def urlencode(query, doseq=True): prefix = '' for (k, v) in query: - if k.__class__ is text_type: - k = native_(k, 'utf-8') - k = quote_plus(str(k)) + k = _enc(k) + if is_nonstr_iter(v): for x in v: - if x.__class__ is text_type: - x = native_(x, 'utf-8') - x = quote_plus(str(x)) + x = _enc(x) result += '%s%s=%s' % (prefix, k, x) prefix = '&' else: - if v.__class__ is text_type: - v = native_(v, 'utf-8') - v = quote_plus(str(v)) + v = _enc(v) result += '%s%s=%s' % (prefix, k, v) + prefix = '&' return result + +def _enc(val): + cls = val.__class__ + if cls is text_type: + val = val.encode('utf-8') + elif cls is not binary_type: + val = str(val).encode('utf-8') + return quote_plus(val) + diff --git a/pyramid/testing.py b/pyramid/testing.py index 862d31459..89cd39a1b 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -14,6 +14,9 @@ from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import ISession +from pyramid.compat import PY3 +from pyramid.compat import PYPY +from pyramid.compat import class_types from pyramid.config import Configurator from pyramid.decorator import reify from pyramid.httpexceptions import HTTPForbidden @@ -896,21 +899,25 @@ class MockTemplate(object): return self.response def skip_on(*platforms): + skip = False + for platform in platforms: + if skip_on.os_name.startswith(platform): + skip = True + if platform == 'pypy' and PYPY: # pragma: no cover + skip = True + if platform == 'py3' and PY3: # pragma: no cover + skip = True def decorator(func): - def wrapper(*args, **kw): - for platform in platforms: - if skip_on.os_name.startswith(platform): - return - if platform == 'pypy' and skip_on.pypy: # pragma: no cover + if isinstance(func, class_types): + if skip: return None + else: return func + else: + def wrapper(*args, **kw): + if skip: return - return func(*args, **kw) - wrapper.__name__ = func.__name__ - wrapper.__doc__ = func.__doc__ - return wrapper + return func(*args, **kw) + wrapper.__name__ = func.__name__ + wrapper.__doc__ = func.__doc__ + return wrapper return decorator skip_on.os_name = os.name # for testing -try: # pragma: no cover - import __pypy__ - skip_on.pypy = True -except ImportError: - skip_on.pypy = False diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 141b60e87..9f2ff9b6f 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -5,6 +5,7 @@ from pyramid.tests.test_config import IDummy from pyramid.tests.test_config import dummy_view +from pyramid.compat import im_func from pyramid.exceptions import ConfigurationError from pyramid.exceptions import ConfigurationExecutionError from pyramid.exceptions import ConfigurationConflictError @@ -3245,12 +3246,12 @@ class Test_preserve_view_attrs(unittest.TestCase): self.assertTrue(view1.__doc__ is view2.__doc__) self.assertTrue(view1.__module__ is view2.__module__) self.assertTrue(view1.__name__ is view2.__name__) - self.assertTrue(view1.__call_permissive__.im_func is - view2.__call_permissive__.im_func) - self.assertTrue(view1.__permitted__.im_func is - view2.__permitted__.im_func) - self.assertTrue(view1.__predicated__.im_func is - view2.__predicated__.im_func) + self.assertTrue(getattr(view1.__call_permissive__, im_func) is + getattr(view2.__call_permissive__, im_func)) + self.assertTrue(getattr(view1.__permitted__, im_func) is + getattr(view2.__permitted__, im_func)) + self.assertTrue(getattr(view1.__predicated__, im_func) is + getattr(view2.__predicated__, im_func)) class TestStaticURLInfo(unittest.TestCase): diff --git a/pyramid/tests/test_encode.py b/pyramid/tests/test_encode.py index 738efeea2..ccc8f16e3 100644 --- a/pyramid/tests/test_encode.py +++ b/pyramid/tests/test_encode.py @@ -1,5 +1,6 @@ import unittest from pyramid.compat import text_ +from pyramid.compat import native_ class UrlEncodeTests(unittest.TestCase): def _callFUT(self, query, doseq=False): @@ -11,17 +12,17 @@ class UrlEncodeTests(unittest.TestCase): self.assertEqual(result, 'a=1&b=2') def test_unicode_key(self): - la = text_('LaPe\xc3\xb1a', 'utf-8') + la = text_(b'LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([(la, 1), ('b',2)]) self.assertEqual(result, 'LaPe%C3%B1a=1&b=2') def test_unicode_val_single(self): - la = text_('LaPe\xc3\xb1a', 'utf-8') + la = text_(b'LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([('a', la), ('b',2)]) self.assertEqual(result, 'a=LaPe%C3%B1a&b=2') def test_unicode_val_multiple(self): - la = [text_('LaPe\xc3\xb1a', 'utf-8')] * 2 + la = [text_(b'LaPe\xc3\xb1a', 'utf-8')] * 2 result = self._callFUT([('a', la), ('b',2)], doseq=True) self.assertEqual(result, 'a=LaPe%C3%B1a&a=LaPe%C3%B1a&b=2') @@ -30,6 +31,10 @@ class UrlEncodeTests(unittest.TestCase): result = self._callFUT([('a', s)], doseq=True) self.assertEqual(result, 'a=1&a=2') + def test_with_spaces(self): + result = self._callFUT([('a', '123 456')], doseq=True) + self.assertEqual(result, 'a=123+456') + def test_dict(self): result = self._callFUT({'a':1}) self.assertEqual(result, 'a=1') @@ -39,29 +44,17 @@ class URLQuoteTests(unittest.TestCase): from pyramid.encode import url_quote return url_quote(val, safe) - def test_it_default(self): - la = 'La/Pe\xc3\xb1a' + def test_it_bytes(self): + la = b'La/Pe\xc3\xb1a' result = self._callFUT(la) self.assertEqual(result, 'La%2FPe%C3%B1a') - def test_it_with_safe(self): - la = 'La/Pe\xc3\xb1a' - result = self._callFUT(la, '/') - self.assertEqual(result, 'La/Pe%C3%B1a') - -class TestQuotePlus(unittest.TestCase): - def _callFUT(self, val, safe=''): - from pyramid.encode import quote_plus - return quote_plus(val, safe) - - def test_it_default(self): - la = 'La Pe\xc3\xb1a' + def test_it_native(self): + la = native_(b'La/Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) - self.assertEqual(result, 'La+Pe%C3%B1a') - + self.assertEqual(result, 'La%2FPe%C3%B1a') + def test_it_with_safe(self): - la = 'La /Pe\xc3\xb1a' + la = b'La/Pe\xc3\xb1a' result = self._callFUT(la, '/') - self.assertEqual(result, 'La+/Pe%C3%B1a') - - + self.assertEqual(result, 'La/Pe%C3%B1a') diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index 6bc7fbb30..927d27733 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -277,7 +277,7 @@ class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): exc.content_type = content_type result = list(exc(environ, start_response))[0] if exc.empty_body: - self.assertEqual(result, '') + self.assertEqual(result, b'') else: self.assertTrue(bytes_(exc.status) in result) L.append(result) diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index f46aca49d..a697b5691 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1,5 +1,7 @@ import unittest +from pyramid.testing import skip_on +@skip_on('py3') class TestPShellCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PShellCommand @@ -246,6 +248,7 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) +@skip_on('py3') class TestPRoutesCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PRoutesCommand @@ -372,6 +375,7 @@ class TestPRoutesCommand(unittest.TestCase): result = command._get_mapper(registry) self.assertEqual(result.__class__, RoutesMapper) +@skip_on('py3') class TestPViewsCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PViewsCommand @@ -824,6 +828,7 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[8], ' pyramid.tests.test_paster.view.call') self.assertEqual(L[9], ' view predicates (predicate = x)') +@skip_on('py3') class TestGetApp(unittest.TestCase): def _callFUT(self, config_file, section_name, loadapp): from pyramid.paster import get_app @@ -859,6 +864,7 @@ class TestGetApp(unittest.TestCase): self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) +@skip_on('py3') class TestBootstrap(unittest.TestCase): def _callFUT(self, config_uri, request=None): from pyramid.paster import bootstrap @@ -898,6 +904,7 @@ class TestBootstrap(unittest.TestCase): self.assertEqual(result['root'], self.root) self.assert_('closer' in result) +@skip_on('py3') class TestPTweensCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PTweensCommand diff --git a/pyramid/tests/test_scaffolds.py b/pyramid/tests/test_scaffolds.py index ed2c5a993..265e20c3b 100644 --- a/pyramid/tests/test_scaffolds.py +++ b/pyramid/tests/test_scaffolds.py @@ -1,5 +1,7 @@ import unittest +from pyramid.testing import skip_on +@skip_on('py3') class TestPyramidTemplate(unittest.TestCase): def _getTargetClass(self): from pyramid.scaffolds import PyramidTemplate diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index cd48d0268..07f7515eb 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -4,6 +4,7 @@ from pyramid.testing import cleanUp from pyramid.compat import text_ from pyramid.compat import native_ from pyramid.compat import text_type +from pyramid.compat import url_quote class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): @@ -42,18 +43,16 @@ class TraversalPathTests(unittest.TestCase): self.assertEqual(result2, (text_('foo'), text_('bar'))) def test_utf8(self): - import urllib - la = 'La Pe\xc3\xb1a' - encoded = urllib.quote(la) + la = b'La Pe\xc3\xb1a' + encoded = url_quote(la) decoded = text_(la, 'utf-8') path = '/'.join([encoded, encoded]) self.assertEqual(self._callFUT(path), (decoded, decoded)) def test_utf16(self): from pyramid.exceptions import URLDecodeError - import urllib - la = text_('La Pe\xc3\xb1a', 'utf-8').encode('utf-16') - encoded = urllib.quote(la) + la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16') + encoded = url_quote(la) path = '/'.join([encoded, encoded]) self.assertRaises(URLDecodeError, self._callFUT, path) @@ -67,7 +66,7 @@ class TraversalPathTests(unittest.TestCase): self.assertEqual(self._callFUT(path), (text_('abc'),)) def test_unicode_undecodeable_to_ascii(self): - path = text_('/La Pe\xc3\xb1a', 'utf-8') + path = text_(b'/La Pe\xc3\xb1a', 'utf-8') self.assertRaises(UnicodeEncodeError, self._callFUT, path) class ResourceTreeTraverserTests(unittest.TestCase): @@ -604,7 +603,7 @@ class FindResourceTests(unittest.TestCase): root = DummyContext(unprintable) unprintable.__parent__ = root unprintable.__name__ = text_( - '/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') + b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') root.__parent__ = None root.__name__ = None traverser = ResourceTreeTraverser @@ -757,7 +756,7 @@ class QuotePathSegmentTests(unittest.TestCase): return quote_path_segment(s) def test_unicode(self): - la = text_('/La Pe\xc3\xb1a', 'utf-8') + la = text_(b'/La Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) self.assertEqual(result, '%2FLa%20Pe%C3%B1a') @@ -774,7 +773,7 @@ class QuotePathSegmentTests(unittest.TestCase): def test_long(self): from pyramid.compat import long import sys - s = long(sys.maxint + 1) + s = long(sys.maxsize + 1) result = self._callFUT(s) expected = str(s) self.assertEqual(result, expected) @@ -847,7 +846,7 @@ class TraversalContextURLTests(unittest.TestCase): root.__name__ = None one = DummyContext() one.__parent__ = root - one.__name__ = text_('La Pe\xc3\xb1a', 'utf-8') + one.__name__ = text_(b'La Pe\xc3\xb1a', 'utf-8') two = DummyContext() two.__parent__ = one two.__name__ = 'La Pe\xc3\xb1a' diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 22eacd758..aa6fa30dd 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -49,7 +49,7 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_unicode_in_element_names(self): request = self._makeOne() self._registerContextURL(request.registry) - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') context = DummyContext() result = request.resource_url(context, uc) self.assertEqual(result, @@ -74,7 +74,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query={'a':uc}) self.assertEqual(result, 'http://example.com/context/a?a=La+Pe%C3%B1a') @@ -83,9 +83,9 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query=[('a', 'hi there'), - ('b', uc)]) + ('b', uc)]) self.assertEqual(result, 'http://example.com/context/a?a=hi+there&b=La+Pe%C3%B1a') @@ -118,7 +118,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, anchor=uc) self.assertEqual(result, 'http://example.com/context/#La Pe\xc3\xb1a') @@ -173,7 +173,7 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1#foo') @@ -191,7 +191,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - anchor = text_('La Pe\xc3\xb1a', 'utf-8') + anchor = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.route_url('flub', _anchor=anchor) self.assertEqual(result, 'http://example.com:5432/1/2/3#La Pe\xc3\xb1a') @@ -282,7 +282,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -295,7 +295,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo"), + _anchor=text_(b"foo"), _route_name='bar') self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -310,7 +310,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '/script_name' request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_path('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/script_name/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_elements(self): @@ -321,7 +321,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '' result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_script_name(self): @@ -332,7 +332,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/foo/1/2/3/extra1/extra2?a=1#foo') def test_static_url_staticurlinfo_notfound(self): diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 696b69f89..b11bcefcb 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -8,7 +8,7 @@ from pyramid.compat import url_unquote_text from pyramid.compat import native_ from pyramid.compat import text_type from pyramid.compat import is_nonstr_iter -from pyramid.encode import url_quote +from pyramid.compat import url_quote from pyramid.exceptions import URLDecodeError from pyramid.traversal import traversal_path from pyramid.traversal import quote_path_segment @@ -163,7 +163,7 @@ def _compile_route(route): v = '/'.join([quote_path_segment(x) for x in v]) elif k != star: try: - v = url_quote(v) + v = url_quote(v, safe='') except TypeError: pass newdict[k] = v -- cgit v1.2.3 From 47844249ca11e1b0b031d8c7a036ff9fa2a125f9 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 04:15:10 -0400 Subject: fix failing tests in router.py --- pyramid/tests/test_router.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 1e3261b77..7ba4d5722 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -188,8 +188,8 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertTrue('/' in why[0], why) - self.assertFalse('debug_notfound' in why[0]) + self.assertTrue('/' in why.args[0], why) + self.assertFalse('debug_notfound' in why.args[0]) self.assertEqual(len(logger.messages), 0) def test_traverser_raises_notfound_class(self): @@ -209,7 +209,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertTrue('foo' in why[0], why) + self.assertTrue('foo' in why.args[0], why) def test_traverser_raises_forbidden_class(self): from pyramid.httpexceptions import HTTPForbidden @@ -229,7 +229,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPForbidden, router, environ, start_response) - self.assertTrue('foo' in why[0], why) + self.assertTrue('foo' in why.args[0], why) def test_call_no_view_registered_no_isettings(self): from pyramid.httpexceptions import HTTPNotFound @@ -240,8 +240,8 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertTrue('/' in why[0], why) - self.assertFalse('debug_notfound' in why[0]) + self.assertTrue('/' in why.args[0], why) + self.assertFalse('debug_notfound' in why.args[0]) self.assertEqual(len(logger.messages), 0) def test_call_no_view_registered_debug_notfound_false(self): @@ -254,8 +254,8 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertTrue('/' in why[0], why) - self.assertFalse('debug_notfound' in why[0]) + self.assertTrue('/' in why.args[0], why) + self.assertFalse('debug_notfound' in why.args[0]) self.assertEqual(len(logger.messages), 0) def test_call_no_view_registered_debug_notfound_true(self): @@ -270,15 +270,15 @@ class TestRouter(unittest.TestCase): why = exc_raised(HTTPNotFound, router, environ, start_response) self.assertTrue( "debug_notfound of url http://localhost:8080/; path_info: '/', " - "context:" in why[0]) - self.assertTrue("view_name: '', subpath: []" in why[0]) - self.assertTrue('http://localhost:8080' in why[0], why) + "context:" in why.args[0]) + self.assertTrue("view_name: '', subpath: []" in why.args[0]) + self.assertTrue('http://localhost:8080' in why.args[0], why) self.assertEqual(len(logger.messages), 1) message = logger.messages[0] self.assertTrue('of url http://localhost:8080' in message) self.assertTrue("path_info: '/'" in message) - self.assertTrue('DummyContext instance at' in message) + self.assertTrue('DummyContext' in message) self.assertTrue("view_name: ''" in message) self.assertTrue("subpath: []" in message) @@ -428,7 +428,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPForbidden, router, environ, start_response) - self.assertEqual(why[0], 'unauthorized') + self.assertEqual(why.args[0], 'unauthorized') def test_call_view_raises_notfound(self): from zope.interface import Interface @@ -448,7 +448,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertEqual(why[0], 'notfound') + self.assertEqual(why.args[0], 'notfound') def test_call_view_raises_response_cleared(self): from zope.interface import Interface @@ -737,7 +737,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) - self.assertTrue('from root factory' in why[0]) + self.assertTrue('from root factory' in why.args[0]) def test_root_factory_raises_forbidden(self): from pyramid.interfaces import IRootFactory @@ -755,7 +755,7 @@ class TestRouter(unittest.TestCase): router = self._makeOne() start_response = DummyStartResponse() why = exc_raised(HTTPForbidden, router, environ, start_response) - self.assertTrue('from root factory' in why[0]) + self.assertTrue('from root factory' in why.args[0]) def test_root_factory_exception_propagating(self): from pyramid.interfaces import IRootFactory -- cgit v1.2.3 From 44ebac8a36467f2ad65cd40b906c576e4aca0330 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 04:15:40 -0400 Subject: take advantage of as-syntax --- pyramid/tweens.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyramid/tweens.py b/pyramid/tweens.py index e40f5102f..65d7c3919 100644 --- a/pyramid/tweens.py +++ b/pyramid/tweens.py @@ -15,11 +15,11 @@ def excview_tween_factory(handler, registry): attrs = request.__dict__ try: response = handler(request) - except Exception: + except Exception as exc: # WARNING: do not assign the result of sys.exc_info() to a # local var here, doing so will cause a leak attrs['exc_info'] = sys.exc_info() - exc = attrs['exception'] = attrs['exc_info'][1] + attrs['exception'] = exc # clear old generated request.response, if any; it may # have been mutated by the view, and its state is not # sane (e.g. caching headers) -- cgit v1.2.3 From e1258eef6ed47831a8201e6b53ca341a901ad5c4 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 04:22:52 -0400 Subject: fix signed_serialize and signed_deserialize on py3 --- pyramid/session.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pyramid/session.py b/pyramid/session.py index cd685e51c..a59f9c628 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -10,6 +10,8 @@ from zope.interface import implementer from pyramid.compat import pickle from pyramid.compat import PY3 from pyramid.compat import text_ +from pyramid.compat import bytes_ +from pyramid.compat import native_ from pyramid.interfaces import ISession def manage_accessed(wrapped): @@ -234,8 +236,8 @@ def signed_serialize(data, secret): response.set_cookie('signed_cookie', cookieval) """ pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) - sig = hmac.new(secret, pickled, sha1).hexdigest() - return sig + base64.standard_b64encode(pickled) + sig = hmac.new(bytes_(secret), pickled, sha1).hexdigest() + return sig + native_(base64.b64encode(pickled)) def signed_deserialize(serialized, secret, hmac=hmac): """ Deserialize the value returned from ``signed_serialize``. If @@ -253,12 +255,12 @@ def signed_deserialize(serialized, secret, hmac=hmac): # hmac parameterized only for unit tests try: input_sig, pickled = (serialized[:40], - base64.standard_b64decode(serialized[40:])) + base64.b64decode(bytes_(serialized[40:]))) except (binascii.Error, TypeError) as e: # Badly formed data can make base64 die raise ValueError('Badly formed base64 data: %s' % e) - sig = hmac.new(secret, pickled, sha1).hexdigest() + sig = hmac.new(bytes_(secret), pickled, sha1).hexdigest() if len(sig) != len(input_sig): raise ValueError('Wrong signature length') -- cgit v1.2.3 From 55fb96a0411d5a2b14360ce075eb9e087aedc310 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 04:44:02 -0400 Subject: fix all request tests except the ones which invoke call_app_with_subpath --- pyramid/request.py | 4 ++-- pyramid/tests/test_request.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pyramid/request.py b/pyramid/request.py index cfab88860..6b77b09e9 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -11,8 +11,8 @@ from pyramid.interfaces import ISessionFactory from pyramid.interfaces import IResponseFactory from pyramid.compat import json -from pyramid.compat import native_ from pyramid.compat import iterkeys_, itervalues_, iteritems_ +from pyramid.compat import text_ from pyramid.exceptions import ConfigurationError from pyramid.decorator import reify from pyramid.response import Response @@ -362,7 +362,7 @@ class Request(BaseRequest, DeprecatedRequestMethodsMixin, URLMethodsMixin, @property def json_body(self): - return json.loads(self.body, encoding=self.charset) + return json.loads(text_(self.body, self.charset)) def route_request_iface(name, bases=()): # zope.interface treats the __name__ as the __doc__ and changes __name__ diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 2dadb7d52..c731edb7f 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -2,6 +2,8 @@ import unittest from pyramid import testing from pyramid.compat import text_ +from pyramid.compat import bytes_ +from pyramid.compat import iteritems_, iterkeys_, itervalues_ class TestRequest(unittest.TestCase): def setUp(self): @@ -52,7 +54,7 @@ class TestRequest(unittest.TestCase): } request = self._makeOne(environ) request.charset = None - self.assertEqual(request.GET['la'], text_('La Pe\xf1a')) + self.assertEqual(request.GET['la'], text_(b'La Pe\xf1a')) def test_class_implements(self): from pyramid.interfaces import IRequest @@ -249,8 +251,8 @@ class TestRequest(unittest.TestCase): from pyramid.compat import json request = self._makeOne({'REQUEST_METHOD':'POST'}) request.charset = 'latin-1' - la = text_('La Pe\xc3\xb1a', 'utf-8') - body = json.dumps({'a':la}, encoding='latin-1') + la = text_(b'La Pe\xc3\xb1a', 'utf-8') + body = bytes_(json.dumps({'a':la}), 'latin-1') request.body = body self.assertEqual(request.json_body, {'a':la}) @@ -324,17 +326,17 @@ class TestRequestDeprecatedMethods(unittest.TestCase): def test_iteritems(self): environ = {'zooma':1} inst = self._makeOne(environ) - self.assertEqual(list(inst.iteritems()), list(environ.iteritems())) + self.assertEqual(list(inst.iteritems()), list(iteritems_(environ))) def test_iterkeys(self): environ = {'zooma':1} inst = self._makeOne(environ) - self.assertEqual(list(inst.iterkeys()), list(environ.iterkeys())) + self.assertEqual(list(inst.iterkeys()), list(iterkeys_(environ))) def test_itervalues(self): environ = {'zooma':1} inst = self._makeOne(environ) - self.assertEqual(list(inst.itervalues()), list(environ.itervalues())) + self.assertEqual(list(inst.itervalues()), list(itervalues_(environ))) def test_keys(self): environ = {'zooma':1} -- cgit v1.2.3 From 7975a185be516e1d721afff6a98fdfb5110281e2 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 04:59:51 -0400 Subject: more ridiculousness --- pyramid/config/__init__.py | 5 +++-- pyramid/config/util.py | 6 +++--- pyramid/tests/test_config/test_testing.py | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index 527745ecf..6f1d71d21 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -912,8 +912,9 @@ class ActionState(object): except: t, v, tb = sys.exc_info() try: - reraise( - ConfigurationExecutionError(t, v, info), None, tb) + reraise(None, + ConfigurationExecutionError(t, v, info), + tb) finally: del t, v, tb finally: diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 73bd053bd..498fe7629 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -115,7 +115,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, try: path_info_val = re.compile(path_info) except re.error as why: - raise ConfigurationError(why[0]) + raise ConfigurationError(why.args[0]) def path_info_predicate(context, request): return path_info_val.match(request.path_info) is not None text = "path_info = %s" @@ -150,7 +150,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, try: header_val = re.compile(header_val) except re.error as why: - raise ConfigurationError(why[0]) + raise ConfigurationError(why.args[0]) if header_val is None: text = "header %s" % header_name else: @@ -198,7 +198,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, match_param = {match_param: match_param_val} text = "match_param %s" % match_param def match_param_predicate(context, request): - for k, v in match_param.iteritems(): + for k, v in match_param.items(): if request.matchdict.get(k) != v: return False return True diff --git a/pyramid/tests/test_config/test_testing.py b/pyramid/tests/test_config/test_testing.py index 7f8c2c2b2..6c048b46d 100644 --- a/pyramid/tests/test_config/test_testing.py +++ b/pyramid/tests/test_config/test_testing.py @@ -1,5 +1,6 @@ import unittest +from pyramid.compat import text_ from pyramid.tests.test_config import IDummy class TestingConfiguratorMixinTests(unittest.TestCase): @@ -35,14 +36,14 @@ class TestingConfiguratorMixinTests(unittest.TestCase): self.assertEqual(result['context'], ob1) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'ob1',)) + self.assertEqual(result['traversed'], (text_('ob1'),)) self.assertEqual(result['virtual_root'], ob1) self.assertEqual(result['virtual_root_path'], ()) result = adapter(DummyRequest({'PATH_INFO':'/ob2'})) self.assertEqual(result['context'], ob2) self.assertEqual(result['view_name'], '') self.assertEqual(result['subpath'], ()) - self.assertEqual(result['traversed'], (u'ob2',)) + self.assertEqual(result['traversed'], (text_('ob2'),)) self.assertEqual(result['virtual_root'], ob2) self.assertEqual(result['virtual_root_path'], ()) self.assertRaises(KeyError, adapter, DummyRequest({'PATH_INFO':'/ob3'})) -- cgit v1.2.3 From e0549d7bafa289cb01efe00eb7a904035806013d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 05:01:48 -0400 Subject: fix tests on py2 --- pyramid/config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index 6f1d71d21..e90ffcf3b 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -912,7 +912,7 @@ class ActionState(object): except: t, v, tb = sys.exc_info() try: - reraise(None, + reraise(ConfigurationExecutionError, ConfigurationExecutionError(t, v, info), tb) finally: -- cgit v1.2.3 From f12147b76adefb2c70fd7ae453a71f8206793e7d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 05:06:24 -0400 Subject: fix asset tests on py3 --- pyramid/tests/test_config/test_assets.py | 9 +++++---- pyramid/tests/test_integration.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 876a921b4..8d9ab5825 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -165,7 +165,7 @@ class TestOverrideProvider(unittest.TestCase): here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, resource_name)) with provider.get_resource_stream(None, resource_name) as result: - self.assertEqual(result.read().replace('\r', ''), expected) + self.assertEqual(result.read().replace(b'\r', b''), expected) def test_get_resource_string_no_overrides(self): import os @@ -175,7 +175,7 @@ class TestOverrideProvider(unittest.TestCase): here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, resource_name)) result = provider.get_resource_string(None, resource_name) - self.assertEqual(result.replace('\r', ''), expected) + self.assertEqual(result.replace(b'\r', b''), expected) def test_has_resource_no_overrides(self): resource_name = 'test_assets.py' @@ -422,7 +422,7 @@ class TestPackageOverrides(unittest.TestCase): here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, 'test_assets.py')) with po.get_stream('whatever') as stream: - self.assertEqual(stream.read().replace('\r', ''), + self.assertEqual(stream.read().replace(b'\r', b''), expected) def test_get_stream_file_doesnt_exist(self): @@ -442,7 +442,8 @@ class TestPackageOverrides(unittest.TestCase): po.overrides= overrides here = os.path.dirname(os.path.abspath(__file__)) expected = read_(os.path.join(here, 'test_assets.py')) - self.assertEqual(po.get_string('whatever').replace('\r', ''), expected) + self.assertEqual(po.get_string('whatever').replace(b'\r', b''), + expected) def test_get_string_file_doesnt_exist(self): overrides = [ DummyOverride(None), DummyOverride( diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index ca6301105..381d52aae 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -191,7 +191,7 @@ class TestStaticAppNoSubpath(unittest.TestCase): def _assertBody(self, body, filename): self.assertEqual( - body.replace(r'\r', r''), + body.replace(b'\r', b''), open(filename, 'rb').read() ) -- cgit v1.2.3 From 0e131e30da1c5ce9c35965252a5718f1b2660eea Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 05:30:03 -0400 Subject: fix test_renderers tests on py3 --- pyramid/renderers.py | 4 ++-- pyramid/tests/test_renderers.py | 8 ++++---- setup.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 2d420f67a..88cb869a5 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -149,7 +149,7 @@ def json_renderer_factory(info): def string_renderer_factory(info): def _render(value, system): if not isinstance(value, string_types): - value = native_(value, 'utf-8') + value = str(value) request = system.get('request') if request is not None: response = request.response @@ -441,7 +441,7 @@ class RendererHelper(object): result = '' if isinstance(result, text_type): - response.unicode_body = result + response.text = result else: response.body = result diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 758331788..1054dcb1c 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -453,14 +453,14 @@ class Test_string_renderer_factory(unittest.TestCase): def test_with_request_content_type_notset(self): request = testing.DummyRequest() renderer = self._callFUT(None) - renderer(None, {'request':request}) + renderer('', {'request':request}) self.assertEqual(request.response.content_type, 'text/plain') def test_with_request_content_type_set(self): request = testing.DummyRequest() request.response.content_type = 'text/mishmash' renderer = self._callFUT(None) - renderer(None, {'request':request}) + renderer('', {'request':request}) self.assertEqual(request.response.content_type, 'text/mishmash') @@ -600,7 +600,7 @@ class TestRendererHelper(unittest.TestCase): self._registerResponseFactory() request = None helper = self._makeOne('loo.foo') - response = helper._make_response('abc', request) + response = helper._make_response(b'abc', request) self.assertEqual(response.__class__.__name__, 'ResponseFactory') self.assertEqual(response.body, b'abc') @@ -687,7 +687,7 @@ class TestRendererHelper(unittest.TestCase): self.config.registry.registerUtility(ResponseFactory, IResponseFactory) request = testing.DummyRequest() helper = self._makeOne('loo.foo') - response = helper._make_response('abc', request) + response = helper._make_response(b'abc', request) self.assertEqual(response.__class__, ResponseFactory) self.assertEqual(response.body, b'abc') diff --git a/setup.py b/setup.py index 4213bb628..010dd06cc 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ except IOError: install_requires=[ 'Chameleon >= 1.2.3', 'Mako >= 0.3.6', # strict_undefined - 'WebOb >= 1.0.2', # no "default_charset"; request.script_name doesnt error + 'WebOb >= 1.2dev', # response.text / py3 compat 'repoze.lru', 'setuptools', 'zope.interface >= 3.8.0', # has zope.interface.registry -- cgit v1.2.3 From 10aaa260624def9a41f3565830f2230f9bfde1ae Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 05:34:47 -0400 Subject: fix test_config/test_views on py3 --- pyramid/config/views.py | 2 +- pyramid/tests/test_config/test_views.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 326aa801e..726223fd9 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1064,7 +1064,7 @@ class ViewsConfiguratorMixin(object): 'view', context, name, request_type, IView, containment, request_param, request_method, route_name, attr, xhr, accept, header, path_info, match_param] - discriminator.extend(sorted(custom_predicates)) + discriminator.extend(sorted([hash(x) for x in custom_predicates])) discriminator = tuple(discriminator) self.action(discriminator, register) diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 9f2ff9b6f..ce8d01f38 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -353,7 +353,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IViewClassifier from pyramid.interfaces import IMultiView phash = md5() - phash.update('xhr:True') + phash.update(b'xhr:True') view = lambda *arg: 'NOT OK' view.__phash__ = phash.hexdigest() config = self._makeOne(autocommit=True) @@ -377,7 +377,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): from pyramid.interfaces import IExceptionViewClassifier from pyramid.interfaces import IMultiView phash = md5() - phash.update('xhr:True') + phash.update(b'xhr:True') view = lambda *arg: 'NOT OK' view.__phash__ = phash.hexdigest() config = self._makeOne(autocommit=True) @@ -2656,7 +2656,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(request.wrapped_body, inner_response.body) self.assertEqual(request.wrapped_view.__original_view__, inner_view) - return Response('outer ' + request.wrapped_body) + return Response(b'outer ' + request.wrapped_body) self.config.registry.registerAdapter( outer_view, (IViewClassifier, None, None), IView, 'owrap') deriver = self._makeOne(viewname='inner', -- cgit v1.2.3 From fbd01aca7c6d9ee97a35070398c85192dec3b2af Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 05:48:36 -0400 Subject: fix test_init tests for py3 --- pyramid/config/__init__.py | 12 ++++++++++-- pyramid/tests/test_config/test_init.py | 14 +++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index e90ffcf3b..02a78445e 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -16,6 +16,7 @@ from pyramid.authorization import ACLAuthorizationPolicy from pyramid.compat import text_ from pyramid.compat import reraise from pyramid.compat import string_types +from pyramid.compat import PY3 from pyramid.events import ApplicationCreated from pyramid.exceptions import ConfigurationConflictError from pyramid.exceptions import ConfigurationError @@ -659,7 +660,10 @@ class Configurator( c, action_wrap = c if action_wrap: c = action_method(c) - m = types.MethodType(c, self, self.__class__) + if PY3: + m = types.MethodType(c, self) + else: + m = types.MethodType(c, self, self.__class__) return m @classmethod @@ -1000,7 +1004,11 @@ def resolveConflicts(actions): # We need to sort the actions by the paths so that the shortest # path with a given prefix comes first: - dups.sort() + def allbutfunc(stupid): + # f me with a shovel, py3 cant cope with sorting when the + # callable function is in the list + return stupid[0:2] + stupid[3:] + dups.sort(key=allbutfunc) (basepath, i, callable, args, kw, baseinfo) = dups[0] output.append( (i, discriminator, callable, args, kw, basepath, baseinfo) diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 302a185f2..b5eb85d59 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -3,6 +3,8 @@ import unittest import os from pyramid.compat import PYPY +from pyramid.compat import im_func +from pyramid.testing import skip_on from pyramid.tests.test_config import dummy_tween_factory from pyramid.tests.test_config import dummy_include @@ -927,6 +929,7 @@ pyramid.tests.test_config.dummy_include2""", self.assertTrue("@view_config(name='two', renderer='string')" in which) + @skip_on('py3') def test_hook_zca(self): from zope.component import getSiteManager def foo(): @@ -940,6 +943,7 @@ pyramid.tests.test_config.dummy_include2""", finally: getSiteManager.reset() + @skip_on('py3') def test_unhook_zca(self): from zope.component import getSiteManager def foo(): @@ -1067,7 +1071,7 @@ pyramid.tests.test_config.dummy_include2""", directives = {'foo':(foo, True)} config.registry._directives = directives foo_meth = config.foo - self.assertTrue(foo_meth.im_func.__docobj__ is foo) + self.assertTrue(getattr(foo_meth, im_func).__docobj__ is foo) def test___getattr__matches_no_action_wrap(self): config = self._makeOne() @@ -1075,7 +1079,7 @@ pyramid.tests.test_config.dummy_include2""", directives = {'foo':(foo, False)} config.registry._directives = directives foo_meth = config.foo - self.assertTrue(foo_meth.im_func is foo) + self.assertTrue(getattr(foo_meth, im_func) is foo) class TestConfiguratorDeprecatedFeatures(unittest.TestCase): def setUp(self): @@ -1306,7 +1310,7 @@ class TestConfigurator_add_directive(unittest.TestCase): config = self.config config.add_directive( 'dummy_extend', 'pyramid.tests.test_config.dummy_extend') - self.assert_(hasattr(config, 'dummy_extend')) + self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state self.assertEqual( @@ -1319,7 +1323,7 @@ class TestConfigurator_add_directive(unittest.TestCase): config = self.config config.add_directive( 'dummy_extend', dummy_extend) - self.assert_(hasattr(config, 'dummy_extend')) + self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state self.assertEqual( @@ -1333,7 +1337,7 @@ class TestConfigurator_add_directive(unittest.TestCase): 'dummy_extend', dummy_extend) config.add_directive( 'dummy_extend', dummy_extend2) - self.assert_(hasattr(config, 'dummy_extend')) + self.assertTrue(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') after = config.action_state self.assertEqual( -- cgit v1.2.3 From 0ce501a771feaed09d19ebf45ba514648d7f819b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 06:09:56 -0400 Subject: fix adapter tests for py3 --- pyramid/tests/test_config/test_adapters.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pyramid/tests/test_config/test_adapters.py b/pyramid/tests/test_config/test_adapters.py index ff1ce52a1..84b7119cf 100644 --- a/pyramid/tests/test_config/test_adapters.py +++ b/pyramid/tests/test_config/test_adapters.py @@ -1,5 +1,6 @@ import unittest +from pyramid.compat import PY3 from pyramid.tests.test_config import IDummy class AdaptersConfiguratorMixinTests(unittest.TestCase): @@ -103,8 +104,11 @@ class AdaptersConfiguratorMixinTests(unittest.TestCase): def test_add_response_adapter_dottednames(self): from pyramid.interfaces import IResponse config = self._makeOne(autocommit=True) - config.add_response_adapter('pyramid.response.Response', - 'types.StringType') + if PY3: # pragma: no cover + str_name = 'builtins.str' + else: + str_name = '__builtin__.str' + config.add_response_adapter('pyramid.response.Response', str_name) result = config.registry.queryAdapter('foo', IResponse) - self.assertTrue(result.body, 'foo') + self.assertTrue(result.body, b'foo') -- cgit v1.2.3 From 466ab45b775f3010e388cb849f5a8c8beb05d30b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 06:12:05 -0400 Subject: fix chameleon_zpt test --- pyramid/tests/test_chameleon_zpt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyramid/tests/test_chameleon_zpt.py b/pyramid/tests/test_chameleon_zpt.py index 6a38bd329..1a8e6767e 100644 --- a/pyramid/tests/test_chameleon_zpt.py +++ b/pyramid/tests/test_chameleon_zpt.py @@ -156,8 +156,8 @@ class RenderTemplateToResponseTests(Base, unittest.TestCase): result = self._callFUT(minimal) from webob import Response self.assertTrue(isinstance(result, Response)) - self.assertEqual(result.app_iter[0].rstrip('\n'), - '
\n
') + self.assertEqual(result.app_iter[0].rstrip(b'\n'), + b'
\n
') self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) -- cgit v1.2.3 From 45009ceddd0ecc7a41f8f2d8336e24f36e51f58d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 07:28:35 -0400 Subject: fix authentication module tests on py3 --- pyramid/authentication.py | 22 ++++++++++++++-------- pyramid/compat.py | 5 +++++ pyramid/tests/test_authentication.py | 32 ++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index a84983447..e38c984b3 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -10,6 +10,7 @@ from zope.interface import implementer from pyramid.compat import long from pyramid.compat import text_type +from pyramid.compat import binary_type from pyramid.compat import url_unquote from pyramid.compat import url_quote from pyramid.compat import bytes_ @@ -389,10 +390,10 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): return self.cookie.forget(request) def b64encode(v): - return base64.b64encode(v).strip().replace('\n', '') + return base64.b64encode(bytes_(v)).strip().replace(b'\n', b'') def b64decode(v): - return base64.b64decode(v) + return base64.b64decode(bytes_(v)) # this class licensed under the MIT license (stolen from Paste) class AuthTicket(object): @@ -507,9 +508,9 @@ def calculate_digest(ip, timestamp, secret, userid, tokens, user_data): tokens = bytes_(tokens, 'utf-8') user_data = bytes_(user_data, 'utf-8') digest0 = md5( - encode_ip_timestamp(ip, timestamp) + secret + userid + '\0' - + tokens + '\0' + user_data).hexdigest() - digest = md5(digest0 + secret).hexdigest() + encode_ip_timestamp(ip, timestamp) + secret + userid + b'\0' + + tokens + b'\0' + user_data).hexdigest() + digest = md5(bytes_(digest0) + secret).hexdigest() return digest # this function licensed under the MIT license (stolen from Paste) @@ -521,7 +522,7 @@ def encode_ip_timestamp(ip, timestamp): (t & 0xff00) >> 8, t & 0xff) ts_chars = ''.join(map(chr, ts)) - return ip_chars + ts_chars + return bytes_(ip_chars + ts_chars) EXPIRE = object() @@ -548,7 +549,7 @@ class AuthTktCookieHelper(object): int: ('int', str), long: ('int', str), text_type: ('b64unicode', lambda x: b64encode(utf_8_encode(x)[0])), - str: ('b64str', lambda x: b64encode(x)), + binary_type: ('b64str', lambda x: b64encode(x)), } def __init__(self, secret, cookie_name='auth_tkt', secure=False, @@ -659,7 +660,7 @@ class AuthTktCookieHelper(object): if reissue and not hasattr(request, '_authtkt_reissued'): if ( (now - timestamp) > self.reissue_time ): # work around https://github.com/Pylons/pyramid/issues#issue/108 - tokens = filter(None, tokens) + tokens = list(filter(None, tokens)) headers = self.remember(request, userid, max_age=self.max_age, tokens=tokens) def reissue_authtkt(request, response): @@ -726,6 +727,11 @@ class AuthTktCookieHelper(object): user_data = 'userid_type:%s' % encoding for token in tokens: + if isinstance(token, text_type): + try: + token.encode('ascii') + except UnicodeEncodeError: + raise ValueError("Invalid token %r" % (token,)) if not (isinstance(token, str) and VALID_TOKEN.match(token)): raise ValueError("Invalid token %r" % (token,)) diff --git a/pyramid/compat.py b/pyramid/compat.py index ecb661ce9..ed5e900ad 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -199,3 +199,8 @@ try: # pragma: no cover except ImportError: # pragma: no cover import ConfigParser configparser = ConfigParser + +try: + from Cookie import SimpleCookie +except ImportError: # pragma: no cover + from http.cookies import SimpleCookie diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index 7f64af705..b612c5789 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -1,6 +1,7 @@ import unittest from pyramid import testing from pyramid.compat import text_ +from pyramid.compat import bytes_ class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase): def setUp(self): @@ -463,7 +464,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): return cookie def _parseCookie(self, cookie): - from Cookie import SimpleCookie + from pyramid.compat import SimpleCookie cookies = SimpleCookie() cookies.load(cookie) return cookies.get('auth_tkt') @@ -563,14 +564,15 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(environ['AUTH_TYPE'],'cookie') def test_identify_good_cookie_b64str_useridtype(self): + from base64 import b64encode helper = self._makeOne('secret', include_ip=False) - helper.auth_tkt.userid = 'encoded'.encode('base64').strip() + helper.auth_tkt.userid = b64encode(b'encoded').strip() helper.auth_tkt.user_data = 'userid_type:b64str' request = self._makeRequest('ticket') result = helper.identify(request) self.assertEqual(len(result), 4) self.assertEqual(result['tokens'], ()) - self.assertEqual(result['userid'], 'encoded') + self.assertEqual(result['userid'], b'encoded') self.assertEqual(result['userdata'], 'userid_type:b64str') self.assertEqual(result['timestamp'], 0) environ = request.environ @@ -579,14 +581,15 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(environ['AUTH_TYPE'],'cookie') def test_identify_good_cookie_b64unicode_useridtype(self): + from base64 import b64encode helper = self._makeOne('secret', include_ip=False) - helper.auth_tkt.userid = '\xc3\xa9ncoded'.encode('base64').strip() + helper.auth_tkt.userid = b64encode(b'\xc3\xa9ncoded').strip() helper.auth_tkt.user_data = 'userid_type:b64unicode' request = self._makeRequest('ticket') result = helper.identify(request) self.assertEqual(len(result), 4) self.assertEqual(result['tokens'], ()) - self.assertEqual(result['userid'], text_('\xc3\xa9ncoded', 'utf-8')) + self.assertEqual(result['userid'], text_(b'\xc3\xa9ncoded', 'utf-8')) self.assertEqual(result['userdata'], 'userid_type:b64unicode') self.assertEqual(result['timestamp'], 0) environ = request.environ @@ -823,14 +826,16 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertTrue(result[1][1].endswith('; Path=/; Domain=example.com')) self.assertTrue(result[1][1].startswith('auth_tkt=')) - def test_remember_string_userid(self): + def test_remember_binary_userid(self): + import base64 helper = self._makeOne('secret') request = self._makeRequest() - result = helper.remember(request, 'userid') + result = helper.remember(request, b'userid') values = self._parseHeaders(result) self.assertEqual(len(result), 3) val = self._cookieValue(values[0]) - self.assertEqual(val['userid'], 'userid'.encode('base64').strip()) + self.assertEqual(val['userid'], + bytes_(base64.b64encode(b'userid').strip())) self.assertEqual(val['user_data'], 'userid_type:b64str') def test_remember_int_userid(self): @@ -844,6 +849,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(val['user_data'], 'userid_type:int') def test_remember_long_userid(self): + from pyramid.compat import long helper = self._makeOne('secret') request = self._makeRequest() result = helper.remember(request, long(1)) @@ -854,15 +860,16 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(val['user_data'], 'userid_type:int') def test_remember_unicode_userid(self): + import base64 helper = self._makeOne('secret') request = self._makeRequest() - userid = text_('\xc2\xa9', 'utf-8') + userid = text_(b'\xc2\xa9', 'utf-8') result = helper.remember(request, userid) values = self._parseHeaders(result) self.assertEqual(len(result), 3) val = self._cookieValue(values[0]) self.assertEqual(val['userid'], - userid.encode('utf-8').encode('base64').strip()) + base64.b64encode(userid.encode('utf-8'))) self.assertEqual(val['user_data'], 'userid_type:b64unicode') def test_remember_insane_userid(self): @@ -900,11 +907,12 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result[2][0], 'Set-Cookie') self.assertTrue("'tokens': ('foo', 'bar')" in result[2][1]) - def test_remember_non_string_token(self): + def test_remember_nonascii_token(self): helper = self._makeOne('secret') request = self._makeRequest() + la = text_(b'La Pe\xc3\xb1a', 'utf-8') self.assertRaises(ValueError, helper.remember, request, 'other', - tokens=(text_('foo'),)) + tokens=(la,)) def test_remember_invalid_token_format(self): helper = self._makeOne('secret') -- cgit v1.2.3 From 1b494c7d56940f52ab80346b6052147ce59c45f0 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 07:37:40 -0400 Subject: cope with moved module --- pyramid/scaffolds/tests.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyramid/scaffolds/tests.py b/pyramid/scaffolds/tests.py index fe5d6957a..7eb838e2f 100644 --- a/pyramid/scaffolds/tests.py +++ b/pyramid/scaffolds/tests.py @@ -1,5 +1,4 @@ import sys -import httplib import os import pkg_resources import shutil @@ -8,6 +7,11 @@ import tempfile import time import signal +try: + import httplib +except ImportError: # pragma: no cover + import http.client as httplib + class TemplateTest(object): def make_venv(self, directory): # pragma: no cover import virtualenv -- cgit v1.2.3 From a0e8dfbc0ebcb45ac6b286cca8c08f9e6c5e9739 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 07:37:55 -0400 Subject: centralize reading file and closing --- pyramid/tests/test_integration.py | 71 +++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 381d52aae..2bd060ac1 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -63,37 +63,28 @@ class IntegrationBase(object): here = os.path.dirname(__file__) class TestStaticAppBase(IntegrationBase): - def _assertBody(self, body, filename): - self.assertEqual( - body.replace(b'\r', b''), - open(filename, 'rb').read() - ) - def test_basic(self): res = self.testapp.get('/minimal.pt', status=200) - self._assertBody(res.body, os.path.join(here, 'fixtures/minimal.pt')) + _assertBody(res.body, os.path.join(here, 'fixtures/minimal.pt')) def test_hidden(self): res = self.testapp.get('/static/.hiddenfile', status=200) - self._assertBody( - res.body, - os.path.join(here, 'fixtures/static/.hiddenfile') - ) + _assertBody(res.body, os.path.join(here, 'fixtures/static/.hiddenfile')) def test_highchars_in_pathelement(self): res = self.testapp.get('/static/héhé/index.html', status=200) - self._assertBody( - res.body, os.path.join( - here, - text_('fixtures/static/héhé/index.html', 'utf-8')) + _assertBody( + res.body, + os.path.join(here, + text_('fixtures/static/héhé/index.html', 'utf-8')) ) def test_highchars_in_filename(self): res = self.testapp.get('/static/héhé.html', status=200) - self._assertBody( - res.body, os.path.join( - here, - text_('fixtures/static/héhé.html', 'utf-8')) + _assertBody( + res.body, + os.path.join(here, + text_('fixtures/static/héhé.html', 'utf-8')) ) def test_not_modified(self): @@ -105,7 +96,7 @@ class TestStaticAppBase(IntegrationBase): def test_file_in_subdir(self): fn = os.path.join(here, 'fixtures/static/index.html') res = self.testapp.get('/static/index.html', status=200) - self._assertBody(res.body, fn) + _assertBody(res.body, fn) def test_directory_noslash_redir(self): res = self.testapp.get('/static', status=301) @@ -125,7 +116,7 @@ class TestStaticAppBase(IntegrationBase): def test_directory_withslash(self): fn = os.path.join(here, 'fixtures/static/index.html') res = self.testapp.get('/static/', status=200) - self._assertBody(res.body, fn) + _assertBody(res.body, fn) def test_range_inclusive(self): self.testapp.extra_environ = {'HTTP_RANGE':'bytes=1-2'} @@ -140,15 +131,15 @@ class TestStaticAppBase(IntegrationBase): def test_range_notbytes(self): self.testapp.extra_environ = {'HTTP_RANGE':'kHz=-5'} res = self.testapp.get('/static/index.html', status=200) - self._assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody(res.body, + os.path.join(here, 'fixtures/static/index.html')) def test_range_multiple(self): res = self.testapp.get('/static/index.html', [('HTTP_RANGE', 'bytes=10-11,11-12')], status=200) - self._assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody(res.body, + os.path.join(here, 'fixtures/static/index.html')) def test_range_oob(self): self.testapp.extra_environ = {'HTTP_RANGE':'bytes=1000-1002'} @@ -189,36 +180,25 @@ class TestStaticAppNoSubpath(unittest.TestCase): request = Request(kw) return request - def _assertBody(self, body, filename): - self.assertEqual( - body.replace(b'\r', b''), - open(filename, 'rb').read() - ) - def test_basic(self): request = self._makeRequest({'PATH_INFO':'/minimal.pt'}) context = DummyContext() result = self.staticapp(context, request) self.assertEqual(result.status, '200 OK') - self._assertBody(result.body, os.path.join(here, 'fixtures/minimal.pt')) + _assertBody(result.body, os.path.join(here, 'fixtures/minimal.pt')) class TestStaticAppWithRoutePrefix(IntegrationBase, unittest.TestCase): package = 'pyramid.tests.pkgs.static_routeprefix' - def _assertBody(self, body, filename): - self.assertEqual( - body.replace(b'\r', b''), - open(filename, 'rb').read() - ) def test_includelevel1(self): res = self.testapp.get('/static/minimal.pt', status=200) - self._assertBody(res.body, - os.path.join(here, 'fixtures/minimal.pt')) + _assertBody(res.body, + os.path.join(here, 'fixtures/minimal.pt')) def test_includelevel2(self): res = self.testapp.get('/prefix/static/index.html', status=200) - self._assertBody(res.body, - os.path.join(here, 'fixtures/static/index.html')) + _assertBody(res.body, + os.path.join(here, 'fixtures/static/index.html')) class TestFixtureApp(IntegrationBase, unittest.TestCase): @@ -593,3 +573,12 @@ def httpdate(ts): import datetime ts = datetime.datetime.utcfromtimestamp(ts) return ts.strftime("%a, %d %b %Y %H:%M:%S GMT") + +def read_(filename): + with open(filename, 'rb') as fp: + val = fp.read() + return val + +def _assertBody(body, filename): + assert(body.replace(b'\r', b'') == read_(filename)) + -- cgit v1.2.3 From fccffe9c468ec652e07c13991cb340e76e82166d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 07:48:12 -0400 Subject: squash some open file warnings --- pyramid/fixers/fix_bfg_imports.py | 1 + pyramid/i18n.py | 11 ++++++----- pyramid/tests/test_integration.py | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pyramid/fixers/fix_bfg_imports.py b/pyramid/fixers/fix_bfg_imports.py index 8fd32a797..d9a4a6dfb 100644 --- a/pyramid/fixers/fix_bfg_imports.py +++ b/pyramid/fixers/fix_bfg_imports.py @@ -199,6 +199,7 @@ def fix_zcml(path): newf.write(newt) newf.flush() newf.close() + text.close() for dir in dirs: if dir.startswith('.'): diff --git a/pyramid/i18n.py b/pyramid/i18n.py index 040e581b5..082723cd3 100644 --- a/pyramid/i18n.py +++ b/pyramid/i18n.py @@ -180,10 +180,10 @@ def make_localizer(current_locale_name, translation_directories): mopath = os.path.realpath(os.path.join(messages_dir, mofile)) if mofile.endswith('.mo') and os.path.isfile(mopath): - mofp = open(mopath, 'rb') - domain = mofile[:-3] - dtrans = Translations(mofp, domain) - translations.add(dtrans) + with open(mopath, 'rb') as mofp: + domain = mofile[:-3] + dtrans = Translations(mofp, domain) + translations.add(dtrans) return Localizer(locale_name=current_locale_name, translations=translations) @@ -257,7 +257,8 @@ class Translations(gettext.GNUTranslations, object): filename = gettext.find(domain, dirname, locales) if not filename: return gettext.NullTranslations() - return cls(fileobj=open(filename, 'rb'), domain=domain) + with open(filename, 'rb') as fp: + return cls(fileobj=fp, domain=domain) def __repr__(self): return '<%s: "%s">' % (type(self).__name__, diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 2bd060ac1..286e1146b 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -228,7 +228,7 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): result = self.testapp.get('/allowed/index.html', status=200) self.assertEqual( result.body.replace(b'\r', b''), - open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) + read_(os.path.join(here, 'fixtures/static/index.html'))) def test_denied_via_acl_global_root_factory(self): self.testapp.extra_environ = {'REMOTE_USER':'bob'} @@ -239,7 +239,7 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): result = self.testapp.get('/protected/index.html', status=200) self.assertEqual( result.body.replace(b'\r', b''), - open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) + read_(os.path.join(here, 'fixtures/static/index.html'))) def test_denied_via_acl_local_root_factory(self): self.testapp.extra_environ = {'REMOTE_USER':'fred'} @@ -250,7 +250,7 @@ class TestStaticPermApp(IntegrationBase, unittest.TestCase): result = self.testapp.get('/factory_protected/index.html', status=200) self.assertEqual( result.body.replace(b'\r', b''), - open(os.path.join(here, 'fixtures/static/index.html'), 'rb').read()) + read_(os.path.join(here, 'fixtures/static/index.html'))) class TestCCBug(IntegrationBase, unittest.TestCase): # "unordered" as reported in IRC by author of -- cgit v1.2.3 From 5942ec4b3e9211436f2ccf044f3cf03a4a9960b2 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 08:32:16 -0400 Subject: more wtfing --- pyramid/tests/test_traversal.py | 12 +++-- pyramid/traversal.py | 116 +++++++++++++++++++++++++--------------- 2 files changed, 81 insertions(+), 47 deletions(-) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 07f7515eb..9af47aec3 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -608,9 +608,12 @@ class FindResourceTests(unittest.TestCase): root.__name__ = None traverser = ResourceTreeTraverser self._registerTraverser(traverser) + # fails on py3 + # path_info is / on py3, likely not so much on py2 result = self._callFUT( root, - text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF')) + text_(b'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') + ) self.assertEqual(result, unprintable) class ResourcePathTests(unittest.TestCase): @@ -849,12 +852,13 @@ class TraversalContextURLTests(unittest.TestCase): one.__name__ = text_(b'La Pe\xc3\xb1a', 'utf-8') two = DummyContext() two.__parent__ = one - two.__name__ = 'La Pe\xc3\xb1a' + two.__name__ = b'La Pe\xc3\xb1a' request = DummyRequest() context_url = self._makeOne(two, request) result = context_url() - self.assertEqual(result, - 'http://example.com:5432/La%20Pe%C3%B1a/La%20Pe%C3%B1a/') + self.assertEqual( + result, + 'http://example.com:5432/La%20Pe%C3%B1a/La%20Pe%C3%B1a/') def test_call_with_virtual_root_path(self): from pyramid.interfaces import VH_ROOT_KEY diff --git a/pyramid/traversal.py b/pyramid/traversal.py index e535da657..366bee563 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -10,9 +10,11 @@ from pyramid.interfaces import IRequestFactory from pyramid.interfaces import ITraverser from pyramid.interfaces import VH_ROOT_KEY +from pyramid.compat import PY3 from pyramid.compat import native_ from pyramid.compat import text_ from pyramid.compat import text_type +from pyramid.compat import binary_type from pyramid.compat import url_unquote_text from pyramid.compat import is_nonstr_iter from pyramid.encode import url_quote @@ -476,8 +478,9 @@ def traversal_path(path): their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ - if isinstance(path, text_type): - path = native_(path.encode('ascii')) + if (not PY3) and (isinstance(path, text_type)): + # XXX this stinks + path = path.encode('ascii') path = path.strip('/') clean = [] for segment in path.split('/'): @@ -496,47 +499,74 @@ def traversal_path(path): _segment_cache = {} -def quote_path_segment(segment, safe=''): - """ Return a quoted representation of a 'path segment' (such as - the string ``__name__`` attribute of a resource) as a string. If the - ``segment`` passed in is a unicode object, it is converted to a - UTF-8 string, then it is URL-quoted using Python's - ``urllib.quote``. If the ``segment`` passed in is a string, it is - URL-quoted using Python's :mod:`urllib.quote`. If the segment - passed in is not a string or unicode object, an error will be - raised. The return value of ``quote_path_segment`` is always a - string, never Unicode. - - You may pass a string of characters that need not be encoded as - the ``safe`` argument to this function. This corresponds to the - ``safe`` argument to :mod:`urllib.quote`. - - .. note:: The return value for each segment passed to this - function is cached in a module-scope dictionary for - speed: the cached version is returned when possible - rather than recomputing the quoted version. No cache - emptying is ever done for the lifetime of an - application, however. If you pass arbitrary - user-supplied strings to this function (as opposed to - some bounded set of values from a 'working set' known to - your application), it may become a memory leak. - """ - # The bit of this code that deals with ``_segment_cache`` is an - # optimization: we cache all the computation of URL path segments - # in this module-scope dictionary with the original string (or - # unicode value) as the key, so we can look it up later without - # needing to reencode or re-url-quote it - try: - return _segment_cache[(segment, safe)] - except KeyError: - ## if segment.__class__ is text_type: # isinstance slighly slower (~15%) - ## result = url_quote(segment.encode('utf-8'), safe) - ## else: - result = url_quote(native_(segment, 'utf-8'), safe) - # we don't need a lock to mutate _segment_cache, as the below - # will generate exactly one Python bytecode (STORE_SUBSCR) - _segment_cache[(segment, safe)] = result - return result +quote_path_segment_doc = """ \ +Return a quoted representation of a 'path segment' (such as +the string ``__name__`` attribute of a resource) as a string. If the +``segment`` passed in is a unicode object, it is converted to a +UTF-8 string, then it is URL-quoted using Python's +``urllib.quote``. If the ``segment`` passed in is a string, it is +URL-quoted using Python's :mod:`urllib.quote`. If the segment +passed in is not a string or unicode object, an error will be +raised. The return value of ``quote_path_segment`` is always a +string, never Unicode. + +You may pass a string of characters that need not be encoded as +the ``safe`` argument to this function. This corresponds to the +``safe`` argument to :mod:`urllib.quote`. + +.. note:: + + The return value for each segment passed to this + function is cached in a module-scope dictionary for + speed: the cached version is returned when possible + rather than recomputing the quoted version. No cache + emptying is ever done for the lifetime of an + application, however. If you pass arbitrary + user-supplied strings to this function (as opposed to + some bounded set of values from a 'working set' known to + your application), it may become a memory leak. +""" + + +if PY3: # pragma: no cover + # special-case on Python 2 for speed? unchecked + def quote_path_segment(segment, safe=''): + """ %s """ % quote_path_segment_doc + # The bit of this code that deals with ``_segment_cache`` is an + # optimization: we cache all the computation of URL path segments + # in this module-scope dictionary with the original string (or + # unicode value) as the key, so we can look it up later without + # needing to reencode or re-url-quote it + try: + return _segment_cache[(segment, safe)] + except KeyError: + if segment.__class__ not in (text_type, binary_type): + segment = str(segment) + result = url_quote(native_(segment, 'utf-8'), safe) + # we don't need a lock to mutate _segment_cache, as the below + # will generate exactly one Python bytecode (STORE_SUBSCR) + _segment_cache[(segment, safe)] = result + return result +else: + def quote_path_segment(segment, safe=''): + """ %s """ % quote_path_segment_doc + # The bit of this code that deals with ``_segment_cache`` is an + # optimization: we cache all the computation of URL path segments + # in this module-scope dictionary with the original string (or + # unicode value) as the key, so we can look it up later without + # needing to reencode or re-url-quote it + try: + return _segment_cache[(segment, safe)] + except KeyError: + if segment.__class__ is text_type: #isinstance slighly slower (~15%) + result = url_quote(segment.encode('utf-8'), safe) + else: + result = url_quote(str(segment), safe) + # we don't need a lock to mutate _segment_cache, as the below + # will generate exactly one Python bytecode (STORE_SUBSCR) + _segment_cache[(segment, safe)] = result + return result + @implementer(ITraverser) class ResourceTreeTraverser(object): -- cgit v1.2.3 From c9b78f324cdbd38c2ac095ea97472605746e081e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 08:39:40 -0400 Subject: version minimums --- setup.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 010dd06cc..99771a941 100644 --- a/setup.py +++ b/setup.py @@ -29,15 +29,15 @@ except IOError: README = CHANGES = '' install_requires=[ + 'setuptools', 'Chameleon >= 1.2.3', 'Mako >= 0.3.6', # strict_undefined 'WebOb >= 1.2dev', # response.text / py3 compat - 'repoze.lru', - 'setuptools', + 'repoze.lru >= 0.4', # py3 compat 'zope.interface >= 3.8.0', # has zope.interface.registry - 'zope.deprecation', + 'zope.deprecation >= 3.5.0', # py3 compat 'venusian >= 1.0a1', # ``onerror`` - 'translationstring', + 'translationstring >= 0.4', # py3 compat ] if not PY3: @@ -48,11 +48,11 @@ if not PY3: ]) tests_require = install_requires + [ - 'WebTest', + 'WebTest >= 1.3.1', # py3 compat 'virtualenv', ] -if not JYTHON: +if not (JYTHON or PY3): tests_require.extend([ 'Sphinx', 'docutils', -- cgit v1.2.3 From 10d2f293f250faf93844a8446c8fcfc5e1c90580 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 12:28:19 -0400 Subject: fix mako tests on py3 --- pyramid/compat.py | 5 +++++ pyramid/tests/fixtures/helloworld.mak | 4 ++-- pyramid/tests/fixtures/helloworld.mako | 4 ++-- pyramid/tests/pkgs/permbugapp/__init__.py | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index ed5e900ad..1936d58ac 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -204,3 +204,8 @@ try: from Cookie import SimpleCookie except ImportError: # pragma: no cover from http.cookies import SimpleCookie + +if PY3: # pragma: no cover + from html import escape +else: + from cgi import escape diff --git a/pyramid/tests/fixtures/helloworld.mak b/pyramid/tests/fixtures/helloworld.mak index efcf791e8..25283a50d 100644 --- a/pyramid/tests/fixtures/helloworld.mak +++ b/pyramid/tests/fixtures/helloworld.mak @@ -1,3 +1,3 @@ ## -*- coding: utf-8 -*- -<% a, b = 'foo', u'föö' %> -Hello ${u'föö'} +<%!from pyramid.compat import text_%><% a, b = 'foo', text_('föö', 'utf-8') %> +Hello ${text_('föö', 'utf-8')} diff --git a/pyramid/tests/fixtures/helloworld.mako b/pyramid/tests/fixtures/helloworld.mako index efcf791e8..25283a50d 100644 --- a/pyramid/tests/fixtures/helloworld.mako +++ b/pyramid/tests/fixtures/helloworld.mako @@ -1,3 +1,3 @@ ## -*- coding: utf-8 -*- -<% a, b = 'foo', u'föö' %> -Hello ${u'föö'} +<%!from pyramid.compat import text_%><% a, b = 'foo', text_('föö', 'utf-8') %> +Hello ${text_('föö', 'utf-8')} diff --git a/pyramid/tests/pkgs/permbugapp/__init__.py b/pyramid/tests/pkgs/permbugapp/__init__.py index 10a244f3b..330d983ab 100644 --- a/pyramid/tests/pkgs/permbugapp/__init__.py +++ b/pyramid/tests/pkgs/permbugapp/__init__.py @@ -1,6 +1,6 @@ -from cgi import escape +from pyramid.compat import escape from pyramid.security import view_execution_permitted -from webob import Response +from pyramid.response import Response def x_view(request): # pragma: no cover return Response('this is private!') -- cgit v1.2.3 From ff6c115215f147201db3e8dc33c03a9331a3c82b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 12:28:40 -0400 Subject: fix mako tests on py3 --- pyramid/tests/test_router.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 7ba4d5722..ab4fc116b 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -653,6 +653,7 @@ class TestRouter(unittest.TestCase): self.assertEqual(request.matched_route.name, 'foo') self.assertEqual(len(logger.messages), 1) + import pdb; pdb.set_trace() self.assertTrue( logger.messages[0].startswith( "route matched for url http://localhost:8080" -- cgit v1.2.3 From 105cb1123ca93dd25f0a6a22aa0e7288155f404c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 12:29:56 -0400 Subject: Revert "fix mako tests on py3" This reverts commit ff6c115215f147201db3e8dc33c03a9331a3c82b. --- pyramid/tests/test_router.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index ab4fc116b..7ba4d5722 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -653,7 +653,6 @@ class TestRouter(unittest.TestCase): self.assertEqual(request.matched_route.name, 'foo') self.assertEqual(len(logger.messages), 1) - import pdb; pdb.set_trace() self.assertTrue( logger.messages[0].startswith( "route matched for url http://localhost:8080" -- cgit v1.2.3 From 7950a27d0ec4c50e7a722feee2f97ca08949b14b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 12:33:31 -0400 Subject: protect against webob repr changes --- pyramid/tests/test_router.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 7ba4d5722..eb9b7285d 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -269,15 +269,14 @@ class TestRouter(unittest.TestCase): start_response = DummyStartResponse() why = exc_raised(HTTPNotFound, router, environ, start_response) self.assertTrue( - "debug_notfound of url http://localhost:8080/; path_info: '/', " - "context:" in why.args[0]) + "debug_notfound of url http://localhost:8080/; " in why.args[0]) self.assertTrue("view_name: '', subpath: []" in why.args[0]) self.assertTrue('http://localhost:8080' in why.args[0], why) self.assertEqual(len(logger.messages), 1) message = logger.messages[0] self.assertTrue('of url http://localhost:8080' in message) - self.assertTrue("path_info: '/'" in message) + self.assertTrue("path_info: " in message) self.assertTrue('DummyContext' in message) self.assertTrue("view_name: ''" in message) self.assertTrue("subpath: []" in message) @@ -651,15 +650,13 @@ class TestRouter(unittest.TestCase): self.assertEqual(environ['bfg.routes.route'].name, 'foo') self.assertEqual(request.matchdict, matchdict) self.assertEqual(request.matched_route.name, 'foo') - self.assertEqual(len(logger.messages), 1) self.assertTrue( logger.messages[0].startswith( "route matched for url http://localhost:8080" "/archives/action1/article1; " "route_name: 'foo', " - "path_info: '/archives/action1/article1', " - "pattern: 'archives/:action/:article', ")) + "path_info: ")) def test_call_route_match_miss_debug_routematch(self): from pyramid.httpexceptions import HTTPNotFound -- cgit v1.2.3 From 110483301e28fc5685c1dba12aae88a6a5a66983 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 12:54:54 -0400 Subject: get traversal_path tests slightly righter --- pyramid/tests/test_traversal.py | 6 ++---- pyramid/traversal.py | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 9af47aec3..cf1f841ec 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -284,8 +284,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) - from pyramid.exceptions import URLDecodeError - self.assertRaises(URLDecodeError, policy, request) + self.assertRaises(UnicodeEncodeError, policy, request) def test_non_utf8_path_segment_settings_unicode_path_segments_fails(self): foo = DummyContext() @@ -294,8 +293,7 @@ class ResourceTreeTraverserTests(unittest.TestCase): segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) - from pyramid.exceptions import URLDecodeError - self.assertRaises(URLDecodeError, policy, request) + self.assertRaises(UnicodeEncodeError, policy, request) def test_withroute_nothingfancy(self): resource = DummyContext() diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 366bee563..4d6a18b0d 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -478,9 +478,8 @@ def traversal_path(path): their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ - if (not PY3) and (isinstance(path, text_type)): - # XXX this stinks - path = path.encode('ascii') + if isinstance(path, text_type): + path.encode('ascii') # check for asci-only-ness path = path.strip('/') clean = [] for segment in path.split('/'): -- cgit v1.2.3 From 00473554def2bc59183aff71675d40c243e4cc7c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 16:35:36 -0400 Subject: decoy comment --- pyramid/tests/test_traversal.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index cf1f841ec..2f1ffcf5a 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -606,8 +606,6 @@ class FindResourceTests(unittest.TestCase): root.__name__ = None traverser = ResourceTreeTraverser self._registerTraverser(traverser) - # fails on py3 - # path_info is / on py3, likely not so much on py2 result = self._callFUT( root, text_(b'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') -- cgit v1.2.3 From 795253eefe30d8799a55d31e9905c6af21a32ffb Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 18:57:20 -0400 Subject: fix setup.py and tox.ini for dev/testing purposes --- setup.py | 14 ++++---------- tox.ini | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/setup.py b/setup.py index 99771a941..08aa1643e 100644 --- a/setup.py +++ b/setup.py @@ -13,13 +13,14 @@ ############################################################################## import os -import platform import sys from setuptools import setup, find_packages +if sys.version_info[:2] < (2, 6): + raise RuntimeError('Requires Python 2.6 or better') + PY3 = sys.version_info[0] == 3 -JYTHON = platform.system() != 'Java' here = os.path.abspath(os.path.dirname(__file__)) try: @@ -52,21 +53,14 @@ tests_require = install_requires + [ 'virtualenv', ] -if not (JYTHON or PY3): +if not PY3: tests_require.extend([ 'Sphinx', 'docutils', 'repoze.sphinx.autointerface', - ]) - -if not PY3: - tests_require.extend([ 'zope.component>=3.11.0', ]) -if sys.version_info[:2] < (2, 6): - install_requires.append('simplejson') - setup(name='pyramid', version='1.2', description=('The Pyramid web application development framework, a ' diff --git a/tox.ini b/tox.ini index 58980e805..a422b2eb6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,19 +1,25 @@ [tox] envlist = - py26,py27,jython,pypy,cover + py26,py27,py32,pypy,cover [testenv] commands = python setup.py test -q deps = + https://github.com/Pylons/webob/zipball/master + zope.component Sphinx - WebTest repoze.sphinx.autointerface + WebTest virtualenv -[testenv:jython] +[testenv:py32] commands = - jython setup.py test -q + python setup.py test -q +deps = + https://github.com/Pylons/webob/zipball/master + WebTest + virtualenv [testenv:cover] basepython = @@ -21,6 +27,8 @@ basepython = commands = python setup.py nosetests --with-xunit --with-xcoverage deps = + https://github.com/Pylons/webob/zipball/master + zope.component Sphinx WebTest repoze.sphinx.autointerface -- cgit v1.2.3 From 9d7eeaade0de81dc98e6443d135eff13e328ec47 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 24 Sep 2011 19:14:15 -0400 Subject: fix on 2.7 --- pyramid/tests/test_config/test_assets.py | 6 +++--- pyramid/urldispatch.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 8d9ab5825..627eefba7 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -273,13 +273,13 @@ class TestOverrideProvider(unittest.TestCase): self.assertEqual(result, 'value') def test_get_resource_stream_override_returns_value(self): - from io import StringIO - overrides = DummyOverrides(StringIO('value')) + from io import BytesIO + overrides = DummyOverrides(BytesIO(b'value')) import pyramid.tests.test_config self._registerOverrides(overrides) provider = self._makeOne(pyramid.tests.test_config) with provider.get_resource_stream(None, 'test_assets.py') as stream: - self.assertEqual(stream.getvalue(), 'value') + self.assertEqual(stream.getvalue(), b'value') def test_get_resource_string_override_returns_value(self): overrides = DummyOverrides('value') diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index b11bcefcb..54b52336a 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -7,6 +7,7 @@ from pyramid.interfaces import IRoute from pyramid.compat import url_unquote_text from pyramid.compat import native_ from pyramid.compat import text_type +from pyramid.compat import string_types from pyramid.compat import is_nonstr_iter from pyramid.compat import url_quote from pyramid.exceptions import URLDecodeError @@ -157,11 +158,13 @@ def _compile_route(route): def generator(dict): newdict = {} for k, v in dict.items(): - if isinstance(v, text_type): + if v.__class__ is text_type: v = native_(v, 'utf-8') if k == star and is_nonstr_iter(v): v = '/'.join([quote_path_segment(x) for x in v]) elif k != star: + if v.__class__ not in string_types: + v = str(v) try: v = url_quote(v, safe='') except TypeError: -- cgit v1.2.3 From f8414776aac292c178f96ea07fce634ec3af9f7a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 01:17:17 -0400 Subject: add path_traversal_info method to match reality of latin-1 encoded envvars, fix traversal tests under 3.2 --- pyramid/compat.py | 19 ++++++++- pyramid/config/__init__.py | 2 +- pyramid/config/testing.py | 4 +- pyramid/config/util.py | 4 +- pyramid/static.py | 8 ++-- pyramid/tests/test_traversal.py | 83 ++++++++++++++++++++++++++------------- pyramid/tests/test_urldispatch.py | 21 ++++++---- pyramid/traversal.py | 74 ++++++++++++++++++++-------------- pyramid/urldispatch.py | 9 ++--- 9 files changed, 143 insertions(+), 81 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index 1936d58ac..e1f5f16a8 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -49,6 +49,17 @@ def bytes_(s, encoding='latin-1', errors='strict'): return s.encode(encoding, errors) return s +if PY3: # pragma: no cover + def ascii_native_(s): + if isinstance(s, text_type): + s = s.encode('ascii') + return str(s, 'ascii', 'strict') +else: + def ascii_native_(s): + if isinstance(s, text_type): + s = s.encode('ascii') + return str(s) + if PY3: # pragma: no cover def native_(s, encoding='latin-1', errors='strict'): if isinstance(s, text_type): @@ -60,7 +71,7 @@ else: return s.encode(encoding, errors) return str(s) -try: # pragma: no cover +if PY3: # pragma: no cover from urllib import parse urlparse = parse from urllib.parse import quote as url_quote @@ -69,7 +80,8 @@ try: # pragma: no cover from urllib.parse import urlencode as url_encode from urllib.request import urlopen as url_open url_unquote_text = url_unquote -except ImportError: + url_unquote_native = url_unquote +else: import urlparse from urllib import quote as url_quote from urllib import quote_plus as url_quote_plus @@ -79,6 +91,9 @@ except ImportError: def url_unquote_text(v, encoding='utf-8', errors='replace'): v = url_unquote(v) return v.decode(encoding, errors) + def url_unquote_native(v, encoding='utf-8', errors='replace'): + return native_(url_unquote_text(v, encoding, errors)) + if PY3: # pragma: no cover import builtins diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index 02a78445e..3b5d88d5f 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -660,7 +660,7 @@ class Configurator( c, action_wrap = c if action_wrap: c = action_method(c) - if PY3: + if PY3: # pragma: no cover m = types.MethodType(c, self) else: m = types.MethodType(c, self, self.__class__) diff --git a/pyramid/config/testing.py b/pyramid/config/testing.py index 0f709f634..36729acdf 100644 --- a/pyramid/config/testing.py +++ b/pyramid/config/testing.py @@ -6,7 +6,7 @@ from pyramid.interfaces import IAuthenticationPolicy from pyramid.interfaces import IRendererFactory from pyramid.renderers import RendererHelper -from pyramid.traversal import traversal_path +from pyramid.traversal import traversal_path_info from pyramid.config.util import action_method @@ -66,7 +66,7 @@ class TestingConfiguratorMixin(object): def __call__(self, request): path = request.environ['PATH_INFO'] ob = resources[path] - traversed = traversal_path(path) + traversed = traversal_path_info(path) return {'context':ob, 'view_name':'','subpath':(), 'traversed':traversed, 'virtual_root':ob, 'virtual_root_path':(), 'root':ob} diff --git a/pyramid/config/util.py b/pyramid/config/util.py index 498fe7629..919862a9d 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -6,7 +6,7 @@ from pyramid.compat import bytes_ from pyramid.compat import is_nonstr_iter from pyramid.exceptions import ConfigurationError from pyramid.traversal import find_interface -from pyramid.traversal import traversal_path +from pyramid.traversal import traversal_path_info from hashlib import md5 @@ -241,7 +241,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, return True m = context['match'] tvalue = tgenerate(m) - m['traverse'] = traversal_path(tvalue) + m['traverse'] = traversal_path_info(tvalue) return True # This isn't actually a predicate, it's just a infodict # modifier that injects ``traverse`` into the matchdict. As a diff --git a/pyramid/static.py b/pyramid/static.py index edb20b54f..79384da09 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -20,7 +20,7 @@ from pyramid.httpexceptions import HTTPNotFound from pyramid.httpexceptions import HTTPMovedPermanently from pyramid.path import caller_package from pyramid.response import Response -from pyramid.traversal import traversal_path +from pyramid.traversal import traversal_path_info slash = text_('/') @@ -112,8 +112,8 @@ class static_view(object): ``PATH_INFO`` when calling the underlying WSGI application which actually serves the static files. If it is ``True``, the static application will consider ``request.subpath`` as ``PATH_INFO`` input. If it is ``False``, - the static application will consider request.path_info as ``PATH_INFO`` - input. By default, this is ``False``. + the static application will consider request.environ[``PATH_INFO``] as + ``PATH_INFO`` input. By default, this is ``False``. .. note:: If the ``root_dir`` is relative to a :term:`package`, or is a :term:`asset specification` the :app:`Pyramid` @@ -142,7 +142,7 @@ class static_view(object): if self.use_subpath: path_tuple = request.subpath else: - path_tuple = traversal_path(request.path_info) + path_tuple = traversal_path_info(request.environ['PATH_INFO']) path = _secure_path(path_tuple) diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index 2f1ffcf5a..72192b23b 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -11,6 +11,39 @@ class TraversalPathTests(unittest.TestCase): from pyramid.traversal import traversal_path return traversal_path(path) + def test_utf8(self): + la = b'La Pe\xc3\xb1a' + encoded = url_quote(la) + decoded = text_(la, 'utf-8') + path = '/'.join([encoded, encoded]) + result = self._callFUT(path) + self.assertEqual(result, (decoded, decoded)) + + def test_utf16(self): + from pyramid.exceptions import URLDecodeError + la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16') + encoded = url_quote(la) + path = '/'.join([encoded, encoded]) + self.assertRaises(URLDecodeError, self._callFUT, path) + + def test_unicode_highorder_chars(self): + path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') + self.assertEqual(self._callFUT(path), + (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),)) + + def test_element_urllquoted(self): + self.assertEqual(self._callFUT('/foo/space%20thing/bar'), + (text_('foo'), text_('space thing'), text_('bar'))) + + def test_unicode_undecodeable_to_ascii(self): + path = text_(b'/La Pe\xc3\xb1a', 'utf-8') + self.assertRaises(UnicodeEncodeError, self._callFUT, path) + +class TraversalPathInfoTests(unittest.TestCase): + def _callFUT(self, path): + from pyramid.traversal import traversal_path_info + return traversal_path_info(path) + def test_path_startswith_endswith(self): self.assertEqual(self._callFUT('/foo/'), (text_('foo'),)) @@ -27,10 +60,6 @@ class TraversalPathTests(unittest.TestCase): def test_twodots_at_start(self): self.assertEqual(self._callFUT('../../bar'), (text_('bar'),)) - def test_element_urllquoted(self): - self.assertEqual(self._callFUT('/foo/space%20thing/bar'), - (text_('foo'), text_('space thing'), text_('bar'))) - def test_segments_are_unicode(self): result = self._callFUT('/foo/bar') self.assertEqual(type(result[0]), text_type) @@ -42,32 +71,21 @@ class TraversalPathTests(unittest.TestCase): self.assertEqual(result1, (text_('foo'), text_('bar'))) self.assertEqual(result2, (text_('foo'), text_('bar'))) - def test_utf8(self): - la = b'La Pe\xc3\xb1a' - encoded = url_quote(la) - decoded = text_(la, 'utf-8') - path = '/'.join([encoded, encoded]) - self.assertEqual(self._callFUT(path), (decoded, decoded)) - - def test_utf16(self): - from pyramid.exceptions import URLDecodeError - la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16') - encoded = url_quote(la) - path = '/'.join([encoded, encoded]) - self.assertRaises(URLDecodeError, self._callFUT, path) - - def test_unicode_highorder_chars(self): - path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF') - self.assertEqual(self._callFUT(path), - (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),)) - def test_unicode_simple(self): path = text_('/abc') self.assertEqual(self._callFUT(path), (text_('abc'),)) - def test_unicode_undecodeable_to_ascii(self): - path = text_(b'/La Pe\xc3\xb1a', 'utf-8') - self.assertRaises(UnicodeEncodeError, self._callFUT, path) + def test_highorder(self): + la = b'La Pe\xc3\xb1a' + latin1 = native_(la) + result = self._callFUT(latin1) + self.assertEqual(result, (text_(la, 'utf-8'),)) + + def test_highorder_undecodeable(self): + from pyramid.exceptions import URLDecodeError + la = text_(b'La Pe\xc3\xb1a', 'utf-8') + notlatin1 = native_(la) + self.assertRaises(URLDecodeError, self._callFUT, notlatin1) class ResourceTreeTraverserTests(unittest.TestCase): def setUp(self): @@ -278,22 +296,24 @@ class ResourceTreeTraverserTests(unittest.TestCase): self.assertEqual(result['virtual_root_path'], ()) def test_non_utf8_path_segment_unicode_path_segments_fails(self): + from pyramid.exceptions import URLDecodeError foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) - self.assertRaises(UnicodeEncodeError, policy, request) + self.assertRaises(URLDecodeError, policy, request) def test_non_utf8_path_segment_settings_unicode_path_segments_fails(self): + from pyramid.exceptions import URLDecodeError foo = DummyContext() root = DummyContext(foo) policy = self._makeOne(root) segment = native_(text_(b'LaPe\xc3\xb1a', 'utf-8'), 'utf-16') environ = self._getEnviron(PATH_INFO='/%s' % segment) request = DummyRequest(environ) - self.assertRaises(UnicodeEncodeError, policy, request) + self.assertRaises(URLDecodeError, policy, request) def test_withroute_nothingfancy(self): resource = DummyContext() @@ -1049,6 +1069,13 @@ class TraverseTests(unittest.TestCase): self._callFUT(resource, '') self.assertEqual(resource.request.environ['PATH_INFO'], '') + def test_self_unicode_found(self): + resource = DummyContext() + traverser = make_traverser({'context':resource, 'view_name':''}) + self._registerTraverser(traverser) + self._callFUT(resource, text_('')) + self.assertEqual(resource.request.environ['PATH_INFO'], '') + def test_self_tuple_found(self): resource = DummyContext() traverser = make_traverser({'context':resource, 'view_name':''}) diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index 2f6182a66..be823b045 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -1,6 +1,7 @@ import unittest from pyramid import testing from pyramid.compat import text_ +from pyramid.compat import native_ class TestRoute(unittest.TestCase): def _getTargetClass(self): @@ -294,7 +295,8 @@ class TestCompileRoute(unittest.TestCase): def test_url_decode_error(self): from pyramid.exceptions import URLDecodeError matcher, generator = self._callFUT('/:foo') - self.assertRaises(URLDecodeError, matcher, '/%FF%FE%8B%00') + self.assertRaises(URLDecodeError, matcher, + native_(b'/\xff\xfe\x8b\x00')) def test_custom_regex(self): matcher, generator = self._callFUT('foo/{baz}/biz/{buz:[^/\.]+}.{bar}') @@ -364,9 +366,12 @@ class TestCompileRouteFunctional(unittest.TestCase): self.matches('zzz/{x}*traverse', '/zzz/abc/def/g', {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) - self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches('{x}', '/La%20Pe%C3%B1a', {'x':text_(b'La Pe\xf1a')}) - self.matches('*traverse', '/La%20Pe%C3%B1a/x', + self.matches('*traverse', '/zzz/ abc', {'traverse':('zzz', ' abc')}) + #'/La%20Pe%C3%B1a' + self.matches('{x}', native_(b'/La Pe\xc3\xb1a'), + {'x':text_(b'La Pe\xf1a')}) + # '/La%20Pe%C3%B1a/x' + self.matches('*traverse', native_(b'/La Pe\xc3\xb1a/x'), {'traverse':(text_(b'La Pe\xf1a'), 'x')}) self.matches('/foo/{id}.html', '/foo/bar.html', {'id':'bar'}) self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def', @@ -387,10 +392,12 @@ class TestCompileRouteFunctional(unittest.TestCase): self.matches('zzz/:x*traverse', '/zzz/abc/def/g', {'x':'abc', 'traverse':('def', 'g')}) self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')}) - self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')}) - self.matches(':x', '/La%20Pe%C3%B1a', + self.matches('*traverse', '/zzz/ abc', {'traverse':('zzz', ' abc')}) + #'/La%20Pe%C3%B1a' + self.matches(':x', native_(b'/La Pe\xc3\xb1a'), {'x':text_(b'La Pe\xf1a')}) - self.matches('*traverse', '/La%20Pe%C3%B1a/x', + # '/La%20Pe%C3%B1a/x' + self.matches('*traverse', native_(b'/La Pe\xc3\xb1a/x'), {'traverse':(text_(b'La Pe\xf1a'), 'x')}) self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'}) self.matches('/foo/:id_html', '/foo/bar_html', {'id_html':'bar_html'}) diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 4d6a18b0d..49f9be55f 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -13,9 +13,11 @@ from pyramid.interfaces import VH_ROOT_KEY from pyramid.compat import PY3 from pyramid.compat import native_ from pyramid.compat import text_ +from pyramid.compat import bytes_ +from pyramid.compat import ascii_native_ from pyramid.compat import text_type from pyramid.compat import binary_type -from pyramid.compat import url_unquote_text +from pyramid.compat import url_unquote_native from pyramid.compat import is_nonstr_iter from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError @@ -66,6 +68,10 @@ def find_resource(resource, path): :func:`pyramid.traversal.resource_path` function generates strings which follow these rules (albeit only absolute ones). + Rules for passing *text* (Unicode) as the ``path`` argument are the same + as those for a string. In particular, the text may not have any nonascii + characters in it. + Rules for passing a *tuple* as the ``path`` argument: if the first element in the path tuple is the empty string (for example ``('', 'a', 'b', 'c')``, the path is considered absolute and the resource tree @@ -85,6 +91,8 @@ def find_resource(resource, path): be imported as :func:`pyramid.traversal.find_model`, although doing so will emit a deprecation warning. """ + if isinstance(path, text_type): + path = ascii_native_(path) D = traverse(resource, path) view_name = D['view_name'] context = D['context'] @@ -299,8 +307,7 @@ def traverse(resource, path): # step rather than later down the line as the result of calling # ``traversal_path``). - if isinstance(path, text_type): - path = native_(path, 'ascii') + path = ascii_native_(path) if path and path[0] == '/': resource = find_root(resource) @@ -410,26 +417,35 @@ def virtual_root(resource, request): urlgenerator = TraversalContextURL(resource, request) return urlgenerator.virtual_root() -@lru_cache(1000) def traversal_path(path): - """ Given a ``PATH_INFO`` string (slash-separated path segments), - return a tuple representing that path which can be used to - traverse a resource tree. - - The ``PATH_INFO`` is split on slashes, creating a list of - segments. Each segment is URL-unquoted, and subsequently decoded - into Unicode. Each segment is assumed to be encoded using the - UTF-8 encoding (or a subset, such as ASCII); a - :exc:`pyramid.exceptions.URLDecodeError` is raised if a segment - cannot be decoded. If a segment name is empty or if it is ``.``, - it is ignored. If a segment name is ``..``, the previous segment - is deleted, and the ``..`` is ignored. + """ Variant of :func:`pyramid.traversal.traversal_path_info` suitable for + decoding paths that are URL-encoded.""" + path = ascii_native_(path) + path = url_unquote_native(path, 'latin-1', 'strict') + return traversal_path_info(path) - If this function is passed a Unicode object instead of a string, - that Unicode object *must* directly encodeable to ASCII. For - example, u'/foo' will work but u'/' (a - Unicode object with characters that cannot be encoded to ascii) - will not. +@lru_cache(1000) +def traversal_path_info(path): + """ Given a ``PATH_INFO`` environ value (slash-separated path segments), + return a tuple representing that path which can be used to traverse a + resource tree. + + ``PATH_INFO`` is assumed to already be URL-decoded. It is encoded to + bytes using the Latin-1 encoding; the resulting set of bytes is + subsequently decoded to text using the UTF-8 encoding; a + :exc:`pyramid.exc.URLDecodeError` is raised if a the URL cannot be + decoded. + + The ``PATH_INFO`` is split on slashes, creating a list of segments. Each + segment subsequently decoded into Unicode. If a segment name is empty or + if it is ``.``, it is ignored. If a segment name is ``..``, the previous + segment is deleted, and the ``..`` is ignored. + + If this function is passed a Unicode object instead of a string, that + Unicode object *must* directly encodeable to ASCII. For example, u'/foo' + will work but u'/' (a Unicode object with characters + that cannot be encoded to ascii) will not. A :exc:`UnicodeError` will be + raised if the Unicode cannot be encoded directly to ASCII. Examples: @@ -478,15 +494,13 @@ def traversal_path(path): their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ - if isinstance(path, text_type): - path.encode('ascii') # check for asci-only-ness + try: + path = bytes_(path, 'latin-1').decode('utf-8') + except UnicodeDecodeError as e: + raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) path = path.strip('/') clean = [] for segment in path.split('/'): - try: - segment = url_unquote_text(segment, 'utf-8', 'strict') - except UnicodeDecodeError as e: - raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if not segment or segment == '.': continue elif segment == '..': @@ -604,7 +618,7 @@ class ResourceTreeTraverser(object): subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) - subpath = traversal_path(subpath) + subpath = traversal_path_info(subpath) else: # this request did not match a route @@ -616,7 +630,7 @@ class ResourceTreeTraverser(object): if VH_ROOT_KEY in environ: vroot_path = environ[VH_ROOT_KEY] - vroot_tuple = traversal_path(vroot_path) + vroot_tuple = traversal_path_info(vroot_path) vpath = vroot_path + path vroot_idx = len(vroot_tuple) -1 else: @@ -637,7 +651,7 @@ class ResourceTreeTraverser(object): # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR - vpath_tuple = traversal_path(vpath) + vpath_tuple = traversal_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return {'context':ob, diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 54b52336a..6fe49f442 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -4,14 +4,14 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoute -from pyramid.compat import url_unquote_text from pyramid.compat import native_ +from pyramid.compat import bytes_ from pyramid.compat import text_type from pyramid.compat import string_types from pyramid.compat import is_nonstr_iter from pyramid.compat import url_quote from pyramid.exceptions import URLDecodeError -from pyramid.traversal import traversal_path +from pyramid.traversal import traversal_path_info from pyramid.traversal import quote_path_segment _marker = object() @@ -139,11 +139,10 @@ def _compile_route(route): d = {} for k, v in m.groupdict().items(): if k == star: - d[k] = traversal_path(v) + d[k] = traversal_path_info(v) else: try: - val = url_unquote_text( - v, encoding='utf-8', errors='strict') + val = bytes_(v).decode('utf-8', 'strict') d[k] = val except UnicodeDecodeError as e: raise URLDecodeError( -- cgit v1.2.3 From a7c67c168934b8fe23a817f2bdc8b3b298a384c8 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 02:05:37 -0400 Subject: fix url tests on 3.2 --- pyramid/tests/test_url.py | 36 ++++++++++++++++++++++++++++-------- pyramid/url.py | 3 +-- pyramid/urldispatch.py | 5 +---- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index aa6fa30dd..4c39d8e9c 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -3,6 +3,7 @@ import unittest from pyramid.testing import setUp from pyramid.testing import tearDown from pyramid.compat import text_ +from pyramid.compat import native_ class TestURLMethodsMixin(unittest.TestCase): def setUp(self): @@ -120,8 +121,13 @@ class TestURLMethodsMixin(unittest.TestCase): context = DummyContext() uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, anchor=uc) - self.assertEqual(result, - 'http://example.com/context/#La Pe\xc3\xb1a') + self.assertEqual( + result, + native_( + text_(b'http://example.com/context/#La Pe\xc3\xb1a', + 'utf-8'), + 'utf-8') + ) def test_resource_url_anchor_is_not_urlencoded(self): request = self._makeOne() @@ -177,14 +183,21 @@ class TestURLMethodsMixin(unittest.TestCase): self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1#foo') - def test_route_url_with_anchor_string(self): + def test_route_url_with_anchor_binary(self): from pyramid.interfaces import IRoutesMapper request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - result = request.route_url('flub', _anchor="La Pe\xc3\xb1a") - self.assertEqual(result, - 'http://example.com:5432/1/2/3#La Pe\xc3\xb1a') + result = request.route_url('flub', _anchor=b"La Pe\xc3\xb1a") + + self.assertEqual( + result, + native_( + text_( + b'http://example.com:5432/1/2/3#La Pe\xc3\xb1a', + 'utf-8'), + 'utf-8') + ) def test_route_url_with_anchor_unicode(self): from pyramid.interfaces import IRoutesMapper @@ -193,8 +206,15 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) anchor = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.route_url('flub', _anchor=anchor) - self.assertEqual(result, - 'http://example.com:5432/1/2/3#La Pe\xc3\xb1a') + + self.assertEqual( + result, + native_( + text_( + b'http://example.com:5432/1/2/3#La Pe\xc3\xb1a', + 'utf-8'), + 'utf-8') + ) def test_route_url_with_query(self): from pyramid.interfaces import IRoutesMapper diff --git a/pyramid/url.py b/pyramid/url.py index c0c623aeb..0ccf02ab9 100644 --- a/pyramid/url.py +++ b/pyramid/url.py @@ -137,8 +137,7 @@ class URLMethodsMixin(object): if '_anchor' in kw: anchor = kw.pop('_anchor') - if isinstance(anchor, text_type): - anchor = native_(anchor, 'utf-8') + anchor = native_(anchor, 'utf-8') anchor = '#' + anchor if '_app_url' in kw: diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 6fe49f442..662615845 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -164,10 +164,7 @@ def _compile_route(route): elif k != star: if v.__class__ not in string_types: v = str(v) - try: - v = url_quote(v, safe='') - except TypeError: - pass + v = url_quote(v, safe='') newdict[k] = v return gen % newdict -- cgit v1.2.3 From 884807ee7de11b1d72a17112519e2f1669cd9726 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 02:34:28 -0400 Subject: fix i18n poorly --- pyramid/i18n.py | 13 +++++++++++-- pyramid/tests/test_i18n.py | 18 +++++++++++------- pyramid/tests/test_integration.py | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/pyramid/i18n.py b/pyramid/i18n.py index 082723cd3..889227130 100644 --- a/pyramid/i18n.py +++ b/pyramid/i18n.py @@ -9,6 +9,7 @@ from translationstring import TranslationStringFactory # API TranslationString = TranslationString # PyFlakes TranslationStringFactory = TranslationStringFactory # PyFlakes +from pyramid.compat import PY3 from pyramid.interfaces import ILocalizer from pyramid.interfaces import ITranslationDirectories from pyramid.interfaces import ILocaleNegotiator @@ -328,7 +329,10 @@ class Translations(gettext.GNUTranslations, object): """Like ``ugettext()``, but look the message up in the specified domain. """ - return self._domains.get(domain, self).ugettext(message) + if PY3: # pragma: no cover + return self._domains.get(domain, self).gettext(message) + else: # pragma: no cover + return self._domains.get(domain, self).ugettext(message) def dngettext(self, domain, singular, plural, num): """Like ``ngettext()``, but look the message up in the specified @@ -346,5 +350,10 @@ class Translations(gettext.GNUTranslations, object): """Like ``ungettext()`` but look the message up in the specified domain. """ - return self._domains.get(domain, self).ungettext(singular, plural, num) + if PY3: # pragma: no cover + return self._domains.get(domain, self).ngettext( + singular, plural, num) + else: # pragma: no cover + return self._domains.get(domain, self).ungettext( + singular, plural, num) diff --git a/pyramid/tests/test_i18n.py b/pyramid/tests/test_i18n.py index 008cf525a..bd4998b10 100644 --- a/pyramid/tests/test_i18n.py +++ b/pyramid/tests/test_i18n.py @@ -50,9 +50,9 @@ class TestLocalizer(unittest.TestCase): def test_pluralize(self): translations = DummyTranslations() localizer = self._makeOne(None, translations) - self.assertEqual(localizer.pluralize('singular', 'plural', 1, - domain='1', mapping={}), - 'singular') + result = localizer.pluralize('singular', 'plural', 1, + domain='1', mapping={}) + self.assertEqual(result, 'singular') self.assertTrue(localizer.pluralizer) def test_pluralize_pluralizer_already_added(self): @@ -434,8 +434,8 @@ class TestTranslations(unittest.TestCase): def test_ldgettext(self): t = self._makeOne() - self.assertEqual(t.ldgettext('messages', 'foo'), 'Voh') - self.assertEqual(t.ldgettext('messages1', 'foo'), 'VohD') + self.assertEqual(t.ldgettext('messages', 'foo'), b'Voh') + self.assertEqual(t.ldgettext('messages1', 'foo'), b'VohD') def test_dugettext(self): t = self._makeOne() @@ -449,8 +449,8 @@ class TestTranslations(unittest.TestCase): def test_ldngettext(self): t = self._makeOne() - self.assertEqual(t.ldngettext('messages', 'foo1', 'foos1', 1), 'Voh1') - self.assertEqual(t.ldngettext('messages1', 'foo1', 'foos1', 1), 'VohD1') + self.assertEqual(t.ldngettext('messages', 'foo1', 'foos1', 1), b'Voh1') + self.assertEqual(t.ldngettext('messages1', 'foo1', 'foos1', 1),b'VohD1') def test_dungettext(self): t = self._makeOne() @@ -476,5 +476,9 @@ class DummyTranslations(object): def ugettext(self, text): return text + gettext = ugettext + def ungettext(self, singular, plural, n): return singular + + ngettext = ungettext diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 286e1146b..1a723c0d7 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -7,6 +7,7 @@ from pyramid.wsgi import wsgiapp from pyramid.view import view_config from pyramid.static import static_view from pyramid.compat import text_ +from pyramid.compat import native_ from zope.interface import Interface -- cgit v1.2.3 From f4bdf9e8a7e9598042c53d96f1539b431880ec3f Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 03:04:14 -0400 Subject: fix integration tests --- pyramid/tests/test_integration.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 1a723c0d7..0c17b88ce 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -7,7 +7,7 @@ from pyramid.wsgi import wsgiapp from pyramid.view import view_config from pyramid.static import static_view from pyramid.compat import text_ -from pyramid.compat import native_ +from pyramid.compat import url_quote from zope.interface import Interface @@ -73,7 +73,8 @@ class TestStaticAppBase(IntegrationBase): _assertBody(res.body, os.path.join(here, 'fixtures/static/.hiddenfile')) def test_highchars_in_pathelement(self): - res = self.testapp.get('/static/héhé/index.html', status=200) + url = url_quote('/static/héhé/index.html') + res = self.testapp.get(url, status=200) _assertBody( res.body, os.path.join(here, @@ -81,7 +82,8 @@ class TestStaticAppBase(IntegrationBase): ) def test_highchars_in_filename(self): - res = self.testapp.get('/static/héhé.html', status=200) + url = url_quote('/static/héhé.html') + res = self.testapp.get(url, status=200) _assertBody( res.body, os.path.join(here, -- cgit v1.2.3 From c779f17dd60745e033075df2d76ab168cc2ecfd5 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 03:37:30 -0400 Subject: all tests pass on 3.2 --- pyramid/request.py | 7 +++++-- pyramid/tests/test_request.py | 13 ++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pyramid/request.py b/pyramid/request.py index 6b77b09e9..afeee4bb2 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -13,6 +13,8 @@ from pyramid.interfaces import IResponseFactory from pyramid.compat import json from pyramid.compat import iterkeys_, itervalues_, iteritems_ from pyramid.compat import text_ +from pyramid.compat import bytes_ +from pyramid.compat import native_ from pyramid.exceptions import ConfigurationError from pyramid.decorator import reify from pyramid.response import Response @@ -406,7 +408,8 @@ def call_app_with_subpath_as_path_info(request, app): new_script_name = '' # compute new_path_info - new_path_info = '/' + '/'.join([x.encode('utf-8') for x in subpath]) + new_path_info = '/' + '/'.join([native_(x.encode('utf-8'), 'latin-1') + for x in subpath]) if new_path_info != '/': # don't want a sole double-slash if path_info != '/': # if orig path_info is '/', we're already done @@ -424,7 +427,7 @@ def call_app_with_subpath_as_path_info(request, app): break el = workback.pop() if el: - tmp.insert(0, el.decode('utf-8')) + tmp.insert(0, text_(bytes_(el, 'latin-1'), 'utf-8')) # strip all trailing slashes from workback to avoid appending undue slashes # to end of script_name diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index c731edb7f..9d48d3b6e 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -3,6 +3,7 @@ from pyramid import testing from pyramid.compat import text_ from pyramid.compat import bytes_ +from pyramid.compat import native_ from pyramid.compat import iteritems_, iterkeys_, itervalues_ class TestRequest(unittest.TestCase): @@ -501,14 +502,16 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase): self.assertEqual(request.environ['PATH_INFO'], '/hello/') def test_subpath_path_info_and_script_name_have_utf8(self): - la = 'La Pe\xc3\xb1a' - request = DummyRequest({'PATH_INFO':'/'+la, 'SCRIPT_NAME':'/'+la}) - request.subpath = (text_(la, 'utf-8'), ) + encoded = native_(text_(b'La Pe\xc3\xb1a')) + decoded = text_(bytes_(encoded), 'utf-8') + request = DummyRequest({'PATH_INFO':'/' + encoded, + 'SCRIPT_NAME':'/' + encoded}) + request.subpath = (decoded, ) response = self._callFUT(request, 'app') self.assertTrue(request.copied) self.assertEqual(response, 'app') - self.assertEqual(request.environ['SCRIPT_NAME'], '/' + la) - self.assertEqual(request.environ['PATH_INFO'], '/' + la) + self.assertEqual(request.environ['SCRIPT_NAME'], '/' + encoded) + self.assertEqual(request.environ['PATH_INFO'], '/' + encoded) class DummyRequest: def __init__(self, environ=None): -- cgit v1.2.3 From fd266a8ffe324a0c45bffded28522ff9984765a3 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 03:47:56 -0400 Subject: coverage and warnings --- pyramid/compat.py | 2 +- pyramid/tests/test_config/test_init.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyramid/compat.py b/pyramid/compat.py index e1f5f16a8..e686be27d 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -42,7 +42,7 @@ else: def text_(s, encoding='latin-1', errors='strict'): if isinstance(s, binary_type): return s.decode(encoding, errors) - return s + return s # pragma: no cover def bytes_(s, encoding='latin-1', errors='strict'): if isinstance(s, text_type): diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index b5eb85d59..ca1508295 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -605,8 +605,8 @@ class ConfiguratorTests(unittest.TestCase): pyramid.tests.test_config.dummy_include2""", } config.setup_registry(settings=settings) - self.assert_(reg.included) - self.assert_(reg.also_included) + self.assertTrue(reg.included) + self.assertTrue(reg.also_included) def test_setup_registry_includes_spaces(self): from pyramid.registry import Registry @@ -617,8 +617,8 @@ pyramid.tests.test_config.dummy_include2""", """pyramid.tests.test_config.dummy_include pyramid.tests.test_config.dummy_include2""", } config.setup_registry(settings=settings) - self.assert_(reg.included) - self.assert_(reg.also_included) + self.assertTrue(reg.included) + self.assertTrue(reg.also_included) def test_setup_registry_tweens(self): from pyramid.interfaces import ITweens -- cgit v1.2.3