From 6b0e4625da2c53a1e3fdb4857fc7c6ba6ce562cf Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 31 Oct 2018 01:36:26 -0500 Subject: initial work to remove py2 from the codebase --- src/pyramid/compat.py | 302 ++++++++++-------------------------------- src/pyramid/i18n.py | 15 +-- src/pyramid/interfaces.py | 15 --- src/pyramid/request.py | 4 +- src/pyramid/scripts/pserve.py | 23 ++-- src/pyramid/session.py | 8 +- src/pyramid/testing.py | 4 +- src/pyramid/traversal.py | 61 +++------ src/pyramid/urldispatch.py | 12 +- src/pyramid/util.py | 13 +- 10 files changed, 109 insertions(+), 348 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 31832c874..77e9bea98 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -13,34 +13,15 @@ except BaseException: # pragma: no cover __pypy__ = None PYPY = False -try: - import cPickle as pickle -except ImportError: # pragma: no cover - import pickle - -try: - from functools import lru_cache -except ImportError: - from repoze.lru import lru_cache - -# PY3 is left as bw-compat but PY2 should be used for most checks. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY2: - string_types = (basestring,) - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - long = long -else: - string_types = (str,) - integer_types = (int,) - class_types = (type,) - text_type = str - binary_type = bytes - long = int +from functools import lru_cache +import pickle + +string_types = (str,) +integer_types = (int,) +class_types = (type,) +text_type = str +binary_type = bytes +long = int def text_(s, encoding='latin-1', errors='strict'): @@ -59,236 +40,105 @@ def bytes_(s, encoding='latin-1', errors='strict'): return s -if PY2: - - def ascii_native_(s): - if isinstance(s, text_type): - s = s.encode('ascii') - return str(s) - - -else: - - def ascii_native_(s): - if isinstance(s, text_type): - s = s.encode('ascii') - return str(s, 'ascii', 'strict') - - -ascii_native_.__doc__ = """ -Python 3: If ``s`` is an instance of ``text_type``, return -``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')`` - -Python 2: If ``s`` is an instance of ``text_type``, return -``s.encode('ascii')``, otherwise return ``str(s)`` -""" - - -if PY2: - - def native_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``text_type``, return - ``s.encode(encoding, errors)``, otherwise return ``str(s)``""" - if isinstance(s, text_type): - return s.encode(encoding, errors) - return str(s) - - -else: - - def native_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``text_type``, return - ``s``, otherwise return ``str(s, encoding, errors)``""" - if isinstance(s, text_type): - return s - return str(s, encoding, errors) - - -native_.__doc__ = """ -Python 3: If ``s`` is an instance of ``text_type``, return ``s``, otherwise -return ``str(s, encoding, errors)`` - -Python 2: If ``s`` is an instance of ``text_type``, return -``s.encode(encoding, errors)``, otherwise return ``str(s)`` -""" - -if PY2: - 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 - - def url_unquote_text( - v, encoding='utf-8', errors='replace' - ): # pragma: no cover - v = url_unquote(v) - return v.decode(encoding, errors) - - def url_unquote_native( - v, encoding='utf-8', errors='replace' - ): # pragma: no cover - return native_(url_unquote_text(v, encoding, errors)) - - -else: - 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 - from urllib.parse import urlencode as url_encode - from urllib.request import urlopen as url_open - - url_unquote_text = url_unquote - url_unquote_native = url_unquote - - -if PY2: # 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 ascii_native_(s): + """ + If ``s`` is an instance of ``text_type``, return + ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')`` + """ + if isinstance(s, text_type): + s = s.encode('ascii') + return str(s, 'ascii', 'strict') -else: # pragma: no cover - import builtins - exec_ = getattr(builtins, "exec") +def native_(s, encoding='latin-1', errors='strict'): + """ If ``s`` is an instance of ``text_type``, return + ``s``, otherwise return ``str(s, encoding, errors)`` + """ + if isinstance(s, text_type): + return s + return str(s, encoding, errors) - def reraise(tp, value, tb=None): - if value is None: - value = tp - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - del builtins +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 +from urllib.parse import urlencode as url_encode +from urllib.request import urlopen as url_open -if PY2: # pragma: no cover +url_unquote_text = url_unquote +url_unquote_native = url_unquote - def iteritems_(d): - return d.iteritems() - def itervalues_(d): - return d.itervalues() +import builtins - def iterkeys_(d): - return d.iterkeys() +exec_ = getattr(builtins, "exec") -else: # pragma: no cover +def reraise(tp, value, tb=None): + if value is None: + value = tp + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value - def iteritems_(d): - return d.items() - def itervalues_(d): - return d.values() +del builtins - def iterkeys_(d): - return d.keys() +def iteritems_(d): + return d.items() -if PY2: - map_ = map -else: - def map_(*arg): - return list(map(*arg)) +def itervalues_(d): + return d.values() -if PY2: +def iterkeys_(d): + return d.keys() - def is_nonstr_iter(v): - return hasattr(v, '__iter__') +def map_(*arg): + return list(map(*arg)) -else: - def is_nonstr_iter(v): - if isinstance(v, str): - return False - return hasattr(v, '__iter__') +def is_nonstr_iter(v): + if isinstance(v, str): + return False + return hasattr(v, '__iter__') -if PY2: - im_func = 'im_func' - im_self = 'im_self' -else: - im_func = '__func__' - im_self = '__self__' +im_func = '__func__' +im_self = '__self__' -try: - import configparser -except ImportError: - import ConfigParser as configparser +import configparser -try: - from http.cookies import SimpleCookie -except ImportError: - from Cookie import SimpleCookie +from http.cookies import SimpleCookie -if PY2: - from cgi import escape -else: - from html import escape +from html import escape -if PY2: - input_ = raw_input -else: - input_ = input +input_ = input -if PY2: - from io import BytesIO as NativeIO -else: - from io import StringIO as NativeIO +from io import StringIO as NativeIO # "json" is not an API; it's here to support older pyramid_debugtoolbar # versions which attempt to import it import json -if PY2: - - def decode_path_info(path): - return path.decode('utf-8') +# see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before +# decoding it to utf-8 +def decode_path_info(path): + return path.encode('latin-1').decode('utf-8') -else: - # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before - # decoding it to utf-8 - def decode_path_info(path): - return path.encode('latin-1').decode('utf-8') +# see PEP 3333 for why we decode the path to latin-1 +from urllib.parse import unquote_to_bytes -if PY2: - from urlparse import unquote as unquote_to_bytes - - def unquote_bytes_to_wsgi(bytestring): - return unquote_to_bytes(bytestring) - - -else: - # see PEP 3333 for why we decode the path to latin-1 - from urllib.parse import unquote_to_bytes - - def unquote_bytes_to_wsgi(bytestring): - return unquote_to_bytes(bytestring).decode('latin-1') +def unquote_bytes_to_wsgi(bytestring): + return unquote_to_bytes(bytestring).decode('latin-1') def is_bound_method(ob): @@ -296,15 +146,9 @@ def is_bound_method(ob): # support annotations and keyword-only arguments in PY3 -if PY2: - from inspect import getargspec -else: - from inspect import getfullargspec as getargspec +from inspect import getfullargspec as getargspec -if PY2: - from itertools import izip_longest as zip_longest -else: - from itertools import zip_longest +from itertools import zip_longest def is_unbound_method(fn): @@ -318,9 +162,7 @@ def is_unbound_method(fn): spec = getargspec(fn) has_self = len(spec.args) > 0 and spec.args[0] == 'self' - if PY2 and inspect.ismethod(fn): - return True - elif inspect.isfunction(fn) and has_self: + if inspect.isfunction(fn) and has_self: return True return False diff --git a/src/pyramid/i18n.py b/src/pyramid/i18n.py index e99a29aab..45f528852 100644 --- a/src/pyramid/i18n.py +++ b/src/pyramid/i18n.py @@ -8,7 +8,6 @@ from translationstring import ( TranslationStringFactory, # API ) -from pyramid.compat import PY2 from pyramid.decorator import reify from pyramid.interfaces import ( @@ -353,10 +352,7 @@ class Translations(gettext.GNUTranslations, object): """Like ``ugettext()``, but look the message up in the specified domain. """ - if PY2: - return self._domains.get(domain, self).ugettext(message) - else: - return self._domains.get(domain, self).gettext(message) + return self._domains.get(domain, self).gettext(message) def dngettext(self, domain, singular, plural, num): """Like ``ngettext()``, but look the message up in the specified @@ -374,14 +370,7 @@ class Translations(gettext.GNUTranslations, object): """Like ``ungettext()`` but look the message up in the specified domain. """ - if PY2: - return self._domains.get(domain, self).ungettext( - singular, plural, num - ) - else: - return self._domains.get(domain, self).ngettext( - singular, plural, num - ) + return self._domains.get(domain, self).ngettext(singular, plural, num) class LocalizerRequestMixin(object): diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py index 31bcd7e88..f1e238c6b 100644 --- a/src/pyramid/interfaces.py +++ b/src/pyramid/interfaces.py @@ -1,7 +1,5 @@ from zope.interface import Attribute, Interface -from pyramid.compat import PY2 - # public API interfaces @@ -366,19 +364,6 @@ class IDict(Interface): def values(): """ Return a list of values from the dictionary """ - if PY2: - - 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 doesn't exist, and default is provided, return the default. If k diff --git a/src/pyramid/request.py b/src/pyramid/request.py index 907b4477f..5ee87ff58 100644 --- a/src/pyramid/request.py +++ b/src/pyramid/request.py @@ -13,7 +13,7 @@ from pyramid.interfaces import ( ISessionFactory, ) -from pyramid.compat import text_, bytes_, native_, iteritems_ +from pyramid.compat import text_, bytes_, native_ from pyramid.decorator import reify from pyramid.i18n import LocalizerRequestMixin @@ -328,7 +328,7 @@ def apply_request_extensions(request, extensions=None): if extensions is None: extensions = request.registry.queryUtility(IRequestExtensions) if extensions is not None: - for name, fn in iteritems_(extensions.methods): + for name, fn in extensions.methods.items(): method = fn.__get__(request, request.__class__) setattr(request, name, method) diff --git a/src/pyramid/scripts/pserve.py b/src/pyramid/scripts/pserve.py index 581479d65..7d68521a4 100644 --- a/src/pyramid/scripts/pserve.py +++ b/src/pyramid/scripts/pserve.py @@ -19,8 +19,6 @@ import webbrowser import hupper -from pyramid.compat import PY2 - from pyramid.scripts.common import get_config_loader from pyramid.scripts.common import parse_vars from pyramid.path import AssetResolver @@ -380,18 +378,15 @@ def cherrypy_server_runner( server = WSGIServer(bind_addr, app, server_name=server_name, **kwargs) if ssl_pem is not None: - if PY2: - server.ssl_certificate = server.ssl_private_key = ssl_pem - else: - # creates wsgiserver.ssl_builtin as side-effect - try: - from cheroot.server import get_ssl_adapter_class - from cheroot.ssl.builtin import BuiltinSSLAdapter - except ImportError: - from cherrypy.wsgiserver import get_ssl_adapter_class - from cherrypy.wsgiserver.ssl_builtin import BuiltinSSLAdapter - get_ssl_adapter_class() - server.ssl_adapter = BuiltinSSLAdapter(ssl_pem, ssl_pem) + # creates wsgiserver.ssl_builtin as side-effect + try: + from cheroot.server import get_ssl_adapter_class + from cheroot.ssl.builtin import BuiltinSSLAdapter + except ImportError: + from cherrypy.wsgiserver import get_ssl_adapter_class + from cherrypy.wsgiserver.ssl_builtin import BuiltinSSLAdapter + get_ssl_adapter_class() + server.ssl_adapter = BuiltinSSLAdapter(ssl_pem, ssl_pem) if protocol_version: server.protocol = protocol_version diff --git a/src/pyramid/session.py b/src/pyramid/session.py index 68e0c506c..e9486ec6d 100644 --- a/src/pyramid/session.py +++ b/src/pyramid/session.py @@ -7,7 +7,7 @@ from zope.interface import implementer from webob.cookies import JSONSerializer, SignedSerializer -from pyramid.compat import pickle, PY2, text_, bytes_, native_ +from pyramid.compat import pickle, text_, bytes_, native_ from pyramid.csrf import check_csrf_origin, check_csrf_token from pyramid.interfaces import ISession @@ -255,12 +255,6 @@ def BaseCookieSessionFactory( __len__ = manage_accessed(dict.__len__) __iter__ = manage_accessed(dict.__iter__) - if PY2: - 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_changed(dict.clear) update = manage_changed(dict.update) diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index f700b5a4e..5fe8f8a62 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -8,7 +8,7 @@ from zope.interface import implementer, alsoProvides from pyramid.interfaces import IRequest, ISession -from pyramid.compat import PY3, PYPY, class_types, text_ +from pyramid.compat import PYPY, class_types, text_ from pyramid.config import Configurator from pyramid.decorator import reify @@ -640,8 +640,6 @@ def skip_on(*platforms): # pragma: no cover skip = True if platform == 'pypy' and PYPY: skip = True - if platform == 'py3' and PY3: - skip = True def decorator(func): if isinstance(func, class_types): diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 338b49083..f46937d73 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -9,7 +9,6 @@ from pyramid.interfaces import ( ) from pyramid.compat import ( - PY2, native_, text_, ascii_native_, @@ -580,49 +579,23 @@ the ``safe`` argument to this function. This corresponds to the """ -if PY2: - # special-case on Python 2 for speed? unchecked - def quote_path_segment(segment, safe=PATH_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 - - -else: - - def quote_path_segment(segment, safe=PATH_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 +def quote_path_segment(segment, safe=PATH_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 slash = text_('/') diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index de8a69d2a..1d3f8d91b 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -4,7 +4,6 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper, IRoute from pyramid.compat import ( - PY2, native_, text_, text_type, @@ -227,14 +226,9 @@ def _compile_route(route): def generator(dict): newdict = {} for k, v in dict.items(): - if PY2: - if v.__class__ is text_type: - # url_quote below needs bytes, not unicode on Py2 - v = v.encode('utf-8') - else: - if v.__class__ is binary_type: - # url_quote below needs a native string, not bytes on Py3 - v = v.decode('utf-8') + if v.__class__ is binary_type: + # url_quote below needs a native string, not bytes on Py3 + v = v.decode('utf-8') if k == remainder: # a stararg argument diff --git a/src/pyramid/util.py b/src/pyramid/util.py index bebf9e7d3..39b67471e 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -1,11 +1,6 @@ from contextlib import contextmanager import functools - -try: - # py2.7.7+ and py3.3+ have native comparison support - from hmac import compare_digest -except ImportError: # pragma: no cover - compare_digest = None +from hmac import compare_digest import inspect import weakref @@ -19,7 +14,6 @@ from pyramid.compat import ( string_types, bytes_, text_, - PY2, native_, ) @@ -337,10 +331,7 @@ def object_description(object): if isinstance(object, (bool, float, type(None))): return text_(str(object)) if isinstance(object, set): - if PY2: - return shortrepr(object, ')') - else: - return shortrepr(object, '}') + return shortrepr(object, '}') if isinstance(object, tuple): return shortrepr(object, ')') if isinstance(object, list): -- cgit v1.2.3 From b1a257bacc1c4ac2c1401ed02c51d9c6c03685d2 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 12 Nov 2018 23:16:09 -0600 Subject: get rid of type aliases --- src/pyramid/asset.py | 4 +-- src/pyramid/authentication.py | 12 +++---- src/pyramid/compat.py | 24 +++++--------- src/pyramid/config/__init__.py | 13 ++------ src/pyramid/config/tweens.py | 4 +-- src/pyramid/config/views.py | 12 ++----- src/pyramid/encode.py | 10 +++--- src/pyramid/httpexceptions.py | 12 +++---- src/pyramid/path.py | 8 ++--- src/pyramid/renderers.py | 6 ++-- src/pyramid/scripts/proutes.py | 3 +- src/pyramid/settings.py | 4 +-- src/pyramid/static.py | 7 ++-- src/pyramid/testing.py | 4 +-- src/pyramid/traversal.py | 72 ++++++++++++++++++++---------------------- src/pyramid/url.py | 5 +-- src/pyramid/urldispatch.py | 24 +++++--------- src/pyramid/util.py | 8 ++--- 18 files changed, 90 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/pyramid/asset.py b/src/pyramid/asset.py index 0d7575a85..a32babe6c 100644 --- a/src/pyramid/asset.py +++ b/src/pyramid/asset.py @@ -1,13 +1,11 @@ import os import pkg_resources -from pyramid.compat import string_types - from pyramid.path import package_path, package_name def resolve_asset_spec(spec, pname='__main__'): - if pname and not isinstance(pname, string_types): + if pname and not isinstance(pname, str): pname = pname.__name__ # as package if os.path.isabs(spec): return None, spec diff --git a/src/pyramid/authentication.py b/src/pyramid/authentication.py index 7cb6b6811..7810745b5 100644 --- a/src/pyramid/authentication.py +++ b/src/pyramid/authentication.py @@ -13,9 +13,6 @@ from zope.interface import implementer from webob.cookies import CookieProfile from pyramid.compat import ( - long, - text_type, - binary_type, url_unquote, url_quote, bytes_, @@ -857,9 +854,8 @@ class AuthTktCookieHelper(object): userid_type_encoders = { int: ('int', str), - long: ('int', str), - text_type: ('b64unicode', lambda x: b64encode(utf_8_encode(x)[0])), - binary_type: ('b64str', lambda x: b64encode(x)), + str: ('b64unicode', lambda x: b64encode(utf_8_encode(x)[0])), + bytes: ('b64str', lambda x: b64encode(x)), } def __init__( @@ -1048,7 +1044,7 @@ class AuthTktCookieHelper(object): "type provided.".format(type(userid)), RuntimeWarning, ) - encoding, encoder = self.userid_type_encoders.get(text_type) + encoding, encoder = self.userid_type_encoders.get(str) userid = str(userid) userid = encoder(userid) @@ -1056,7 +1052,7 @@ class AuthTktCookieHelper(object): new_tokens = [] for token in tokens: - if isinstance(token, text_type): + if isinstance(token, str): try: token = ascii_native_(token) except UnicodeEncodeError: diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 77e9bea98..47e842fbb 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -13,48 +13,40 @@ except BaseException: # pragma: no cover __pypy__ = None PYPY = False -from functools import lru_cache import pickle -string_types = (str,) -integer_types = (int,) -class_types = (type,) -text_type = str -binary_type = bytes -long = int - def text_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``binary_type``, return + """ If ``s`` is an instance of ``bytes``, return ``s.decode(encoding, errors)``, otherwise return ``s``""" - if isinstance(s, binary_type): + if isinstance(s, bytes): return s.decode(encoding, errors) return s def bytes_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``text_type``, return + """ If ``s`` is an instance of ``str``, return ``s.encode(encoding, errors)``, otherwise return ``s``""" - if isinstance(s, text_type): + if isinstance(s, str): return s.encode(encoding, errors) return s def ascii_native_(s): """ - If ``s`` is an instance of ``text_type``, return + If ``s`` is an instance of ``str``, return ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')`` """ - if isinstance(s, text_type): + if isinstance(s, str): s = s.encode('ascii') return str(s, 'ascii', 'strict') def native_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``text_type``, return + """ If ``s`` is an instance of ``str``, return ``s``, otherwise return ``str(s, encoding, errors)`` """ - if isinstance(s, text_type): + if isinstance(s, str): return s return str(s, encoding, errors) diff --git a/src/pyramid/config/__init__.py b/src/pyramid/config/__init__.py index 475f0d9a2..198532e0c 100644 --- a/src/pyramid/config/__init__.py +++ b/src/pyramid/config/__init__.py @@ -19,8 +19,6 @@ from pyramid.asset import resolve_asset_spec from pyramid.authorization import ACLAuthorizationPolicy -from pyramid.compat import text_, string_types - from pyramid.events import ApplicationCreated from pyramid.exceptions import ConfigurationError @@ -59,7 +57,6 @@ from pyramid.config.zca import ZCAConfiguratorMixin from pyramid.path import DottedNameResolver -empty = text_('') _marker = object() not_ = not_ # api @@ -367,7 +364,7 @@ class Configurator( self._set_settings(settings) - if isinstance(debug_logger, string_types): + if isinstance(debug_logger, str): debug_logger = logging.getLogger(debug_logger) if debug_logger is None: @@ -489,11 +486,7 @@ class Configurator( if not hasattr(_registry, 'registerSelfAdapter'): def registerSelfAdapter( - required=None, - provided=None, - name=empty, - info=empty, - event=True, + required=None, provided=None, name='', info='', event=True ): return _registry.registerAdapter( lambda x: x, @@ -759,7 +752,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, string_types): + if not isinstance(relative_spec, str): return relative_spec return self._make_spec(relative_spec) diff --git a/src/pyramid/config/tweens.py b/src/pyramid/config/tweens.py index 7fc786a97..7f00c5f4f 100644 --- a/src/pyramid/config/tweens.py +++ b/src/pyramid/config/tweens.py @@ -2,7 +2,7 @@ from zope.interface import implementer from pyramid.interfaces import ITweens -from pyramid.compat import string_types, is_nonstr_iter +from pyramid.compat import is_nonstr_iter from pyramid.exceptions import ConfigurationError @@ -105,7 +105,7 @@ class TweensConfiguratorMixin(object): @action_method def _add_tween(self, tween_factory, under=None, over=None, explicit=False): - if not isinstance(tween_factory, string_types): + if not isinstance(tween_factory, str): raise ConfigurationError( 'The "tween_factory" argument to add_tween must be a ' 'dotted name to a globally importable object, not %r' diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index 0c4a17376..718ea8bf3 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -32,13 +32,7 @@ from pyramid.interfaces import ( from pyramid import renderers from pyramid.asset import resolve_asset_spec -from pyramid.compat import ( - string_types, - urlparse, - url_quote, - WIN, - is_nonstr_iter, -) +from pyramid.compat import urlparse, url_quote, WIN, is_nonstr_iter from pyramid.decorator import reify @@ -889,7 +883,7 @@ class ViewsConfiguratorMixin(object): if not IInterface.providedBy(r_context): r_context = implementedBy(r_context) - if isinstance(renderer, string_types): + if isinstance(renderer, str): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry=self.registry ) @@ -1582,7 +1576,7 @@ class ViewsConfiguratorMixin(object): ): view = self.maybe_dotted(view) mapper = self.maybe_dotted(mapper) - if isinstance(renderer, string_types): + if isinstance(renderer, str): renderer = renderers.RendererHelper( name=renderer, package=self.package, registry=self.registry ) diff --git a/src/pyramid/encode.py b/src/pyramid/encode.py index 2cf2247da..428bd0c08 100644 --- a/src/pyramid/encode.py +++ b/src/pyramid/encode.py @@ -1,6 +1,4 @@ from pyramid.compat import ( - text_type, - binary_type, is_nonstr_iter, url_quote as _url_quote, url_quote_plus as _quote_plus, @@ -9,9 +7,9 @@ from pyramid.compat import ( def url_quote(val, safe=''): # bw compat api cls = val.__class__ - if cls is text_type: + if cls is str: val = val.encode('utf-8') - elif cls is not binary_type: + elif cls is not bytes: val = str(val).encode('utf-8') return _url_quote(val, safe=safe) @@ -19,9 +17,9 @@ def url_quote(val, safe=''): # bw compat api # bw compat api (dnr) def quote_plus(val, safe=''): cls = val.__class__ - if cls is text_type: + if cls is str: val = val.encode('utf-8') - elif cls is not binary_type: + elif cls is not bytes: val = str(val).encode('utf-8') return _quote_plus(val, safe=safe) diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py index 959a45f37..7e83f783f 100644 --- a/src/pyramid/httpexceptions.py +++ b/src/pyramid/httpexceptions.py @@ -137,7 +137,7 @@ from zope.interface import implementer from webob import html_escape as _html_escape from webob.acceptparse import create_accept_header -from pyramid.compat import class_types, text_type, binary_type, text_ +from pyramid.compat import text_ from pyramid.interfaces import IExceptionResponse from pyramid.response import Response @@ -146,13 +146,13 @@ from pyramid.response import Response def _no_escape(value): if value is None: return '' - if not isinstance(value, text_type): + if not isinstance(value, str): if hasattr(value, '__unicode__'): value = value.__unicode__() - if isinstance(value, binary_type): + if isinstance(value, bytes): value = text_(value, 'utf-8') else: - value = text_type(value) + value = str(value) return value @@ -326,7 +326,7 @@ ${body}''' args[k.lower()] = escape(v) body = body_tmpl.substitute(args) page = page_template.substitute(status=self.status, body=body) - if isinstance(page, text_type): + if isinstance(page, str): page = page.encode(self.charset if self.charset else 'UTF-8') self.app_iter = [page] self.body = page @@ -1331,7 +1331,7 @@ status_map = {} code = None for name, value in list(globals().items()): if ( - isinstance(value, class_types) + isinstance(value, type) and issubclass(value, HTTPException) and value not in {HTTPClientError, HTTPServerError} and not name.startswith('_') diff --git a/src/pyramid/path.py b/src/pyramid/path.py index c70be99db..47877ce5d 100644 --- a/src/pyramid/path.py +++ b/src/pyramid/path.py @@ -7,8 +7,6 @@ from zope.interface import implementer from pyramid.interfaces import IAssetDescriptor -from pyramid.compat import string_types - ignore_types = [imp.C_EXTENSION, imp.C_BUILTIN] init_names = [ '__init__%s' % x[0] @@ -101,7 +99,7 @@ class Resolver(object): if package in (None, CALLER_PACKAGE): self.package = package else: - if isinstance(package, string_types): + if isinstance(package, str): try: __import__(package) except ImportError: @@ -307,7 +305,7 @@ class DottedNameResolver(Resolver): v = r.resolve('xml') # v is the xml module """ - if not isinstance(dotted, string_types): + if not isinstance(dotted, str): raise ValueError('%r is not a string' % (dotted,)) package = self.package if package is CALLER_PACKAGE: @@ -328,7 +326,7 @@ class DottedNameResolver(Resolver): v = r.maybe_resolve(xml) # v is the xml module; no exception raised """ - if isinstance(dotted, string_types): + if isinstance(dotted, str): package = self.package if package is CALLER_PACKAGE: package = caller_package() diff --git a/src/pyramid/renderers.py b/src/pyramid/renderers.py index a8e3ec16f..832369fd4 100644 --- a/src/pyramid/renderers.py +++ b/src/pyramid/renderers.py @@ -8,8 +8,6 @@ from zope.interface.registry import Components from pyramid.interfaces import IJSONAdapter, IRendererFactory, IRendererInfo -from pyramid.compat import string_types, text_type - from pyramid.csrf import get_csrf_token from pyramid.decorator import reify @@ -169,7 +167,7 @@ def get_renderer(renderer_name, package=None, registry=None): def string_renderer_factory(info): def _render(value, system): - if not isinstance(value, string_types): + if not isinstance(value, str): value = str(value) request = system.get('request') if request is not None: @@ -485,7 +483,7 @@ class RendererHelper(object): response = response_factory(request) if result is not None: - if isinstance(result, text_type): + if isinstance(result, str): response.text = result elif isinstance(result, bytes): response.body = result diff --git a/src/pyramid/scripts/proutes.py b/src/pyramid/scripts/proutes.py index 2bce7d1de..78c2295d5 100644 --- a/src/pyramid/scripts/proutes.py +++ b/src/pyramid/scripts/proutes.py @@ -7,7 +7,6 @@ import re from zope.interface import Interface from pyramid.paster import bootstrap -from pyramid.compat import string_types from pyramid.interfaces import IRouteRequest from pyramid.config import not_ @@ -188,7 +187,7 @@ def get_route_data(route, registry): view_request_methods[view_module] = [] view_request_methods_order.append(view_module) - if isinstance(request_method, string_types): + if isinstance(request_method, str): request_method = (request_method,) elif isinstance(request_method, not_): request_method = ('!%s' % request_method.value,) diff --git a/src/pyramid/settings.py b/src/pyramid/settings.py index af9433840..d1eb4ff14 100644 --- a/src/pyramid/settings.py +++ b/src/pyramid/settings.py @@ -1,5 +1,3 @@ -from pyramid.compat import string_types - truthy = frozenset(('t', 'true', 'y', 'yes', 'on', '1')) falsey = frozenset(('f', 'false', 'n', 'no', 'off', '0')) @@ -17,7 +15,7 @@ def asbool(s): def aslist_cronly(value): - if isinstance(value, string_types): + if isinstance(value, str): value = filter(None, [x.strip() for x in value.splitlines()]) return list(value) diff --git a/src/pyramid/static.py b/src/pyramid/static.py index 58ad97a46..b300df9ee 100644 --- a/src/pyramid/static.py +++ b/src/pyramid/static.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from functools import lru_cache import json import os @@ -8,8 +9,6 @@ from pkg_resources import resource_exists, resource_filename, resource_isdir from pyramid.asset import abspath_from_asset_spec, resolve_asset_spec -from pyramid.compat import lru_cache, text_ - from pyramid.httpexceptions import HTTPNotFound, HTTPMovedPermanently from pyramid.path import caller_package @@ -18,8 +17,6 @@ from pyramid.response import _guess_type, FileResponse from pyramid.traversal import traversal_path_info -slash = text_('/') - class static_view(object): """ An instance of this class is a callable which can act as a @@ -160,7 +157,7 @@ def _secure_path(path_tuple): return None if any([_contains_slash(item) for item in path_tuple]): return None - encoded = slash.join(path_tuple) # will be unicode + encoded = '/'.join(path_tuple) # will be unicode return encoded diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index 5fe8f8a62..af8008e45 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -8,7 +8,7 @@ from zope.interface import implementer, alsoProvides from pyramid.interfaces import IRequest, ISession -from pyramid.compat import PYPY, class_types, text_ +from pyramid.compat import PYPY, text_ from pyramid.config import Configurator from pyramid.decorator import reify @@ -642,7 +642,7 @@ def skip_on(*platforms): # pragma: no cover skip = True def decorator(func): - if isinstance(func, class_types): + if isinstance(func, type): if skip: return None else: diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index f46937d73..5ff8d22ad 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -1,3 +1,4 @@ +from functools import lru_cache from zope.interface import implementer from zope.interface.interfaces import IInterface @@ -10,14 +11,10 @@ from pyramid.interfaces import ( from pyramid.compat import ( native_, - text_, ascii_native_, - text_type, - binary_type, is_nonstr_iter, decode_path_info, unquote_bytes_to_wsgi, - lru_cache, ) from pyramid.encode import url_quote @@ -28,7 +25,7 @@ from pyramid.threadlocal import get_current_registry PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob PATH_SAFE = PATH_SEGMENT_SAFE + "/" -empty = text_('') +empty = '' def find_root(resource): @@ -93,7 +90,7 @@ def find_resource(resource, path): :func:`pyramid.traversal.resource_path_tuple` can always be resolved by ``find_resource``. """ - if isinstance(path, text_type): + if isinstance(path, str): path = ascii_native_(path) D = traverse(resource, path) view_name = D['view_name'] @@ -445,7 +442,7 @@ def traversal_path(path): not. A :exc:`UnicodeEncodeError` will be raised if the Unicode cannot be encoded directly to ASCII. """ - if isinstance(path, text_type): + if isinstance(path, str): # must not possess characters outside ascii path = path.encode('ascii') # we unquote this path exactly like a PEP 3333 server would @@ -550,37 +547,36 @@ def split_path_info(path): _segment_cache = {} -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. -""" - def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): - """ %s """ % 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. + + """ # 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 @@ -589,7 +585,7 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): try: return _segment_cache[(segment, safe)] except KeyError: - if segment.__class__ not in (text_type, binary_type): + if segment.__class__ not in (str, bytes): segment = str(segment) result = url_quote(native_(segment, 'utf-8'), safe) # we don't need a lock to mutate _segment_cache, as the below @@ -598,7 +594,7 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): return result -slash = text_('/') +slash = '/' @implementer(ITraverser) diff --git a/src/pyramid/url.py b/src/pyramid/url.py index 00dd13bfe..730b7de23 100644 --- a/src/pyramid/url.py +++ b/src/pyramid/url.py @@ -1,10 +1,11 @@ """ Utility functions for dealing with URLs in pyramid """ +from functools import lru_cache import os from pyramid.interfaces import IResourceURL, IRoutesMapper, IStaticURLInfo -from pyramid.compat import bytes_, lru_cache, string_types +from pyramid.compat import bytes_ from pyramid.encode import url_quote, urlencode from pyramid.path import caller_package from pyramid.threadlocal import get_current_registry @@ -45,7 +46,7 @@ def parse_url_overrides(request, kw): qs = '' if query: - if isinstance(query, string_types): + if isinstance(query, str): qs = '?' + url_quote(query, QUERY_SAFE) else: qs = '?' + urlencode(query, doseq=True) diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index 1d3f8d91b..c1db3c969 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -3,15 +3,7 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper, IRoute -from pyramid.compat import ( - native_, - text_, - text_type, - string_types, - binary_type, - is_nonstr_iter, - decode_path_info, -) +from pyramid.compat import native_, text_, is_nonstr_iter, decode_path_info from pyramid.exceptions import URLDecodeError @@ -126,7 +118,7 @@ def _compile_route(route): # using the ASCII decoding. We decode it using ASCII because we don't # want to accept bytestrings with high-order characters in them here as # we have no idea what the encoding represents. - if route.__class__ is not text_type: + if route.__class__ is not str: try: route = text_(route, 'ascii') except UnicodeDecodeError: @@ -173,7 +165,7 @@ def _compile_route(route): name, reg = name.split(':', 1) else: reg = '[^/]+' - gen.append('%%(%s)s' % native_(name)) # native + gen.append('%%(%s)s' % name) # native name = '(?P<%s>%s)' % (name, reg) # unicode rpat.append(name) s = pat.pop() # unicode @@ -188,7 +180,7 @@ def _compile_route(route): if remainder: rpat.append('(?P<%s>.*?)' % remainder) # unicode - gen.append('%%(%s)s' % native_(remainder)) # native + gen.append('%%(%s)s' % remainder) # native pattern = ''.join(rpat) + '$' # unicode @@ -201,7 +193,7 @@ def _compile_route(route): # because we don't want to accept bytestrings with high-order # characters in them here as we have no idea what the encoding # represents. - if path.__class__ is not text_type: + if path.__class__ is not str: path = text_(path, 'ascii') m = match(path) if m is None: @@ -226,7 +218,7 @@ def _compile_route(route): def generator(dict): newdict = {} for k, v in dict.items(): - if v.__class__ is binary_type: + if v.__class__ is bytes: # url_quote below needs a native string, not bytes on Py3 v = v.decode('utf-8') @@ -235,11 +227,11 @@ def _compile_route(route): if is_nonstr_iter(v): v = '/'.join([q(x) for x in v]) # native else: - if v.__class__ not in string_types: + if v.__class__ is not str: v = str(v) v = q(v) else: - if v.__class__ not in string_types: + if v.__class__ is not str: v = str(v) # v may be bytes (py2) or native string (py3) v = q(v) diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 39b67471e..d3e5d1578 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -10,8 +10,6 @@ from pyramid.compat import ( getargspec, im_func, is_nonstr_iter, - integer_types, - string_types, bytes_, text_, native_, @@ -30,7 +28,7 @@ class DottedNameResolver(_DottedNameResolver): def is_string_or_iterable(v): - if isinstance(v, string_types): + if isinstance(v, str): return True if hasattr(v, '__iter__'): return True @@ -324,9 +322,9 @@ def object_description(object): is a boolean, an integer, a list, a tuple, a set, or ``None``, a (possibly shortened) string representation is returned. """ - if isinstance(object, string_types): + if isinstance(object, str): return text_(object) - if isinstance(object, integer_types): + if isinstance(object, int): return text_(str(object)) if isinstance(object, (bool, float, type(None))): return text_(str(object)) -- cgit v1.2.3 From 4cb6a965f7e8ce44ef609436f314b56119131f73 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 12 Nov 2018 23:19:06 -0600 Subject: get rid of pickle alias --- src/pyramid/compat.py | 2 -- src/pyramid/session.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 47e842fbb..c2d7c7f3f 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -13,8 +13,6 @@ except BaseException: # pragma: no cover __pypy__ = None PYPY = False -import pickle - def text_(s, encoding='latin-1', errors='strict'): """ If ``s`` is an instance of ``bytes``, return diff --git a/src/pyramid/session.py b/src/pyramid/session.py index e9486ec6d..1b1bfb3e5 100644 --- a/src/pyramid/session.py +++ b/src/pyramid/session.py @@ -1,5 +1,6 @@ import binascii import os +import pickle import time from zope.deprecation import deprecated @@ -7,7 +8,7 @@ from zope.interface import implementer from webob.cookies import JSONSerializer, SignedSerializer -from pyramid.compat import pickle, text_, bytes_, native_ +from pyramid.compat import text_, bytes_, native_ from pyramid.csrf import check_csrf_origin, check_csrf_token from pyramid.interfaces import ISession -- cgit v1.2.3 From d879bdfd477a138746e8593b8d9f30c492ff71e1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 12 Nov 2018 23:20:48 -0600 Subject: remove exec alias --- src/pyramid/compat.py | 8 -------- src/pyramid/scripts/pshell.py | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index c2d7c7f3f..e502cbce4 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -62,11 +62,6 @@ url_unquote_text = url_unquote url_unquote_native = url_unquote -import builtins - -exec_ = getattr(builtins, "exec") - - def reraise(tp, value, tb=None): if value is None: value = tp @@ -75,9 +70,6 @@ def reraise(tp, value, tb=None): raise value -del builtins - - def iteritems_(d): return d.items() diff --git a/src/pyramid/scripts/pshell.py b/src/pyramid/scripts/pshell.py index e63114d18..a9f02e408 100644 --- a/src/pyramid/scripts/pshell.py +++ b/src/pyramid/scripts/pshell.py @@ -6,7 +6,6 @@ import sys import textwrap import pkg_resources -from pyramid.compat import exec_ from pyramid.util import DottedNameResolver from pyramid.util import make_contextmanager from pyramid.paster import bootstrap @@ -214,7 +213,7 @@ class PShellCommand(object): if self.pystartup and os.path.isfile(self.pystartup): with open(self.pystartup, 'rb') as fp: - exec_(fp.read().decode('utf-8'), env) + exec(fp.read().decode('utf-8'), env) if '__builtins__' in env: del env['__builtins__'] -- cgit v1.2.3 From e2c7bbf5566f5be4d1b5b58d3e23948b4dc9b651 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 12 Nov 2018 23:27:59 -0600 Subject: get rid of NativeIO alias and a few others --- src/pyramid/compat.py | 28 ---------------------------- src/pyramid/security.py | 3 +-- 2 files changed, 1 insertion(+), 30 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index e502cbce4..3ad8720d6 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -70,22 +70,6 @@ def reraise(tp, value, tb=None): raise value -def iteritems_(d): - return d.items() - - -def itervalues_(d): - return d.values() - - -def iterkeys_(d): - return d.keys() - - -def map_(*arg): - return list(map(*arg)) - - def is_nonstr_iter(v): if isinstance(v, str): return False @@ -95,20 +79,10 @@ def is_nonstr_iter(v): im_func = '__func__' im_self = '__self__' -import configparser - from http.cookies import SimpleCookie from html import escape -input_ = input - -from io import StringIO as NativeIO - -# "json" is not an API; it's here to support older pyramid_debugtoolbar -# versions which attempt to import it -import json - # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before # decoding it to utf-8 def decode_path_info(path): @@ -130,8 +104,6 @@ def is_bound_method(ob): # support annotations and keyword-only arguments in PY3 from inspect import getfullargspec as getargspec -from itertools import zip_longest - def is_unbound_method(fn): """ diff --git a/src/pyramid/security.py b/src/pyramid/security.py index 08ae295d8..f8743e9a7 100644 --- a/src/pyramid/security.py +++ b/src/pyramid/security.py @@ -8,7 +8,6 @@ from pyramid.interfaces import ( IViewClassifier, ) -from pyramid.compat import map_ from pyramid.threadlocal import get_current_registry Everyone = 'system.Everyone' @@ -149,7 +148,7 @@ def view_execution_permitted(context, request, name=''): """ reg = _get_registry(request) - provides = [IViewClassifier] + map_(providedBy, (request, context)) + provides = [IViewClassifier] + [providedBy(x) for x in (request, context)] # XXX not sure what to do here about using _find_views or analogue; # for now let's just keep it as-is view = reg.adapters.lookup(provides, ISecuredView, name=name) -- cgit v1.2.3 From 656ce2b499bd05ceb9b0ae492a0be15a07dc283f Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Tue, 13 Nov 2018 10:31:58 -0600 Subject: get rid of some unnecessary constants --- src/pyramid/traversal.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 5ff8d22ad..5adf728b6 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -25,8 +25,6 @@ from pyramid.threadlocal import get_current_registry PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob PATH_SAFE = PATH_SEGMENT_SAFE + "/" -empty = '' - def find_root(resource): """ Find the root node in the resource tree to which ``resource`` @@ -594,9 +592,6 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): return result -slash = '/' - - @implementer(ITraverser) class ResourceTreeTraverser(object): """ A resource tree traverser that should be used (for speed) when @@ -616,12 +611,12 @@ class ResourceTreeTraverser(object): if matchdict is not None: - path = matchdict.get('traverse', slash) or slash + path = matchdict.get('traverse', '/') or '/' if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them - path = '/' + slash.join(path) or slash + path = '/' + '/'.join(path) or '/' subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): @@ -635,10 +630,10 @@ class ResourceTreeTraverser(object): subpath = () try: # empty if mounted under a path in mod_wsgi, for example - path = request.path_info or slash + path = request.path_info or '/' except KeyError: # if environ['PATH_INFO'] is just not there - path = slash + path = '/' except UnicodeDecodeError as e: raise URLDecodeError( e.encoding, e.object, e.start, e.end, e.reason @@ -660,7 +655,7 @@ class ResourceTreeTraverser(object): root = self.root ob = vroot = root - if vpath == slash: # invariant: vpath must not be empty + if vpath == '/': # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () @@ -714,7 +709,7 @@ class ResourceTreeTraverser(object): return { 'context': ob, - 'view_name': empty, + 'view_name': '', 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, -- cgit v1.2.3 From 9ead1d8e84edcb86ea9e07b4d2c31e7b74a098ed Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 18:45:53 -0600 Subject: move is_unbound_method to pyramid.util --- src/pyramid/compat.py | 28 ---------------------------- src/pyramid/util.py | 34 ++++++++++++++++++++++++---------- src/pyramid/viewderivers.py | 9 ++++++--- 3 files changed, 30 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 3ad8720d6..12b4b7b00 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -76,9 +76,6 @@ def is_nonstr_iter(v): return hasattr(v, '__iter__') -im_func = '__func__' -im_self = '__self__' - from http.cookies import SimpleCookie from html import escape @@ -95,28 +92,3 @@ from urllib.parse import unquote_to_bytes def unquote_bytes_to_wsgi(bytestring): return unquote_to_bytes(bytestring).decode('latin-1') - - -def is_bound_method(ob): - return inspect.ismethod(ob) and getattr(ob, im_self, None) is not None - - -# support annotations and keyword-only arguments in PY3 -from inspect import getfullargspec as getargspec - - -def is_unbound_method(fn): - """ - This consistently verifies that the callable is bound to a - class. - """ - is_bound = is_bound_method(fn) - - if not is_bound and inspect.isroutine(fn): - spec = getargspec(fn) - has_self = len(spec.args) > 0 and spec.args[0] == 'self' - - if inspect.isfunction(fn) and has_self: - return True - - return False diff --git a/src/pyramid/util.py b/src/pyramid/util.py index d3e5d1578..23cce195a 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -6,14 +6,7 @@ import weakref from pyramid.exceptions import ConfigurationError, CyclicDependencyError -from pyramid.compat import ( - getargspec, - im_func, - is_nonstr_iter, - bytes_, - text_, - native_, -) +from pyramid.compat import is_nonstr_iter, bytes_, text_, native_ from pyramid.path import DottedNameResolver as _DottedNameResolver @@ -616,13 +609,13 @@ def takes_one_arg(callee, attr=None, argname=None): return False try: - argspec = getargspec(fn) + argspec = inspect.getfullargspec(fn) except TypeError: return False args = argspec[0] - if hasattr(fn, im_func) or ismethod: + if hasattr(fn, '__func__') or ismethod: # it's an instance method (or unbound method on py2) if not args: return False @@ -653,3 +646,24 @@ class SimpleSerializer(object): def dumps(self, appstruct): return bytes_(appstruct) + + +def is_bound_method(ob): + return inspect.ismethod(ob) and getattr(ob, '__self__', None) is not None + + +def is_unbound_method(fn): + """ + This consistently verifies that the callable is bound to a + class. + """ + is_bound = is_bound_method(fn) + + if not is_bound and inspect.isroutine(fn): + spec = inspect.getfullargspec(fn) + has_self = len(spec.args) > 0 and spec.args[0] == 'self' + + if inspect.isfunction(fn) and has_self: + return True + + return False diff --git a/src/pyramid/viewderivers.py b/src/pyramid/viewderivers.py index fbe0c252c..181cc9e5c 100644 --- a/src/pyramid/viewderivers.py +++ b/src/pyramid/viewderivers.py @@ -17,11 +17,14 @@ from pyramid.interfaces import ( IViewMapperFactory, ) -from pyramid.compat import is_bound_method, is_unbound_method - from pyramid.exceptions import ConfigurationError from pyramid.httpexceptions import HTTPForbidden -from pyramid.util import object_description, takes_one_arg +from pyramid.util import ( + object_description, + takes_one_arg, + is_bound_method, + is_unbound_method, +) from pyramid.view import render_view_to_response from pyramid import renderers -- cgit v1.2.3 From 5e7361044cbd18d5d9f72f603a9861c1e69a037b Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 18:50:02 -0600 Subject: remove SimpleCookie and escape shims --- src/pyramid/compat.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 12b4b7b00..2dde5eeee 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -76,10 +76,6 @@ def is_nonstr_iter(v): return hasattr(v, '__iter__') -from http.cookies import SimpleCookie - -from html import escape - # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before # decoding it to utf-8 def decode_path_info(path): -- cgit v1.2.3 From a480acfa4381604320525b5e76e22bfb16d9c964 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 18:54:09 -0600 Subject: move reraise to pyramid.util --- src/pyramid/compat.py | 8 -------- src/pyramid/config/actions.py | 2 +- src/pyramid/tweens.py | 2 +- src/pyramid/util.py | 8 ++++++++ src/pyramid/view.py | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 2dde5eeee..17527271e 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -62,14 +62,6 @@ url_unquote_text = url_unquote url_unquote_native = url_unquote -def reraise(tp, value, tb=None): - if value is None: - value = tp - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - def is_nonstr_iter(v): if isinstance(v, str): return False diff --git a/src/pyramid/config/actions.py b/src/pyramid/config/actions.py index 9c1227d4a..4a526e242 100644 --- a/src/pyramid/config/actions.py +++ b/src/pyramid/config/actions.py @@ -5,7 +5,6 @@ import sys import traceback from zope.interface import implementer -from pyramid.compat import reraise from pyramid.exceptions import ( ConfigurationConflictError, ConfigurationError, @@ -14,6 +13,7 @@ from pyramid.exceptions import ( from pyramid.interfaces import IActionInfo from pyramid.registry import undefer from pyramid.util import is_nonstr_iter +from pyramid.util import reraise class ActionConfiguratorMixin(object): diff --git a/src/pyramid/tweens.py b/src/pyramid/tweens.py index 839c53b8f..b5660b44b 100644 --- a/src/pyramid/tweens.py +++ b/src/pyramid/tweens.py @@ -1,7 +1,7 @@ import sys -from pyramid.compat import reraise from pyramid.httpexceptions import HTTPNotFound +from pyramid.util import reraise def _error_handler(request, exc): diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 23cce195a..544fdc6de 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -667,3 +667,11 @@ def is_unbound_method(fn): return True return False + + +def reraise(tp, value, tb=None): + if value is None: + value = tp + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value diff --git a/src/pyramid/view.py b/src/pyramid/view.py index 9f58e72ae..9e85d7281 100644 --- a/src/pyramid/view.py +++ b/src/pyramid/view.py @@ -16,7 +16,6 @@ from pyramid.interfaces import ( ) from pyramid.compat import decode_path_info -from pyramid.compat import reraise as reraise_ from pyramid.exceptions import ConfigurationError, PredicateMismatch @@ -29,6 +28,7 @@ from pyramid.httpexceptions import ( from pyramid.threadlocal import get_current_registry, manager from pyramid.util import hide_attrs +from pyramid.util import reraise as reraise_ _marker = object() -- cgit v1.2.3 From 8c0cbe3be52a56ba9dc8ab6ced028dab9b48b333 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 18:58:56 -0600 Subject: move is_nonstr_iter to pyramid.util --- src/pyramid/authorization.py | 4 ++-- src/pyramid/compat.py | 6 ------ src/pyramid/config/predicates.py | 3 ++- src/pyramid/config/tweens.py | 8 +++++--- src/pyramid/config/views.py | 4 ++-- src/pyramid/encode.py | 2 +- src/pyramid/predicates.py | 4 +--- src/pyramid/traversal.py | 2 +- src/pyramid/urldispatch.py | 4 +++- src/pyramid/util.py | 8 +++++++- 10 files changed, 24 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/pyramid/authorization.py b/src/pyramid/authorization.py index 974748765..6056a8d25 100644 --- a/src/pyramid/authorization.py +++ b/src/pyramid/authorization.py @@ -4,10 +4,10 @@ from pyramid.interfaces import IAuthorizationPolicy from pyramid.location import lineage -from pyramid.compat import is_nonstr_iter - from pyramid.security import ACLAllowed, ACLDenied, Allow, Deny, Everyone +from pyramid.util import is_nonstr_iter + @implementer(IAuthorizationPolicy) class ACLAuthorizationPolicy(object): diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 17527271e..1010e93f1 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -62,12 +62,6 @@ url_unquote_text = url_unquote url_unquote_native = url_unquote -def is_nonstr_iter(v): - if isinstance(v, str): - return False - return hasattr(v, '__iter__') - - # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before # decoding it to utf-8 def decode_path_info(path): diff --git a/src/pyramid/config/predicates.py b/src/pyramid/config/predicates.py index 31e770562..789bcd6ae 100644 --- a/src/pyramid/config/predicates.py +++ b/src/pyramid/config/predicates.py @@ -1,12 +1,13 @@ from hashlib import md5 from webob.acceptparse import Accept -from pyramid.compat import bytes_, is_nonstr_iter +from pyramid.compat import bytes_ from pyramid.exceptions import ConfigurationError from pyramid.interfaces import IPredicateList, PHASE1_CONFIG from pyramid.predicates import Notted from pyramid.registry import predvalseq from pyramid.util import TopologicalSorter +from pyramid.util import is_nonstr_iter MAX_ORDER = 1 << 30 diff --git a/src/pyramid/config/tweens.py b/src/pyramid/config/tweens.py index 7f00c5f4f..c85639d14 100644 --- a/src/pyramid/config/tweens.py +++ b/src/pyramid/config/tweens.py @@ -2,13 +2,15 @@ from zope.interface import implementer from pyramid.interfaces import ITweens -from pyramid.compat import is_nonstr_iter - from pyramid.exceptions import ConfigurationError from pyramid.tweens import MAIN, INGRESS, EXCVIEW -from pyramid.util import is_string_or_iterable, TopologicalSorter +from pyramid.util import ( + is_nonstr_iter, + is_string_or_iterable, + TopologicalSorter, +) from pyramid.config.actions import action_method diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index 718ea8bf3..0039cd8fe 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -32,7 +32,7 @@ from pyramid.interfaces import ( from pyramid import renderers from pyramid.asset import resolve_asset_spec -from pyramid.compat import urlparse, url_quote, WIN, is_nonstr_iter +from pyramid.compat import urlparse, url_quote, WIN from pyramid.decorator import reify @@ -53,7 +53,7 @@ from pyramid.url import parse_url_overrides from pyramid.view import AppendSlashNotFoundViewFactory -from pyramid.util import as_sorted_tuple, TopologicalSorter +from pyramid.util import as_sorted_tuple, is_nonstr_iter, TopologicalSorter import pyramid.predicates import pyramid.viewderivers diff --git a/src/pyramid/encode.py b/src/pyramid/encode.py index 428bd0c08..1ed2c5a55 100644 --- a/src/pyramid/encode.py +++ b/src/pyramid/encode.py @@ -1,8 +1,8 @@ from pyramid.compat import ( - is_nonstr_iter, url_quote as _url_quote, url_quote_plus as _quote_plus, ) +from pyramid.util import is_nonstr_iter def url_quote(val, safe=''): # bw compat api diff --git a/src/pyramid/predicates.py b/src/pyramid/predicates.py index 280f6c03c..5a1127fb3 100644 --- a/src/pyramid/predicates.py +++ b/src/pyramid/predicates.py @@ -2,8 +2,6 @@ import re from pyramid.exceptions import ConfigurationError -from pyramid.compat import is_nonstr_iter - from pyramid.csrf import check_csrf_token from pyramid.traversal import ( find_interface, @@ -12,7 +10,7 @@ from pyramid.traversal import ( ) from pyramid.urldispatch import _compile_route -from pyramid.util import as_sorted_tuple, object_description +from pyramid.util import as_sorted_tuple, is_nonstr_iter, object_description _marker = object() diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 5adf728b6..429b12e23 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -12,7 +12,6 @@ from pyramid.interfaces import ( from pyramid.compat import ( native_, ascii_native_, - is_nonstr_iter, decode_path_info, unquote_bytes_to_wsgi, ) @@ -21,6 +20,7 @@ from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage from pyramid.threadlocal import get_current_registry +from pyramid.util import is_nonstr_iter PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob PATH_SAFE = PATH_SEGMENT_SAFE + "/" diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index c1db3c969..6d25b2dd5 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -3,12 +3,14 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper, IRoute -from pyramid.compat import native_, text_, is_nonstr_iter, decode_path_info +from pyramid.compat import native_, text_, decode_path_info from pyramid.exceptions import URLDecodeError from pyramid.traversal import quote_path_segment, split_path_info, PATH_SAFE +from pyramid.util import is_nonstr_iter + _marker = object() diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 544fdc6de..6cd8225aa 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -6,7 +6,7 @@ import weakref from pyramid.exceptions import ConfigurationError, CyclicDependencyError -from pyramid.compat import is_nonstr_iter, bytes_, text_, native_ +from pyramid.compat import bytes_, text_, native_ from pyramid.path import DottedNameResolver as _DottedNameResolver @@ -20,6 +20,12 @@ class DottedNameResolver(_DottedNameResolver): _DottedNameResolver.__init__(self, package) +def is_nonstr_iter(v): + if isinstance(v, str): + return False + return hasattr(v, '__iter__') + + def is_string_or_iterable(v): if isinstance(v, str): return True -- cgit v1.2.3 From 0b570220d9f442700eb97c5a5c4eca6ab03a1ee4 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 19:13:07 -0600 Subject: remove urllib.parse shims --- src/pyramid/authentication.py | 17 ++++------------- src/pyramid/compat.py | 13 ------------- src/pyramid/config/routes.py | 4 ++-- src/pyramid/config/views.py | 14 ++++++-------- src/pyramid/csrf.py | 5 +++-- src/pyramid/encode.py | 7 +++---- src/pyramid/scripts/prequest.py | 4 ++-- 7 files changed, 20 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/pyramid/authentication.py b/src/pyramid/authentication.py index 7810745b5..05131a521 100644 --- a/src/pyramid/authentication.py +++ b/src/pyramid/authentication.py @@ -6,19 +6,14 @@ import hashlib import base64 import re import time as time_mod +from urllib.parse import quote, unquote import warnings from zope.interface import implementer from webob.cookies import CookieProfile -from pyramid.compat import ( - url_unquote, - url_quote, - bytes_, - ascii_native_, - native_, -) +from pyramid.compat import bytes_, ascii_native_, native_ from pyramid.interfaces import IAuthenticationPolicy, IDebugLogger @@ -724,11 +719,7 @@ class AuthTicket(object): ) def cookie_value(self): - v = '%s%08x%s!' % ( - self.digest(), - int(self.time), - url_quote(self.userid), - ) + v = '%s%08x%s!' % (self.digest(), int(self.time), quote(self.userid)) if self.tokens: v += self.tokens + '!' v += self.user_data @@ -767,7 +758,7 @@ def parse_ticket(secret, ticket, ip, hashalg='md5'): userid, data = ticket[digest_size + 8 :].split('!', 1) except ValueError: raise BadTicket('userid is not followed by !') - userid = url_unquote(userid) + userid = unquote(userid) if '!' in data: tokens, user_data = data.split('!', 1) else: # pragma: no cover (never generated) diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 1010e93f1..10d3c4998 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -49,19 +49,6 @@ def native_(s, encoding='latin-1', errors='strict'): return str(s, encoding, errors) -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 -from urllib.parse import urlencode as url_encode -from urllib.request import urlopen as url_open - -url_unquote_text = url_unquote -url_unquote_native = url_unquote - - # see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before # decoding it to utf-8 def decode_path_info(path): diff --git a/src/pyramid/config/routes.py b/src/pyramid/config/routes.py index 52540c935..4b26b7481 100644 --- a/src/pyramid/config/routes.py +++ b/src/pyramid/config/routes.py @@ -1,7 +1,7 @@ import contextlib +from urllib.parse import urlparse import warnings -from pyramid.compat import urlparse from pyramid.interfaces import ( IRequest, IRouteRequest, @@ -358,7 +358,7 @@ class RoutesConfiguratorMixin(object): # check for an external route; an external route is one which is # is a full url (e.g. 'http://example.com/{id}') - parsed = urlparse.urlparse(pattern) + parsed = urlparse(pattern) external_url = pattern if parsed.hostname: diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index 0039cd8fe..484c0d754 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -5,6 +5,7 @@ import operator import os import warnings +from urllib.parse import quote, urljoin, urlparse, urlunparse from webob.acceptparse import Accept from zope.interface import Interface, implementedBy, implementer from zope.interface.interfaces import IInterface @@ -32,7 +33,7 @@ from pyramid.interfaces import ( from pyramid import renderers from pyramid.asset import resolve_asset_spec -from pyramid.compat import urlparse, url_quote, WIN +from pyramid.compat import WIN from pyramid.decorator import reify @@ -77,9 +78,6 @@ from pyramid.config.predicates import ( sort_accept_offers, ) -urljoin = urlparse.urljoin -url_parse = urlparse.urlparse - DefaultViewMapper = DefaultViewMapper # bw-compat preserve_view_attrs = preserve_view_attrs # bw-compat requestonly = requestonly # bw-compat @@ -2191,14 +2189,14 @@ class StaticURLInfo(object): return request.route_url(route_name, **kw) else: app_url, qs, anchor = parse_url_overrides(request, kw) - parsed = url_parse(url) + parsed = urlparse(url) if not parsed.scheme: - url = urlparse.urlunparse( + url = urlunparse( parsed._replace( scheme=request.environ['wsgi.url_scheme'] ) ) - subpath = url_quote(subpath) + subpath = quote(subpath) result = urljoin(url, subpath) return result + qs + anchor @@ -2227,7 +2225,7 @@ class StaticURLInfo(object): # make sure it ends with a slash name = name + '/' - if url_parse(name).netloc: + if urlparse(name).netloc: # it's a URL # url, spec, route_name url = name diff --git a/src/pyramid/csrf.py b/src/pyramid/csrf.py index fba5d9baa..ece55ce10 100644 --- a/src/pyramid/csrf.py +++ b/src/pyramid/csrf.py @@ -1,10 +1,11 @@ +from urllib.parse import urlparse import uuid from webob.cookies import CookieProfile from zope.interface import implementer -from pyramid.compat import bytes_, urlparse, text_ +from pyramid.compat import bytes_, text_ from pyramid.exceptions import BadCSRFOrigin, BadCSRFToken from pyramid.interfaces import ICSRFStoragePolicy from pyramid.settings import aslist @@ -303,7 +304,7 @@ def check_csrf_origin(request, trusted_origins=None, raises=True): # Parse our origin so we we can extract the required information from # it. - originp = urlparse.urlparse(origin) + originp = urlparse(origin) # Ensure that our Referer is also secure. if originp.scheme != "https": diff --git a/src/pyramid/encode.py b/src/pyramid/encode.py index 1ed2c5a55..11d3a7787 100644 --- a/src/pyramid/encode.py +++ b/src/pyramid/encode.py @@ -1,7 +1,6 @@ -from pyramid.compat import ( - url_quote as _url_quote, - url_quote_plus as _quote_plus, -) +from urllib.parse import quote as _url_quote +from urllib.parse import quote_plus as _quote_plus + from pyramid.util import is_nonstr_iter diff --git a/src/pyramid/scripts/prequest.py b/src/pyramid/scripts/prequest.py index e8f5ff8b3..eb2032419 100644 --- a/src/pyramid/scripts/prequest.py +++ b/src/pyramid/scripts/prequest.py @@ -2,8 +2,8 @@ import base64 import argparse import sys import textwrap +from urllib.parse import unquote -from pyramid.compat import url_unquote from pyramid.request import Request from pyramid.scripts.common import get_config_loader from pyramid.scripts.common import parse_vars @@ -152,7 +152,7 @@ class PRequestCommand(object): except ValueError: qs = '' - path = url_unquote(path) + path = unquote(path) headers = {} if self.args.login: -- cgit v1.2.3 From a705f56c3ebf34f25ab567d85b7d5b421983aa4a Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 20:35:39 -0600 Subject: rely on webob for request.path_info and request.scheme --- src/pyramid/compat.py | 17 ----------------- src/pyramid/config/testing.py | 4 ++-- src/pyramid/config/views.py | 4 +--- src/pyramid/scripts/pviews.py | 2 +- src/pyramid/static.py | 2 +- src/pyramid/traversal.py | 19 +++++++++++++------ src/pyramid/urldispatch.py | 13 ++++--------- src/pyramid/view.py | 4 +--- 8 files changed, 23 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 10d3c4998..30fc10395 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -1,7 +1,4 @@ -import inspect import platform -import sys -import types WIN = platform.system() == 'Windows' @@ -47,17 +44,3 @@ def native_(s, encoding='latin-1', errors='strict'): if isinstance(s, str): return s return str(s, encoding, errors) - - -# see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before -# decoding it to utf-8 -def decode_path_info(path): - return path.encode('latin-1').decode('utf-8') - - -# see PEP 3333 for why we decode the path to latin-1 -from urllib.parse import unquote_to_bytes - - -def unquote_bytes_to_wsgi(bytestring): - return unquote_to_bytes(bytestring).decode('latin-1') diff --git a/src/pyramid/config/testing.py b/src/pyramid/config/testing.py index bba5054e6..9c998840a 100644 --- a/src/pyramid/config/testing.py +++ b/src/pyramid/config/testing.py @@ -9,7 +9,7 @@ from pyramid.interfaces import ( from pyramid.renderers import RendererHelper -from pyramid.traversal import decode_path_info, split_path_info +from pyramid.traversal import split_path_info from pyramid.config.actions import action_method @@ -95,7 +95,7 @@ class TestingConfiguratorMixin(object): self.context = context def __call__(self, request): - path = decode_path_info(request.environ['PATH_INFO']) + path = request.path_info ob = resources[path] traversed = split_path_info(path) return { diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index 484c0d754..412e30304 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -2192,9 +2192,7 @@ class StaticURLInfo(object): parsed = urlparse(url) if not parsed.scheme: url = urlunparse( - parsed._replace( - scheme=request.environ['wsgi.url_scheme'] - ) + parsed._replace(scheme=request.scheme) ) subpath = quote(subpath) result = urljoin(url, subpath) diff --git a/src/pyramid/scripts/pviews.py b/src/pyramid/scripts/pviews.py index 891dc4709..d2a4bfa40 100644 --- a/src/pyramid/scripts/pviews.py +++ b/src/pyramid/scripts/pviews.py @@ -70,7 +70,7 @@ class PViewsCommand(object): def _find_multi_routes(self, mapper, request): infos = [] - path = request.environ['PATH_INFO'] + path = request.path_info # find all routes that match path, regardless of predicates for route in mapper.get_routes(): match = route.match(path) diff --git a/src/pyramid/static.py b/src/pyramid/static.py index b300df9ee..e3561e93e 100644 --- a/src/pyramid/static.py +++ b/src/pyramid/static.py @@ -88,7 +88,7 @@ class static_view(object): if self.use_subpath: path_tuple = request.subpath else: - path_tuple = traversal_path_info(request.environ['PATH_INFO']) + path_tuple = traversal_path_info(request.path_info) path = _secure_path(path_tuple) if path is None: diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 429b12e23..e846881f3 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -1,4 +1,6 @@ from functools import lru_cache +from urllib.parse import unquote_to_bytes + from zope.interface import implementer from zope.interface.interfaces import IInterface @@ -9,12 +11,7 @@ from pyramid.interfaces import ( VH_ROOT_KEY, ) -from pyramid.compat import ( - native_, - ascii_native_, - decode_path_info, - unquote_bytes_to_wsgi, -) +from pyramid.compat import native_, ascii_native_ from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError @@ -543,6 +540,16 @@ def split_path_info(path): return tuple(clean) +# see PEP 3333 for why we encode to latin-1 then decode to utf-8 +def decode_path_info(path): + return path.encode('latin-1').decode('utf-8') + + +# see PEP 3333 for why we decode the path to latin-1 +def unquote_bytes_to_wsgi(bytestring): + return unquote_to_bytes(bytestring).decode('latin-1') + + _segment_cache = {} diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index 6d25b2dd5..6348ae7e2 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -3,7 +3,7 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper, IRoute -from pyramid.compat import native_, text_, decode_path_info +from pyramid.compat import text_ from pyramid.exceptions import URLDecodeError @@ -75,10 +75,9 @@ class RoutesMapper(object): return self.routes[name].generate(kw) def __call__(self, request): - environ = request.environ try: # empty if mounted under a path in mod_wsgi, for example - path = decode_path_info(environ['PATH_INFO'] or '/') + path = request.path_info or '/' except KeyError: path = '/' except UnicodeDecodeError as e: @@ -202,14 +201,10 @@ def _compile_route(route): return None d = {} for k, v in m.groupdict().items(): - # k and v will be Unicode 2.6.4 and lower doesnt accept unicode - # kwargs as **kw, so we explicitly cast the keys to native - # strings in case someone wants to pass the result as **kw - nk = native_(k, 'ascii') if k == remainder: - d[nk] = split_path_info(v) + d[k] = split_path_info(v) else: - d[nk] = v + d[k] = v return d gen = ''.join(gen) diff --git a/src/pyramid/view.py b/src/pyramid/view.py index 9e85d7281..944ad93ea 100644 --- a/src/pyramid/view.py +++ b/src/pyramid/view.py @@ -15,8 +15,6 @@ from pyramid.interfaces import ( IExceptionViewClassifier, ) -from pyramid.compat import decode_path_info - from pyramid.exceptions import ConfigurationError, PredicateMismatch from pyramid.httpexceptions import ( @@ -305,7 +303,7 @@ class AppendSlashNotFoundViewFactory(object): self.redirect_class = redirect_class def __call__(self, context, request): - path = decode_path_info(request.environ['PATH_INFO'] or '/') + path = request.path_info registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and not path.endswith('/'): -- cgit v1.2.3 From 78dcc6dff88829831ead187804ac9233eafab52e Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 21:26:39 -0600 Subject: remove several places supporting bytes for py2 --- src/pyramid/response.py | 4 +--- src/pyramid/urldispatch.py | 11 +---------- src/pyramid/util.py | 27 ++++++++++++--------------- 3 files changed, 14 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/pyramid/response.py b/src/pyramid/response.py index 38f9fa1ce..8a2ba8929 100644 --- a/src/pyramid/response.py +++ b/src/pyramid/response.py @@ -100,14 +100,12 @@ class FileIter(object): def __iter__(self): return self - def next(self): + def __next__(self): val = self.file.read(self.block_size) if not val: raise StopIteration return val - __next__ = next # py3 - def close(self): self.file.close() diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index 6348ae7e2..97626c5dd 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -188,14 +188,6 @@ def _compile_route(route): match = re.compile(pattern).match def matcher(path): - # This function really wants to consume Unicode patterns natively, - # but if someone passes us a bytestring, we allow it by converting it - # to Unicode using the ASCII decoding. We decode it using ASCII - # because we don't want to accept bytestrings with high-order - # characters in them here as we have no idea what the encoding - # represents. - if path.__class__ is not str: - path = text_(path, 'ascii') m = match(path) if m is None: return None @@ -216,7 +208,7 @@ def _compile_route(route): newdict = {} for k, v in dict.items(): if v.__class__ is bytes: - # url_quote below needs a native string, not bytes on Py3 + # url_quote below needs a native string v = v.decode('utf-8') if k == remainder: @@ -230,7 +222,6 @@ def _compile_route(route): else: if v.__class__ is not str: v = str(v) - # v may be bytes (py2) or native string (py3) v = q(v) # at this point, the value will be a native string diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 6cd8225aa..0688e67d3 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -603,10 +603,7 @@ def takes_one_arg(callee, attr=None, argname=None): if inspect.isroutine(callee): fn = callee elif inspect.isclass(callee): - try: - fn = callee.__init__ - except AttributeError: - return False + fn = callee.__init__ ismethod = hasattr(fn, '__call__') else: try: @@ -614,15 +611,11 @@ def takes_one_arg(callee, attr=None, argname=None): except AttributeError: return False - try: - argspec = inspect.getfullargspec(fn) - except TypeError: - return False - + argspec = inspect.getfullargspec(fn) args = argspec[0] if hasattr(fn, '__func__') or ismethod: - # it's an instance method (or unbound method on py2) + # it's an instance method if not args: return False args = args[1:] @@ -676,8 +669,12 @@ def is_unbound_method(fn): def reraise(tp, value, tb=None): - if value is None: - value = tp - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None -- cgit v1.2.3 From 2f8ede09e52162e475aececf587b21e96a2b1a79 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 22:15:57 -0600 Subject: move text_, bytes_ and ascii_ to pyramid.util and remove native_ --- src/pyramid/authentication.py | 13 +++----- src/pyramid/compat.py | 35 -------------------- src/pyramid/config/__init__.py | 3 +- src/pyramid/config/predicates.py | 3 +- src/pyramid/csrf.py | 12 ++++--- src/pyramid/httpexceptions.py | 3 +- src/pyramid/registry.py | 5 +-- src/pyramid/request.py | 11 ++++--- src/pyramid/session.py | 5 +-- src/pyramid/testing.py | 4 +-- src/pyramid/traversal.py | 10 +++--- src/pyramid/url.py | 2 +- src/pyramid/urldispatch.py | 4 +-- src/pyramid/util.py | 71 +++++++++++++++++++++++++++++----------- 14 files changed, 87 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/pyramid/authentication.py b/src/pyramid/authentication.py index 05131a521..21cfc0c0e 100644 --- a/src/pyramid/authentication.py +++ b/src/pyramid/authentication.py @@ -13,13 +13,11 @@ from zope.interface import implementer from webob.cookies import CookieProfile -from pyramid.compat import bytes_, ascii_native_, native_ - from pyramid.interfaces import IAuthenticationPolicy, IDebugLogger from pyramid.security import Authenticated, Everyone -from pyramid.util import strings_differ +from pyramid.util import strings_differ, bytes_, ascii_, text_ from pyramid.util import SimpleSerializer VALID_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9+_-]*$") @@ -747,7 +745,7 @@ def parse_ticket(secret, ticket, ip, hashalg='md5'): If the ticket cannot be parsed, a ``BadTicket`` exception will be raised with an explanation. """ - ticket = native_(ticket).strip('"') + ticket = text_(ticket).strip('"') digest_size = hashlib.new(hashalg).digest_size * 2 digest = ticket[:digest_size] try: @@ -866,16 +864,13 @@ class AuthTktCookieHelper(object): domain=None, samesite='Lax', ): - - serializer = SimpleSerializer() - self.cookie_profile = CookieProfile( cookie_name=cookie_name, secure=secure, max_age=max_age, httponly=http_only, path=path, - serializer=serializer, + serializer=SimpleSerializer(), samesite=samesite, ) @@ -1045,7 +1040,7 @@ class AuthTktCookieHelper(object): for token in tokens: if isinstance(token, str): try: - token = ascii_native_(token) + token = ascii_(token) except UnicodeEncodeError: raise ValueError("Invalid token %r" % (token,)) if not (isinstance(token, str) and VALID_TOKEN.match(token)): diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py index 30fc10395..ec0ca7017 100644 --- a/src/pyramid/compat.py +++ b/src/pyramid/compat.py @@ -9,38 +9,3 @@ try: # pragma: no cover except BaseException: # pragma: no cover __pypy__ = None PYPY = False - - -def text_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``bytes``, return - ``s.decode(encoding, errors)``, otherwise return ``s``""" - if isinstance(s, bytes): - return s.decode(encoding, errors) - return s - - -def bytes_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``str``, return - ``s.encode(encoding, errors)``, otherwise return ``s``""" - if isinstance(s, str): - return s.encode(encoding, errors) - return s - - -def ascii_native_(s): - """ - If ``s`` is an instance of ``str``, return - ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')`` - """ - if isinstance(s, str): - s = s.encode('ascii') - return str(s, 'ascii', 'strict') - - -def native_(s, encoding='latin-1', errors='strict'): - """ If ``s`` is an instance of ``str``, return - ``s``, otherwise return ``str(s, encoding, errors)`` - """ - if isinstance(s, str): - return s - return str(s, encoding, errors) diff --git a/src/pyramid/config/__init__.py b/src/pyramid/config/__init__.py index 198532e0c..072b654c4 100644 --- a/src/pyramid/config/__init__.py +++ b/src/pyramid/config/__init__.py @@ -35,7 +35,7 @@ from pyramid.settings import aslist from pyramid.threadlocal import manager -from pyramid.util import WeakOrderedSet, object_description +from pyramid.util import WeakOrderedSet, get_callable_name, object_description from pyramid.config.actions import action_method, ActionState from pyramid.config.predicates import not_ @@ -698,6 +698,7 @@ class Configurator( ``add_directive`` does not participate in conflict detection, and later calls to ``add_directive`` will override earlier calls. """ + name = get_callable_name(name) c = self.maybe_dotted(directive) if not hasattr(self.registry, '_directives'): self.registry._directives = {} diff --git a/src/pyramid/config/predicates.py b/src/pyramid/config/predicates.py index 789bcd6ae..3eb07c17d 100644 --- a/src/pyramid/config/predicates.py +++ b/src/pyramid/config/predicates.py @@ -1,13 +1,12 @@ from hashlib import md5 from webob.acceptparse import Accept -from pyramid.compat import bytes_ from pyramid.exceptions import ConfigurationError from pyramid.interfaces import IPredicateList, PHASE1_CONFIG from pyramid.predicates import Notted from pyramid.registry import predvalseq from pyramid.util import TopologicalSorter -from pyramid.util import is_nonstr_iter +from pyramid.util import is_nonstr_iter, bytes_ MAX_ORDER = 1 << 30 diff --git a/src/pyramid/csrf.py b/src/pyramid/csrf.py index ece55ce10..26c628acc 100644 --- a/src/pyramid/csrf.py +++ b/src/pyramid/csrf.py @@ -5,11 +5,16 @@ from webob.cookies import CookieProfile from zope.interface import implementer -from pyramid.compat import bytes_, text_ from pyramid.exceptions import BadCSRFOrigin, BadCSRFToken from pyramid.interfaces import ICSRFStoragePolicy from pyramid.settings import aslist -from pyramid.util import SimpleSerializer, is_same_domain, strings_differ +from pyramid.util import ( + SimpleSerializer, + is_same_domain, + strings_differ, + bytes_, + text_, +) @implementer(ICSRFStoragePolicy) @@ -118,7 +123,6 @@ class CookieCSRFStoragePolicy(object): path='/', samesite='Lax', ): - serializer = SimpleSerializer() self.cookie_profile = CookieProfile( cookie_name=cookie_name, secure=secure, @@ -126,7 +130,7 @@ class CookieCSRFStoragePolicy(object): httponly=httponly, path=path, domains=[domain], - serializer=serializer, + serializer=SimpleSerializer(), samesite=samesite, ) self.cookie_name = cookie_name diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py index 7e83f783f..56797dc88 100644 --- a/src/pyramid/httpexceptions.py +++ b/src/pyramid/httpexceptions.py @@ -137,10 +137,9 @@ from zope.interface import implementer from webob import html_escape as _html_escape from webob.acceptparse import create_accept_header -from pyramid.compat import text_ - from pyramid.interfaces import IExceptionResponse from pyramid.response import Response +from pyramid.util import text_ def _no_escape(value): diff --git a/src/pyramid/registry.py b/src/pyramid/registry.py index c24125830..7b2547dd7 100644 --- a/src/pyramid/registry.py +++ b/src/pyramid/registry.py @@ -4,15 +4,12 @@ import threading from zope.interface import implementer from zope.interface.registry import Components -from pyramid.compat import text_ from pyramid.decorator import reify from pyramid.interfaces import IIntrospector, IIntrospectable, ISettings from pyramid.path import CALLER_PACKAGE, caller_package -empty = text_('') - class Registry(Components, dict): """ A registry object is an :term:`application registry`. @@ -77,7 +74,7 @@ class Registry(Components, dict): return result def registerSelfAdapter( - self, required=None, provided=None, name=empty, info=empty, event=True + self, required=None, provided=None, name='', info='', event=True ): # registerAdapter analogue which always returns the object itself # when required is matched diff --git a/src/pyramid/request.py b/src/pyramid/request.py index 5ee87ff58..23c00468d 100644 --- a/src/pyramid/request.py +++ b/src/pyramid/request.py @@ -13,14 +13,17 @@ from pyramid.interfaces import ( ISessionFactory, ) -from pyramid.compat import text_, bytes_, native_ - from pyramid.decorator import reify from pyramid.i18n import LocalizerRequestMixin from pyramid.response import Response, _get_response_factory from pyramid.security import AuthenticationAPIMixin, AuthorizationAPIMixin from pyramid.url import URLMethodsMixin -from pyramid.util import InstancePropertyHelper, InstancePropertyMixin +from pyramid.util import ( + InstancePropertyHelper, + InstancePropertyMixin, + text_, + bytes_, +) from pyramid.view import ViewMethodsMixin @@ -281,7 +284,7 @@ def call_app_with_subpath_as_path_info(request, app): # compute new_path_info new_path_info = '/' + '/'.join( - [native_(x.encode('utf-8'), 'latin-1') for x in subpath] + [text_(x.encode('utf-8'), 'latin-1') for x in subpath] ) if new_path_info != '/': # don't want a sole double-slash diff --git a/src/pyramid/session.py b/src/pyramid/session.py index 1b1bfb3e5..70ac4f55f 100644 --- a/src/pyramid/session.py +++ b/src/pyramid/session.py @@ -8,11 +8,12 @@ from zope.interface import implementer from webob.cookies import JSONSerializer, SignedSerializer -from pyramid.compat import text_, bytes_, native_ from pyramid.csrf import check_csrf_origin, check_csrf_token from pyramid.interfaces import ISession +from pyramid.util import text_, bytes_ + def manage_accessed(wrapped): """ Decorator which causes a cookie to be renewed when an accessor @@ -304,7 +305,7 @@ def BaseCookieSessionFactory( exception is not None ): # dont set a cookie during exceptions return False - cookieval = native_( + cookieval = text_( serializer.dumps((self.accessed, self.created, dict(self))) ) if len(cookieval) > 4064: diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index af8008e45..04497234b 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -8,7 +8,7 @@ from zope.interface import implementer, alsoProvides from pyramid.interfaces import IRequest, ISession -from pyramid.compat import PYPY, text_ +from pyramid.compat import PYPY from pyramid.config import Configurator from pyramid.decorator import reify @@ -28,7 +28,7 @@ from pyramid.threadlocal import get_current_registry, manager from pyramid.i18n import LocalizerRequestMixin from pyramid.request import CallbackMethodsMixin from pyramid.url import URLMethodsMixin -from pyramid.util import InstancePropertyMixin +from pyramid.util import InstancePropertyMixin, text_ from pyramid.view import ViewMethodsMixin diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index e846881f3..7de4c3f91 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -11,13 +11,11 @@ from pyramid.interfaces import ( VH_ROOT_KEY, ) -from pyramid.compat import native_, ascii_native_ - from pyramid.encode import url_quote from pyramid.exceptions import URLDecodeError from pyramid.location import lineage from pyramid.threadlocal import get_current_registry -from pyramid.util import is_nonstr_iter +from pyramid.util import ascii_, is_nonstr_iter, text_ PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob PATH_SAFE = PATH_SEGMENT_SAFE + "/" @@ -86,7 +84,7 @@ def find_resource(resource, path): resolved by ``find_resource``. """ if isinstance(path, str): - path = ascii_native_(path) + path = ascii_(path) D = traverse(resource, path) view_name = D['view_name'] context = D['context'] @@ -303,7 +301,7 @@ def traverse(resource, path): # step rather than later down the line as the result of calling # ``traversal_path``). - path = ascii_native_(path) + path = ascii_(path) if path and path[0] == '/': resource = find_root(resource) @@ -592,7 +590,7 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): except KeyError: if segment.__class__ not in (str, bytes): segment = str(segment) - result = url_quote(native_(segment, 'utf-8'), safe) + result = url_quote(text_(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/src/pyramid/url.py b/src/pyramid/url.py index 730b7de23..22551a349 100644 --- a/src/pyramid/url.py +++ b/src/pyramid/url.py @@ -5,10 +5,10 @@ import os from pyramid.interfaces import IResourceURL, IRoutesMapper, IStaticURLInfo -from pyramid.compat import bytes_ from pyramid.encode import url_quote, urlencode from pyramid.path import caller_package from pyramid.threadlocal import get_current_registry +from pyramid.util import bytes_ from pyramid.traversal import ( ResourceURL, diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py index 97626c5dd..73b7be9f3 100644 --- a/src/pyramid/urldispatch.py +++ b/src/pyramid/urldispatch.py @@ -3,13 +3,11 @@ from zope.interface import implementer from pyramid.interfaces import IRoutesMapper, IRoute -from pyramid.compat import text_ - from pyramid.exceptions import URLDecodeError from pyramid.traversal import quote_path_segment, split_path_info, PATH_SAFE -from pyramid.util import is_nonstr_iter +from pyramid.util import is_nonstr_iter, text_ _marker = object() diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 0688e67d3..ab46c91f7 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -4,10 +4,6 @@ from hmac import compare_digest import inspect import weakref -from pyramid.exceptions import ConfigurationError, CyclicDependencyError - -from pyramid.compat import bytes_, text_, native_ - from pyramid.path import DottedNameResolver as _DottedNameResolver _marker = object() @@ -20,6 +16,32 @@ class DottedNameResolver(_DottedNameResolver): _DottedNameResolver.__init__(self, package) +def text_(s, encoding='latin-1', errors='strict'): + """ If ``s`` is an instance of ``bytes``, return + ``s.decode(encoding, errors)``, otherwise return ``s``""" + if isinstance(s, bytes): + return s.decode(encoding, errors) + return s + + +def bytes_(s, encoding='latin-1', errors='strict'): + """ If ``s`` is an instance of ``str``, return + ``s.encode(encoding, errors)``, otherwise return ``s``""" + if isinstance(s, str): + return s.encode(encoding, errors) + return s + + +def ascii_(s): + """ + If ``s`` is an instance of ``str``, return + ``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')`` + """ + if isinstance(s, str): + s = s.encode('ascii') + return str(s, 'ascii', 'strict') + + def is_nonstr_iter(v): if isinstance(v, str): return False @@ -322,11 +344,11 @@ def object_description(object): (possibly shortened) string representation is returned. """ if isinstance(object, str): - return text_(object) + return object if isinstance(object, int): - return text_(str(object)) + return str(object) if isinstance(object, (bool, float, type(None))): - return text_(str(object)) + return str(object) if isinstance(object, set): return shortrepr(object, '}') if isinstance(object, tuple): @@ -337,26 +359,25 @@ def object_description(object): return shortrepr(object, '}') module = inspect.getmodule(object) if module is None: - return text_('object %s' % str(object)) + return 'object %s' % str(object) modulename = module.__name__ if inspect.ismodule(object): - return text_('module %s' % modulename) + return 'module %s' % modulename if inspect.ismethod(object): oself = getattr(object, '__self__', None) - if oself is None: # pragma: no cover - oself = getattr(object, 'im_self', None) - return text_( - 'method %s of class %s.%s' - % (object.__name__, modulename, oself.__class__.__name__) + return 'method %s of class %s.%s' % ( + object.__name__, + modulename, + oself.__class__.__name__, ) if inspect.isclass(object): dottedname = '%s.%s' % (modulename, object.__name__) - return text_('class %s' % dottedname) + return 'class %s' % dottedname if inspect.isfunction(object): dottedname = '%s.%s' % (modulename, object.__name__) - return text_('function %s' % dottedname) - return text_('object %s' % str(object)) + return 'function %s' % dottedname + return 'object %s' % str(object) def shortrepr(object, closer): @@ -487,11 +508,17 @@ class TopologicalSorter(object): has_after.add(b) if not self.req_before.issubset(has_before): + # avoid circular dependency + from pyramid.exceptions import ConfigurationError + raise ConfigurationError( 'Unsatisfied before dependencies: %s' % (', '.join(sorted(self.req_before - has_before))) ) if not self.req_after.issubset(has_after): + # avoid circular dependency + from pyramid.exceptions import ConfigurationError + raise ConfigurationError( 'Unsatisfied after dependencies: %s' % (', '.join(sorted(self.req_after - has_after))) @@ -512,6 +539,9 @@ class TopologicalSorter(object): del graph[root] if graph: + # avoid circular dependency + from pyramid.exceptions import CyclicDependencyError + # loop in input cycledeps = {} for k, v in graph.items(): @@ -533,8 +563,11 @@ def get_callable_name(name): if it is not. """ try: - return native_(name, 'ascii') + return ascii_(name) except (UnicodeEncodeError, UnicodeDecodeError): + # avoid circular dependency + from pyramid.exceptions import ConfigurationError + msg = ( '`name="%s"` is invalid. `name` must be ascii because it is ' 'used on __name__ of the method' @@ -641,7 +674,7 @@ def takes_one_arg(callee, attr=None, argname=None): class SimpleSerializer(object): def loads(self, bstruct): - return native_(bstruct) + return text_(bstruct) def dumps(self, appstruct): return bytes_(appstruct) -- cgit v1.2.3 From d4ce9d3f915b18425b4ce5224a51a89342270371 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 14 Nov 2018 22:23:51 -0600 Subject: move WIN and PYPY tests into pyramid.util --- src/pyramid/compat.py | 11 ----------- src/pyramid/config/views.py | 8 ++++++-- src/pyramid/testing.py | 4 +--- src/pyramid/util.py | 11 +++++++++++ 4 files changed, 18 insertions(+), 16 deletions(-) delete mode 100644 src/pyramid/compat.py (limited to 'src') diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py deleted file mode 100644 index ec0ca7017..000000000 --- a/src/pyramid/compat.py +++ /dev/null @@ -1,11 +0,0 @@ -import platform - -WIN = platform.system() == 'Windows' - -try: # pragma: no cover - import __pypy__ - - PYPY = True -except BaseException: # pragma: no cover - __pypy__ = None - PYPY = False diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py index 412e30304..ac531ecb2 100644 --- a/src/pyramid/config/views.py +++ b/src/pyramid/config/views.py @@ -33,7 +33,6 @@ from pyramid.interfaces import ( from pyramid import renderers from pyramid.asset import resolve_asset_spec -from pyramid.compat import WIN from pyramid.decorator import reify @@ -54,7 +53,12 @@ from pyramid.url import parse_url_overrides from pyramid.view import AppendSlashNotFoundViewFactory -from pyramid.util import as_sorted_tuple, is_nonstr_iter, TopologicalSorter +from pyramid.util import ( + as_sorted_tuple, + is_nonstr_iter, + TopologicalSorter, + WIN, +) import pyramid.predicates import pyramid.viewderivers diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py index 04497234b..6831ea4e2 100644 --- a/src/pyramid/testing.py +++ b/src/pyramid/testing.py @@ -8,8 +8,6 @@ from zope.interface import implementer, alsoProvides from pyramid.interfaces import IRequest, ISession -from pyramid.compat import PYPY - from pyramid.config import Configurator from pyramid.decorator import reify from pyramid.path import caller_package @@ -28,7 +26,7 @@ from pyramid.threadlocal import get_current_registry, manager from pyramid.i18n import LocalizerRequestMixin from pyramid.request import CallbackMethodsMixin from pyramid.url import URLMethodsMixin -from pyramid.util import InstancePropertyMixin, text_ +from pyramid.util import InstancePropertyMixin, PYPY, text_ from pyramid.view import ViewMethodsMixin diff --git a/src/pyramid/util.py b/src/pyramid/util.py index ab46c91f7..1180fce83 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -2,12 +2,23 @@ from contextlib import contextmanager import functools from hmac import compare_digest import inspect +import platform import weakref from pyramid.path import DottedNameResolver as _DottedNameResolver _marker = object() +WIN = platform.system() == 'Windows' + +try: # pragma: no cover + import __pypy__ + + PYPY = True +except BaseException: # pragma: no cover + __pypy__ = None + PYPY = False + class DottedNameResolver(_DottedNameResolver): def __init__( -- cgit v1.2.3 From 80cce1874f90a73f74d7c9ef8156df3637694387 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 18 Nov 2018 17:24:54 -0600 Subject: clean up docstrings referencing unicode data --- src/pyramid/encode.py | 4 +- src/pyramid/i18n.py | 15 +++--- src/pyramid/response.py | 4 -- src/pyramid/security.py | 4 +- src/pyramid/traversal.py | 132 ++++++++++++++++++++--------------------------- 5 files changed, 68 insertions(+), 91 deletions(-) (limited to 'src') diff --git a/src/pyramid/encode.py b/src/pyramid/encode.py index 11d3a7787..ed8e177b8 100644 --- a/src/pyramid/encode.py +++ b/src/pyramid/encode.py @@ -26,8 +26,8 @@ def quote_plus(val, safe=''): def urlencode(query, doseq=True, quote_via=quote_plus): """ An alternate implementation of Python's stdlib - :func:`urllib.parse.urlencode` function which accepts unicode keys and - values within the ``query`` dict/sequence; all Unicode keys and values are + :func:`urllib.parse.urlencode` function which accepts string keys and + values within the ``query`` dict/sequence; all string keys and values are first converted to UTF-8 before being used to compose the query string. The value of ``query`` must be a sequence of two-tuples diff --git a/src/pyramid/i18n.py b/src/pyramid/i18n.py index 45f528852..112044e47 100644 --- a/src/pyramid/i18n.py +++ b/src/pyramid/i18n.py @@ -45,12 +45,11 @@ class Localizer(object): ``translate`` method accepts three arguments: ``tstring`` (required), ``domain`` (optional) and ``mapping`` (optional). When called, it will translate the ``tstring`` translation - string to a ``unicode`` object using the current locale. If - the current locale could not be determined, the result of - interpolation of the default value is returned. The optional - ``domain`` argument can be used to specify or override the - domain of the ``tstring`` (useful when ``tstring`` is a normal - string rather than a translation string). The optional + string the current locale. If the current locale could not be + determined, the result of interpolation of the default value is + returned. The optional ``domain`` argument can be used to specify + or override the domain of the ``tstring`` (useful when ``tstring`` + is a normal string rather than a translation string). The optional ``mapping`` argument can specify or override the ``tstring`` interpolation mapping, useful when the ``tstring`` argument is a simple string instead of a translation string. @@ -74,11 +73,11 @@ class Localizer(object): def pluralize(self, singular, plural, n, domain=None, mapping=None): """ - Return a Unicode string translation by using two + Return a string translation by using two :term:`message identifier` objects as a singular/plural pair and an ``n`` value representing the number that appears in the message using gettext plural forms support. The ``singular`` - and ``plural`` objects should be unicode strings. There is no + and ``plural`` objects should be strings. There is no reason to use translation string objects as arguments as all metadata is ignored. diff --git a/src/pyramid/response.py b/src/pyramid/response.py index 8a2ba8929..ea4677226 100644 --- a/src/pyramid/response.py +++ b/src/pyramid/response.py @@ -212,8 +212,4 @@ def _guess_type(path): content_type, content_encoding = mimetypes.guess_type(path, strict=False) if content_type is None: content_type = 'application/octet-stream' - # str-ifying content_type is a workaround for a bug in Python 2.7.7 - # on Windows where mimetypes.guess_type returns unicode for the - # content_type. - content_type = str(content_type) return content_type, content_encoding diff --git a/src/pyramid/security.py b/src/pyramid/security.py index f8743e9a7..61819588b 100644 --- a/src/pyramid/security.py +++ b/src/pyramid/security.py @@ -112,7 +112,7 @@ def forget(request): def principals_allowed_by_permission(context, permission): """ Provided a ``context`` (a resource object), and a ``permission`` - (a string or unicode object), if an :term:`authorization policy` is + string, if an :term:`authorization policy` is in effect, return a sequence of :term:`principal` ids that possess the permission in the ``context``. If no authorization policy is in effect, this will return a sequence with the single value @@ -340,7 +340,7 @@ class AuthorizationAPIMixin(object): ``request.context`` attribute. :param permission: Does this request have the given permission? - :type permission: unicode, str + :type permission: str :param context: A resource object or ``None`` :type context: object :returns: Either :class:`pyramid.security.Allowed` or diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 7de4c3f91..72176fc4b 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -57,16 +57,12 @@ def find_resource(resource, path): object supplied to the function as the ``resource`` argument. If an empty string is passed as ``path``, the ``resource`` passed in will be returned. Resource path strings must be escaped in the following - manner: each Unicode path segment must be encoded as UTF-8 and as - each path segment must escaped via Python's :mod:`urllib.quote`. - For example, ``/path/to%20the/La%20Pe%C3%B1a`` (absolute) or - ``to%20the/La%20Pe%C3%B1a`` (relative). The + manner: each path segment must be UTF-8 encoded and escaped via Python's + :mod:`urllib.quote`. For example, ``/path/to%20the/La%20Pe%C3%B1a`` + (absolute) or ``to%20the/La%20Pe%C3%B1a`` (relative). The :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. + which follow these rules (albeit only absolute ones). 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 ``('', @@ -77,11 +73,10 @@ def find_resource(resource, path): traversal will begin at the resource object supplied to the function as the ``resource`` argument. If an empty sequence is passed as ``path``, the ``resource`` passed in itself will be returned. No - URL-quoting or UTF-8-encoding of individual path segments within - the tuple is required (each segment may be any string or unicode - object representing a resource name). Resource path tuples generated by - :func:`pyramid.traversal.resource_path_tuple` can always be - resolved by ``find_resource``. + URL-quoting of individual path segments within the tuple is required + (each segment may be any string representing a resource name). Resource + path tuples generated by :func:`pyramid.traversal.resource_path_tuple` can + always be resolved by ``find_resource``. """ if isinstance(path, str): path = ascii_(path) @@ -126,8 +121,8 @@ def resource_path(resource, *elements): ``/`` character in a path string represents that the path is absolute). Resource path strings returned will be escaped in the following - manner: each unicode path segment will be encoded as UTF-8 and - each path segment will be escaped via Python's :mod:`urllib.quote`. + manner: each path segment will be encoded as UTF-8 and escaped via + Python's :mod:`urllib.quote`. For example, ``/path/to%20the/La%20Pe%C3%B1a``. This function is a logical inverse of @@ -140,7 +135,7 @@ def resource_path(resource, *elements): Each segment in the path string returned will use the ``__name__`` attribute of the resource it represents within the resource tree. Each - of these segments *should* be a unicode or string object (as per the + of these segments *should* be a string (as per the contract of :term:`location`-awareness). However, no conversion or safety checking of resource names is performed. For instance, if one of the resources in your tree has a ``__name__`` which (by error) is a @@ -189,30 +184,30 @@ def traverse(resource, path): :term:`traversal` or :term:`url dispatch`; if the ``resource`` was found via traversal, this is usually a representation of the path segment which directly follows the path to the ``context`` - in the ``path``. The ``view_name`` will be a Unicode object or - the empty string. The ``view_name`` will be the empty string if + in the ``path``. The ``view_name`` will be a string. The + ``view_name`` will be the empty string if there is no element which follows the ``context`` path. An example: if the path passed is ``/foo/bar``, and a resource object is found at ``/foo`` (but not at ``/foo/bar``), the 'view - name' will be ``u'bar'``. If the ``resource`` was found via + name' will be ``'bar'``. If the ``resource`` was found via urldispatch, the view_name will be the name the route found was registered with. - ``subpath``: For a ``resource`` found via :term:`traversal`, this is a sequence of path segments found in the ``path`` that follow - the ``view_name`` (if any). Each of these items is a Unicode - object. If no path segments follow the ``view_name``, the + the ``view_name`` (if any). Each of these items is a string. + If no path segments follow the ``view_name``, the subpath will be the empty sequence. An example: if the path passed is ``/foo/bar/baz/buz``, and a resource object is found at ``/foo`` (but not ``/foo/bar``), the 'view name' will be - ``u'bar'`` and the :term:`subpath` will be ``[u'baz', u'buz']``. + ``'bar'`` and the :term:`subpath` will be ``['baz', 'buz']``. For a ``resource`` found via url dispatch, the subpath will be a sequence of values discerned from ``*subpath`` in the route pattern matched or the empty sequence. - ``traversed``: The sequence of path elements traversed from the root to find the ``context`` object during :term:`traversal`. - Each of these items is a Unicode object. If no path segments + Each of these items is a string. If no path segments were traversed to find the ``context`` object (e.g. if the ``path`` provided is the empty string), the ``traversed`` value will be the empty sequence. If the ``resource`` is a resource found @@ -232,7 +227,7 @@ def traverse(resource, path): - ``virtual_root_path`` -- If :term:`traversal` was used to find the ``resource``, this will be the sequence of path elements traversed to find the ``virtual_root`` resource. Each of these - items is a Unicode object. If no path segments were traversed + items is a string. If no path segments were traversed to find the ``virtual_root`` resource (e.g. if virtual hosting is not in effect), the ``traversed`` value will be the empty list. If url dispatch was used to find the ``resource``, this will be @@ -249,9 +244,9 @@ def traverse(resource, path): object supplied to the function as the ``resource`` argument. If an empty string is passed as ``path``, the ``resource`` passed in will be returned. Resource path strings must be escaped in the following - manner: each Unicode path segment must be encoded as UTF-8 and - each path segment must escaped via Python's :mod:`urllib.quote`. - For example, ``/path/to%20the/La%20Pe%C3%B1a`` (absolute) or + manner: each path segment must be encoded as UTF-8 and escaped via + Python's :mod:`urllib.quote`. For example, + ``/path/to%20the/La%20Pe%C3%B1a`` (absolute) or ``to%20the/La%20Pe%C3%B1a`` (relative). The :func:`pyramid.traversal.resource_path` function generates strings which follow these rules (albeit only absolute ones). @@ -266,26 +261,24 @@ def traverse(resource, path): as the ``resource`` argument. If an empty sequence is passed as ``path``, the ``resource`` passed in itself will be returned. No URL-quoting or UTF-8-encoding of individual path segments within - the tuple is required (each segment may be any string or unicode - object representing a resource name). + the tuple is required (each segment may be any string representing + a resource name). - Explanation of the conversion of ``path`` segment values to - Unicode during traversal: Each segment is URL-unquoted, and - decoded into Unicode. Each segment is assumed to be encoded using - the UTF-8 encoding (or a subset, such as ASCII); a + Explanation of the decoding of ``path`` segment values during traversal: + Each segment is URL-unquoted, and UTF-8 decoded. 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. As a result of this process, the return values ``view_name``, each element in the ``subpath``, each element in ``traversed``, and each element in - the ``virtual_root_path`` will be Unicode as opposed to a string, - and will be URL-decoded. + the ``virtual_root_path`` will be decoded strings. """ 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 + # the traverser factory expects PATH_INFO to be a string and it + # expects path segments to be utf-8 and # urlencoded (it's the same traverser which accepts PATH_INFO # from user agents; user agents always send strings). if path: @@ -346,7 +339,7 @@ def resource_path_tuple(resource, *elements): Each segment in the path tuple returned will equal the ``__name__`` attribute of the resource it represents within the resource tree. Each - of these segments *should* be a unicode or string object (as per the + of these segments *should* be a string (as per the contract of :term:`location`-awareness). However, no conversion or safety checking of resource names is performed. For instance, if one of the resources in your tree has a ``__name__`` which (by error) is a @@ -428,11 +421,10 @@ def traversal_path(path): """ Variant of :func:`pyramid.traversal.traversal_path_info` suitable for decoding paths that are URL-encoded. - If this function is passed a Unicode object instead of a sequence of - bytes as ``path``, 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:`UnicodeEncodeError` will be raised if the Unicode cannot be + If this function is passed a string, it *must* directly encodeable to + ASCII. For example, '/foo' will work but '/' (a + string object with characters that cannot be encoded to ascii) will + not. A :exc:`UnicodeEncodeError` will be raised if the string cannot be encoded directly to ASCII. """ if isinstance(path, str): @@ -450,18 +442,11 @@ def traversal_path_info(path): already-URL-decoded ``str`` type as if it had come to us from an upstream WSGI server as the ``PATH_INFO`` environ variable. - The ``path`` is first decoded to from its WSGI representation to Unicode; - it is decoded differently depending on platform: - - - On Python 2, ``path`` is decoded to Unicode from bytes using the UTF-8 - decoding directly; a :exc:`pyramid.exc.URLDecodeError` is raised if a the - URL cannot be decoded. - - - On Python 3, as per the PEP 3333 spec, ``path`` is first 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`` is first decoded to from its WSGI representation to text. + Per the PEP 3333 spec, ``path`` is first 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`` is split on slashes, creating a list of segments. If a segment name is empty or if it is ``.``, it is ignored. If a segment @@ -476,31 +461,31 @@ def traversal_path_info(path): ``/foo/bar/baz`` - (u'foo', u'bar', u'baz') + ('foo', 'bar', 'baz') ``foo/bar/baz`` - (u'foo', u'bar', u'baz') + ('foo', 'bar', 'baz') ``/foo/bar/baz/`` - (u'foo', u'bar', u'baz') + ('foo', 'bar', 'baz') ``/foo//bar//baz/`` - (u'foo', u'bar', u'baz') + ('foo', 'bar', 'baz') ``/foo/bar/baz/..`` - (u'foo', u'bar') + ('foo', 'bar') ``/my%20archives/hello`` - (u'my archives', u'hello') + ('my archives', 'hello') ``/archives/La%20Pe%C3%B1a`` - (u'archives', u'') + ('archives', '') .. note:: @@ -555,13 +540,10 @@ def quote_path_segment(segment, safe=PATH_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. + ``segment`` passed in is a bytes object, it is decoded as a UTF-8 string. + The result is then URL-quoted using Python's ``urllib.quote``. + If the segment passed in is not bytes or a string, an error will be + raised. The return value of ``quote_path_segment`` is always a string. You may pass a string of characters that need not be encoded as the ``safe`` argument to this function. This corresponds to the @@ -582,14 +564,14 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): """ # 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 + # in this module-scope dictionary with the original string 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 (str, bytes): segment = str(segment) + return _segment_cache[(segment, safe)] + except KeyError: result = url_quote(text_(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) -- cgit v1.2.3 From 8f2fbe31c6c1aaa1b7792249ebeb984946e7a5e1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 18 Nov 2018 23:29:18 -0600 Subject: stop using u-prefix strings --- src/pyramid/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 1180fce83..cad8142dd 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -338,14 +338,14 @@ def object_description(object): usually involving a Python dotted name. For example: >>> object_description(None) - u'None' + 'None' >>> from xml.dom import minidom >>> object_description(minidom) - u'module xml.dom.minidom' + 'module xml.dom.minidom' >>> object_description(minidom.Attr) - u'class xml.dom.minidom.Attr' + 'class xml.dom.minidom.Attr' >>> object_description(minidom.Attr.appendChild) - u'method appendChild of class xml.dom.minidom.Attr' + 'method appendChild of class xml.dom.minidom.Attr' If this method cannot identify the type of the object, a generic description ala ``object `` will be returned. -- cgit v1.2.3 From e0fcb74e9d0c347a2c1627d07007f1d566dc7e17 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 18 Nov 2018 23:43:18 -0600 Subject: fix up some more docstrings --- src/pyramid/i18n.py | 2 +- src/pyramid/traversal.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/pyramid/i18n.py b/src/pyramid/i18n.py index 112044e47..a20503be2 100644 --- a/src/pyramid/i18n.py +++ b/src/pyramid/i18n.py @@ -45,7 +45,7 @@ class Localizer(object): ``translate`` method accepts three arguments: ``tstring`` (required), ``domain`` (optional) and ``mapping`` (optional). When called, it will translate the ``tstring`` translation - string the current locale. If the current locale could not be + string using the current locale. If the current locale could not be determined, the result of interpolation of the default value is returned. The optional ``domain`` argument can be used to specify or override the domain of the ``tstring`` (useful when ``tstring`` diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 72176fc4b..92436e403 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -62,7 +62,7 @@ def find_resource(resource, path): (absolute) or ``to%20the/La%20Pe%C3%B1a`` (relative). The :func:`pyramid.traversal.resource_path` function generates strings which follow these rules (albeit only absolute ones). The text may not - have any nonascii characters in it. + have any non-ASCII 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 ``('', @@ -190,8 +190,10 @@ def traverse(resource, path): example: if the path passed is ``/foo/bar``, and a resource object is found at ``/foo`` (but not at ``/foo/bar``), the 'view name' will be ``'bar'``. If the ``resource`` was found via - urldispatch, the view_name will be the name the route found was - registered with. + url dispatch, the ``view_name`` will be the empty string unless + the ``traverse`` predicate was specified or the ``*traverse`` route + pattern was used, at which point normal traversal rules dictate the + result. - ``subpath``: For a ``resource`` found via :term:`traversal`, this is a sequence of path segments found in the ``path`` that follow @@ -421,9 +423,9 @@ def traversal_path(path): """ Variant of :func:`pyramid.traversal.traversal_path_info` suitable for decoding paths that are URL-encoded. - If this function is passed a string, it *must* directly encodeable to + If this function is passed a string, it *must* be directly encodeable to ASCII. For example, '/foo' will work but '/' (a - string object with characters that cannot be encoded to ascii) will + string object with characters that cannot be encoded to ASCII) will not. A :exc:`UnicodeEncodeError` will be raised if the string cannot be encoded directly to ASCII. """ -- cgit v1.2.3 From 336e91d824ceb55a113b434be4957d1a5baa11a8 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 18 Nov 2018 23:47:15 -0600 Subject: fix moar strings --- src/pyramid/traversal.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 92436e403..3dc37613e 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -444,11 +444,11 @@ def traversal_path_info(path): already-URL-decoded ``str`` type as if it had come to us from an upstream WSGI server as the ``PATH_INFO`` environ variable. - The ``path`` is first decoded to from its WSGI representation to text. - Per the PEP 3333 spec, ``path`` is first encoded to bytes using the + The ``path`` is first decoded from its WSGI representation to text. + Per the :pep:`3333` spec, ``path`` is first 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. + raised if the URL cannot be decoded. The ``path`` is split on slashes, creating a list of segments. If a segment name is empty or if it is ``.``, it is ignored. If a segment @@ -544,7 +544,7 @@ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE): the string ``__name__`` attribute of a resource) as a string. If the ``segment`` passed in is a bytes object, it is decoded as a UTF-8 string. The result is then URL-quoted using Python's ``urllib.quote``. - If the segment passed in is not bytes or a string, an error will be + If the segment passed in is not bytes nor a string, an error will be raised. The return value of ``quote_path_segment`` is always a string. You may pass a string of characters that need not be encoded as -- cgit v1.2.3 From cfaedc5e247af279059ab93fea4c9d7a27ddcf8a Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 19 Nov 2018 02:46:18 -0800 Subject: Standardize casing of URL when it is an acronym --- src/pyramid/traversal.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py index 3dc37613e..9ed5754b7 100644 --- a/src/pyramid/traversal.py +++ b/src/pyramid/traversal.py @@ -171,17 +171,17 @@ def traverse(resource, path): A definition of each value in the returned dictionary: - ``context``: The :term:`context` (a :term:`resource` object) found - via traversal or url dispatch. If the ``path`` passed in is the + via traversal or URL dispatch. If the ``path`` passed in is the empty string, the value of the ``resource`` argument passed to this function is returned. - ``root``: The resource object at which :term:`traversal` begins. - If the ``resource`` passed in was found via url dispatch or if the + If the ``resource`` passed in was found via URL dispatch or if the ``path`` passed in was relative (non-absolute), the value of the ``resource`` argument passed to this function is returned. - ``view_name``: The :term:`view name` found during - :term:`traversal` or :term:`url dispatch`; if the ``resource`` was + :term:`traversal` or :term:`URL dispatch`; if the ``resource`` was found via traversal, this is usually a representation of the path segment which directly follows the path to the ``context`` in the ``path``. The ``view_name`` will be a string. The @@ -190,7 +190,7 @@ def traverse(resource, path): example: if the path passed is ``/foo/bar``, and a resource object is found at ``/foo`` (but not at ``/foo/bar``), the 'view name' will be ``'bar'``. If the ``resource`` was found via - url dispatch, the ``view_name`` will be the empty string unless + URL dispatch, the ``view_name`` will be the empty string unless the ``traverse`` predicate was specified or the ``*traverse`` route pattern was used, at which point normal traversal rules dictate the result. @@ -203,7 +203,7 @@ def traverse(resource, path): passed is ``/foo/bar/baz/buz``, and a resource object is found at ``/foo`` (but not ``/foo/bar``), the 'view name' will be ``'bar'`` and the :term:`subpath` will be ``['baz', 'buz']``. - For a ``resource`` found via url dispatch, the subpath will be a + For a ``resource`` found via URL dispatch, the subpath will be a sequence of values discerned from ``*subpath`` in the route pattern matched or the empty sequence. @@ -213,7 +213,7 @@ def traverse(resource, path): were traversed to find the ``context`` object (e.g. if the ``path`` provided is the empty string), the ``traversed`` value will be the empty sequence. If the ``resource`` is a resource found - via :term:`url dispatch`, traversed will be None. + via :term:`URL dispatch`, traversed will be None. - ``virtual_root``: A resource object representing the 'virtual' root of the resource tree being traversed during :term:`traversal`. @@ -232,7 +232,7 @@ def traverse(resource, path): items is a string. If no path segments were traversed to find the ``virtual_root`` resource (e.g. if virtual hosting is not in effect), the ``traversed`` value will be the empty list. - If url dispatch was used to find the ``resource``, this will be + If URL dispatch was used to find the ``resource``, this will be ``None``. If the path cannot be resolved, a :exc:`KeyError` will be raised. -- cgit v1.2.3 From f6b0ae2a32d6bcd40246ef1ec3abb16ce65324dc Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 23 Nov 2018 15:55:00 -0600 Subject: always use compare_digest --- src/pyramid/util.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/pyramid/util.py b/src/pyramid/util.py index cad8142dd..e552b37de 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -301,7 +301,7 @@ class WeakOrderedSet(object): return self._items[oid]() -def strings_differ(string1, string2, compare_digest=compare_digest): +def strings_differ(string1, string2): """Check whether two strings differ while avoiding timing attacks. This function returns True if the given strings differ and False @@ -325,11 +325,7 @@ def strings_differ(string1, string2, compare_digest=compare_digest): left = string2 right = string2 - if compare_digest is not None: - invalid_bits += not compare_digest(left, right) - else: - for a, b in zip(left, right): - invalid_bits += a != b + invalid_bits += not compare_digest(left, right) return invalid_bits != 0 -- cgit v1.2.3