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 From 502f7122efb6beabd2b05260ef10e43014658d00 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 04:53:28 -0400 Subject: py3 trove classifiers --- setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.py b/setup.py index 08aa1643e..aa8045a9a 100644 --- a/setup.py +++ b/setup.py @@ -69,6 +69,10 @@ setup(name='pyramid', classifiers=[ "Intended Audience :: Developers", "Programming Language :: Python", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.2", "Framework :: Pylons", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI", -- cgit v1.2.3 From b719fdd3e99bb98f426a2125a4e1b5056cca2a46 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 25 Sep 2011 23:42:02 -0400 Subject: track changes to webob head --- pyramid/tests/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 9d48d3b6e..9de7cb795 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -251,7 +251,7 @@ class TestRequest(unittest.TestCase): def test_json_body_alternate_charset(self): from pyramid.compat import json request = self._makeOne({'REQUEST_METHOD':'POST'}) - request.charset = 'latin-1' + request = request.decode('latin-1') la = text_(b'La Pe\xc3\xb1a', 'utf-8') body = bytes_(json.dumps({'a':la}), 'latin-1') request.body = body -- cgit v1.2.3 From 632a912b4b7f6f387adee2ebadebd677f2ebc82c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 26 Sep 2011 01:58:12 -0400 Subject: better test --- pyramid/tests/test_request.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 9de7cb795..56b1349bb 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -1,6 +1,7 @@ import unittest from pyramid import testing +from pyramid.compat import PY3 from pyramid.compat import text_ from pyramid.compat import bytes_ from pyramid.compat import native_ @@ -251,11 +252,17 @@ class TestRequest(unittest.TestCase): def test_json_body_alternate_charset(self): from pyramid.compat import json request = self._makeOne({'REQUEST_METHOD':'POST'}) - request = request.decode('latin-1') - la = text_(b'La Pe\xc3\xb1a', 'utf-8') - body = bytes_(json.dumps({'a':la}), 'latin-1') + inp = text_( + b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', + 'utf-8' + ) + if PY3: + body = bytes(json.dumps({'a':inp}), 'utf-16') + else: + body = json.dumps({'a':inp}).decode('utf-8').encode('utf-16') request.body = body - self.assertEqual(request.json_body, {'a':la}) + request.content_type = 'application/json; charset=utf-16' + self.assertEqual(request.json_body, {'a':inp}) def test_json_body_GET_request(self): request = self._makeOne({'REQUEST_METHOD':'GET'}) -- cgit v1.2.3 From 9f7de68bc84af8343949b9dd98e53dc9ca8b77a1 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 26 Sep 2011 05:20:48 -0400 Subject: get rid of resourcewarnings --- pyramid/renderers.py | 1 - pyramid/tests/test_config/test_views.py | 1 + pyramid/tests/test_static.py | 14 ++++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 88cb869a5..073ce444d 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -17,7 +17,6 @@ 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 from pyramid.path import caller_package diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 1f7ea05c2..0813eecdb 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -1429,6 +1429,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): request.subpath = ('minimal.pt', ) result = wrapped(None, request) self.assertEqual(result.status, '200 OK') + self.assertTrue(result.body.startswith(b' Date: Mon, 26 Sep 2011 05:34:45 -0400 Subject: coverage --- pyramid/tests/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 56b1349bb..5a11acd07 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -256,7 +256,7 @@ class TestRequest(unittest.TestCase): b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8' ) - if PY3: + if PY3: # pragma: no cover body = bytes(json.dumps({'a':inp}), 'utf-16') else: body = json.dumps({'a':inp}).decode('utf-8').encode('utf-16') -- cgit v1.2.3 From 7a66b778592422e32d121cf96313204c2ba23b44 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 27 Sep 2011 00:11:58 -0400 Subject: typo --- docs/narr/hooks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 3ab82ecf7..7db1eca73 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -863,8 +863,8 @@ Pyramid request handling function or another tween. ``registry`` will be the Pyramid :term:`application registry` represented by this Configurator. A tween factory must return a tween when it is called. -A tween is a callable which accepts a :term:`request` object and returns a -two-tuple a :term:`response` object. +A tween is a callable which accepts a :term:`request` object and returns +a :term:`response` object. Here's an example of a tween factory: -- cgit v1.2.3 From bce463f00c7d022b039c075ad1ee607b216ddb0d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 27 Sep 2011 02:15:01 -0400 Subject: dont try to import zope.component at module scope --- pyramid/testing.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pyramid/testing.py b/pyramid/testing.py index 89cd39a1b..b24a6cac7 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -31,13 +31,6 @@ 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: # pragma: no cover - have_zca = False - _marker = object() def registerDummySecurityPolicy(userid=None, groupids=(), permissive=True): @@ -135,9 +128,7 @@ def registerEventListener(event_iface=None): event will be appended to the list. You can then compare the values in the list to expected event notifications. This method is useful when testing code that wants to call - :meth:`pyramid.registry.Registry.notify`, - :func:`zope.component.event.dispatch` or - :func:`zope.component.event.objectEventNotify`. + :meth:`pyramid.registry.Registry.notify`. The default value of ``event_iface`` (``None``) implies a subscriber registered for *any* kind of event. @@ -727,6 +718,8 @@ class DummyRequest(DeprecatedRequestMethodsMixin, URLMethodsMixin, f = self.registry.queryUtility(IResponseFactory, default=Response) return f() +have_zca = True + def setUp(registry=None, request=None, hook_zca=True, autocommit=True, settings=None): """ @@ -811,7 +804,12 @@ def setUp(registry=None, request=None, hook_zca=True, autocommit=True, # any existing renderer factory lookup system. config.add_renderer(name, renderer) config.commit() - have_zca and hook_zca and config.hook_zca() + global have_zca + try: + have_zca and hook_zca and config.hook_zca() + except ImportError: + # pragma: no cover (dont choke on not being able to import z.component) + have_zca = False config.begin(request=request) return config @@ -826,12 +824,13 @@ def tearDown(unhook_zca=True): argument ``hook_zca=True``. If :mod:`zope.component` cannot be imported, ignore the argument. """ - if unhook_zca: + global have_zca + if unhook_zca and have_zca: try: from zope.component import getSiteManager getSiteManager.reset() except ImportError: # pragma: no cover - pass + have_zca = False info = manager.pop() manager.clear() if info is not None: -- cgit v1.2.3 From 54979dd45918ffbb411c8983d4194855856ed2aa Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 27 Sep 2011 02:15:19 -0400 Subject: add a test for builtins --- pyramid/tests/test_util.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py index 2883a968c..7c870bc45 100644 --- a/pyramid/tests/test_util.py +++ b/pyramid/tests/test_util.py @@ -1,4 +1,5 @@ import unittest +from pyramid.compat import PY3 class TestDottedNameResolver(unittest.TestCase): def _makeOne(self, package=None): @@ -14,6 +15,14 @@ class TestDottedNameResolver(unittest.TestCase): else: raise AssertionError('Invalid not raised') # pragma: no cover + def test_zope_dottedname_style_resolve_builtin(self): + typ = self._makeOne() + if PY3: + result = typ._zope_dottedname_style('builtins.str') + else: + result = typ._zope_dottedname_style('__builtin__.str') + self.assertEqual(result, str) + def test_zope_dottedname_style_resolve_absolute(self): typ = self._makeOne() result = typ._zope_dottedname_style( -- cgit v1.2.3 From dd5a91eb937369d06f3fc438c817e046fc81f891 Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Wed, 28 Sep 2011 10:37:40 +0200 Subject: Accept unicode token instances with ascii content This is required when reissueing cookies which include a token: WebOb returns the tokens from a cookie as unicode instances, so remember() must be able to deal with them when refreshing. --- pyramid/authentication.py | 2 +- pyramid/tests/test_authentication.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pyramid/authentication.py b/pyramid/authentication.py index e38c984b3..ed422b044 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -729,7 +729,7 @@ class AuthTktCookieHelper(object): for token in tokens: if isinstance(token, text_type): try: - token.encode('ascii') + token = token.encode('ascii') except UnicodeEncodeError: raise ValueError("Invalid token %r" % (token,)) if not (isinstance(token, str) and VALID_TOKEN.match(token)): diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index b612c5789..6b8393fc2 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -616,6 +616,7 @@ class TestAuthTktCookieHelper(unittest.TestCase): now = time.time() helper.auth_tkt.timestamp = now helper.now = now + 1 + helper.auth_tkt.tokens = (u'a', ) request = self._makeRequest('bogus') result = helper.identify(request) self.assertTrue(result) @@ -907,6 +908,12 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(result[2][0], 'Set-Cookie') self.assertTrue("'tokens': ('foo', 'bar')" in result[2][1]) + def test_remember_unicode_but_ascii_token(self): + helper = self._makeOne('secret') + request = self._makeRequest() + la = text_(b'foo', 'utf-8') + helper.remember(request, 'other', tokens=(la,)) + def test_remember_nonascii_token(self): helper = self._makeOne('secret') request = self._makeRequest() -- cgit v1.2.3